TKK_E32230176/Source-Code-Web/lib/widgets/webcam_view.dart

108 lines
2.8 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/mqtt_provider.dart';
class WebcamView extends StatefulWidget {
const WebcamView({super.key});
@override
State<WebcamView> createState() => _WebcamViewState();
}
class _WebcamViewState extends State<WebcamView> {
Timer? _refreshTimer;
@override
void initState() {
super.initState();
_startTimer();
}
void _startTimer() {
_refreshTimer = Timer.periodic(const Duration(seconds: 2), (timer) {
if (mounted) {
Provider.of<MQTTProvider>(context, listen: false).requestWebcamFrame();
}
});
}
@override
void dispose() {
_refreshTimer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Consumer<MQTTProvider>(
builder: (context, provider, child) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: provider.webcamImage != null &&
provider.webcamImage!.isNotEmpty
? Image.memory(
base64Decode(provider.webcamImage!),
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return _buildPlaceholder(context, 'Error loading image');
},
)
: _buildPlaceholder(context, 'Menunggu gambar...'),
),
);
},
);
}
Widget _buildPlaceholder(BuildContext context, String message) {
return Container(
height: 300,
width: double.infinity,
color: Colors.grey.shade200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.videocam_off,
size: 64,
color: Colors.grey.shade400,
),
const SizedBox(height: 16),
Text(
message,
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
),
),
const SizedBox(height: 8),
Consumer<MQTTProvider>(
builder: (context, provider, child) {
return Text(
'Deteksi kehadiran: ${provider.detectionCount}',
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 12,
),
);
},
),
],
),
);
}
}