import 'package:flutter/material.dart'; import 'package:my_app/appeditor/custom/AppEditorWidgetContext.dart'; Widget buildCustomWidget(BuildContext context, AppEditorWidgetContext app) { return SensorMonitor(app: app); } class SensorMonitor extends StatefulWidget { const SensorMonitor({super.key, required this.app}); final AppEditorWidgetContext app; @override State createState() => _SensorMonitorState(); } class _SensorMonitorState extends State { late String _variable; late Stream _samples; bool _busy = false; void _bind() { _variable = widget.app.params['variable'] as String? ?? 'sensorData'; _samples = widget.app.watchVar(_variable); } @override void initState() { super.initState(); _bind(); } @override void didUpdateWidget(covariant SensorMonitor oldWidget) { super.didUpdateWidget(oldWidget); if (_variable != (widget.app.params['variable'] as String? ?? 'sensorData') || !identical(oldWidget.app, widget.app)) _bind(); } Future _run(String name) async { final app = widget.app; final variable = _variable; setState(() => _busy = true); try { await app.runAction(name); // Sensor stop preserves its last sample. Clear only this output variable // so this monitor does not display an old sample as a live measurement. if (name == 'stopSensor' && app.mounted) await app.removeVar(variable); } catch (_) { app.showMessage('اجرای عملکرد سنسور ممکن نشد'); } finally { if (mounted) setState(() => _busy = false); } } String _number(dynamic value) => value is num && value.toDouble().isFinite ? value.toStringAsFixed(3) : '—'; @override Widget build(BuildContext context) => StreamBuilder( stream: _samples, builder: (context, snapshot) { final data = snapshot.data is Map ? snapshot.data as Map : const {}; final status = data['status']; final active = status == 'active'; final label = switch (status) { 'starting' => 'در حال شروع', 'active' => 'دریافت داده', 'paused' => 'دریافت مکث شده', 'error' => 'خطای سنسور: ${data['error'] ?? 'نامشخص'}', _ => 'دریافت شروع نشده یا متوقف شده است', }; return Card(child: Padding( padding: const EdgeInsets.all(16), child: Column(mainAxisSize: MainAxisSize.min, children: [ Text(widget.app.params['title'] as String? ?? 'دادهٔ سنسور', style: Theme.of(context).textTheme.titleLarge), const SizedBox(height: 8), Text(label, textAlign: TextAlign.center), if (data['simulated'] == true) const Text('دادهٔ شبیه‌سازی‌شده'), Text('نوع: ${data['sensor'] ?? '—'}'), if (active) ...[ Text('x: ${_number(data['x'])} y: ${_number(data['y'])} z: ${_number(data['z'])}', textDirection: TextDirection.ltr), Text('magnitude: ${_number(data['magnitude'])}', textDirection: TextDirection.ltr), Text('زمان نمونه: ${data['timestamp'] ?? '—'}'), ], const SizedBox(height: 8), Wrap(spacing: 12, children: [ ElevatedButton(onPressed: !_busy && widget.app.hasAction('startSensor') ? () => _run('startSensor') : null, child: const Text('شروع')), OutlinedButton(onPressed: !_busy && widget.app.hasAction('stopSensor') ? () => _run('stopSensor') : null, child: const Text('توقف')), ]), ]), )); }, ); }