Files
notas/lib/widgets/sync_status_indicator.dart
T

188 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:notas/widgets/sync_status.dart';
class SyncStatusIndicator extends StatelessWidget {
const SyncStatusIndicator({
required this.status,
this.progress,
this.detailMessage,
this.errorMessage,
this.onTap,
super.key,
});
final SyncStatus status;
final double? progress;
final String? detailMessage;
final String? errorMessage;
final VoidCallback? onTap;
Widget _buildIndicator(Widget child) {
if (onTap == null) {
return child;
}
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: child,
),
);
}
String _messageForStatus() {
switch (status) {
case SyncStatus.idle:
return 'Sincronización en espera';
case SyncStatus.preparing:
return detailMessage ?? 'Preparando sincronización...';
case SyncStatus.encrypting:
return detailMessage ?? 'Encriptando datos para subir...';
case SyncStatus.uploading:
return detailMessage ?? 'Subiendo datos al servidor...';
case SyncStatus.waitingResponse:
return detailMessage ?? 'Esperando respuesta del servidor...';
case SyncStatus.decrypting:
return detailMessage ?? 'Desencriptando datos recibidos...';
case SyncStatus.syncing:
return detailMessage ?? 'Sincronizando...';
case SyncStatus.synced:
return detailMessage ?? 'Sincronizado';
case SyncStatus.error:
return errorMessage ?? detailMessage ?? 'Error al sincronizar';
}
}
Widget _buildStatusBadge({
required IconData icon,
required Color color,
required bool determinate,
}) {
final double ringProgress = (progress ?? 0).clamp(0.0, 1.0);
return SizedBox(
width: 18,
height: 18,
child: Stack(
alignment: Alignment.center,
children: [
SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
value: determinate ? ringProgress : null,
backgroundColor: color.withValues(alpha: 0.16),
valueColor: AlwaysStoppedAnimation<Color>(color),
),
),
Icon(icon, size: 10, color: color),
],
),
);
}
@override
Widget build(BuildContext context) {
switch (status) {
case SyncStatus.idle:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
const Icon(Icons.cloud_outlined, size: 16, color: Colors.white38),
),
);
case SyncStatus.preparing:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.sync,
color: const Color.fromARGB(255, 165, 165, 165),
determinate: false,
),
),
);
case SyncStatus.encrypting:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.cloud_upload_outlined,
color: const Color.fromARGB(255, 109, 191, 255),
determinate: true,
),
),
);
case SyncStatus.uploading:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.cloud_upload,
color: const Color.fromARGB(255, 98, 190, 255),
determinate: false,
),
),
);
case SyncStatus.waitingResponse:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.cloud_sync_outlined,
color: const Color.fromARGB(255, 150, 150, 150),
determinate: false,
),
),
);
case SyncStatus.decrypting:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.cloud_download_outlined,
color: const Color.fromARGB(255, 154, 194, 112),
determinate: false,
),
),
);
case SyncStatus.syncing:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
_buildStatusBadge(
icon: Icons.sync,
color: const Color.fromARGB(255, 150, 150, 150),
determinate: false,
),
),
);
case SyncStatus.synced:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
const Icon(Icons.check_circle, size: 16, color: Colors.green),
),
);
case SyncStatus.error:
return Tooltip(
message: _messageForStatus(),
child: _buildIndicator(
const Icon(Icons.error, size: 16, color: Colors.red),
),
);
}
}
}