TimeZone support

This commit is contained in:
2026-03-21 20:30:37 -05:00
parent 64f6024b4e
commit 06b71d6caf
7 changed files with 295 additions and 378 deletions

View File

@@ -5,6 +5,7 @@ import 'package:blind_master/BlindMasterResources/blindmaster_progress_indicator
import 'package:blind_master/BlindMasterResources/error_snackbar.dart';
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
import 'package:blind_master/BlindMasterResources/text_inputs.dart';
import 'package:blind_master/BlindMasterResources/timezone_picker.dart';
import 'package:blind_master/BlindMasterScreens/schedules_screen.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -38,6 +39,8 @@ class _PeripheralScreenState extends State<PeripheralScreen> {
bool _movementPending = false;
bool _awaitingDeviceWake = false;
String? _deviceTimezone;
final _peripheralRenameController = TextEditingController();
void getImage() {
@@ -360,9 +363,28 @@ class _PeripheralScreenState extends State<PeripheralScreen> {
if (response.statusCode != 200) throw Exception("Server Error");
final body = json.decode(response.body);
if (!mounted) return;
setState(() => batterySoc = body['battery_soc'] as int?);
setState(() {
batterySoc = body['battery_soc'] as int?;
_deviceTimezone = body['timezone'] as String?;
});
} catch (e) {
// Battery SOC is non-critical; swallow silently
// Non-critical; swallow silently
}
}
Future<void> updateDeviceTimezone(String timezone) async {
try {
final response = await securePost(
{'deviceId': widget.deviceId, 'timezone': timezone},
'update_device_timezone',
);
if (response == null) throw Exception("Auth Error");
if (response.statusCode != 200) throw Exception("Server Error");
if (!mounted) return;
setState(() => _deviceTimezone = timezone);
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
}
}
@@ -442,47 +464,67 @@ class _PeripheralScreenState extends State<PeripheralScreen> {
}
void rename() {
String? dialogTimezone = _deviceTimezone;
showDialog(
context: context,
builder: (BuildContext dialogContext) {
return AlertDialog(
title: Text(
widget.isSinglePort ? "Rename Device" : "Rename Peripheral",
style: GoogleFonts.aBeeZee(),
),
content: BlindMasterMainInput(
widget.isSinglePort ? "New Device Name" : "New Peripheral Name",
controller: _peripheralRenameController,
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: () {
Navigator.of(dialogContext).pop();
},
child: const Text(
"Cancel",
style: TextStyle(color: Colors.red),
)
return StatefulBuilder(
builder: (context, setDialogState) {
return AlertDialog(
title: Text(
widget.isSinglePort ? "Rename Device" : "Rename Peripheral",
style: GoogleFonts.aBeeZee(),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
BlindMasterMainInput(
widget.isSinglePort
? "New Device Name (blank to keep current)"
: "New Peripheral Name (blank to keep current)",
controller: _peripheralRenameController,
),
if (widget.isSinglePort) ...[
const SizedBox(height: 16),
TimezonePicker(
value: dialogTimezone,
label: 'Device Timezone (blank to keep current)',
onChanged: (tz) => setDialogState(() => dialogTimezone = tz),
),
],
],
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: const Text(
"Cancel",
style: TextStyle(color: Colors.red),
),
),
ElevatedButton(
onPressed: () {
final newName = _peripheralRenameController.text.trim();
if (widget.isSinglePort) {
if (newName.isNotEmpty) updateDeviceName(newName);
if (dialogTimezone != null) updateDeviceTimezone(dialogTimezone!);
} else {
if (newName.isNotEmpty) updatePeriphName(newName, widget.peripheralId);
}
Navigator.of(dialogContext).pop();
},
child: const Text("Confirm"),
),
],
),
ElevatedButton(
onPressed: () {
if (widget.isSinglePort) {
updateDeviceName(_peripheralRenameController.text);
} else {
updatePeriphName(_peripheralRenameController.text, widget.peripheralId);
}
Navigator.of(dialogContext).pop();
},
child: const Text("Confirm")
)
],
)
],
);
},
);
}
},
);
}