lodowka/lib/main.dart
Krzysztof Famulski b89e20ba2c Initial commit
2025-07-13 20:02:25 +02:00

1048 lines
36 KiB
Dart

import 'dart:convert';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:workmanager/workmanager.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:developer' as dev;
const _channelId = 'alert_channel';
const _channelName = 'Alerty';
const _channelDescription = 'Alerty z API (lodówka Ubibot)';
final _notifs = FlutterLocalNotificationsPlugin();
Future<void> _ensureNotificationChannel() async {
final android = _notifs.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
await android?.createNotificationChannel(
const AndroidNotificationChannel(
_channelId,
_channelName,
description: _channelDescription,
importance: Importance.max,
),
);
}
NotificationDetails get _alertDetails => const NotificationDetails(
android: AndroidNotificationDetails(
_channelId,
_channelName,
channelDescription: _channelDescription,
importance: Importance.max,
priority: Priority.high,
),
);
@pragma('vm:entry-point')
void callbackDispatcher() {
WidgetsFlutterBinding.ensureInitialized();
Workmanager().executeTask((taskName, _inputData) async {
const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
await _notifs.initialize(
const InitializationSettings(android: initAndroid),
);
await _ensureNotificationChannel();
try {
final prefs = await SharedPreferences.getInstance();
final url = prefs.getString('APIURL') ?? '';
final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
final response =
await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
if (response.statusCode == 200) {
final data = json.decode(response.body);
final field8 = data['channel']?['last_values'] != null
? json.decode(data['channel']['last_values'])['field8']
: null;
if (field8 != null && field8['value'] != null) {
final double temp = field8['value'].toDouble();
if (temp > threshold) {
await _notifs.show(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
'⚠️ ALERT',
'Temperatura wzrosła powyżej progu: $temp°C > $threshold°C',
_alertDetails,
);
}
}
}
} catch (e) {
await _notifs.show(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
'Błąd API',
e.toString(),
_alertDetails,
);
}
return true;
});
}
Future<void> main() async {
dev.log('starting...', name: 'lodowka_ubibot');
WidgetsFlutterBinding.ensureInitialized();
final prefs = await SharedPreferences.getInstance();
await prefs.setString(
'APIURL',
'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
);
const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
await _notifs.initialize(const InitializationSettings(android: initAndroid));
if (Platform.isAndroid) {
final android = _notifs.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
final granted = await android?.requestNotificationsPermission();
if (granted == null || !granted) {
print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
}
}
await _ensureNotificationChannel();
await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
await Workmanager().registerPeriodicTask(
'checkApiPeriodic',
'checkApi',
frequency: const Duration(minutes: 15),
existingWorkPolicy: ExistingWorkPolicy.keep,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _controller = TextEditingController();
String _field8Value = '';
double _threshold = 5.0;
@override
void initState() {
super.initState();
_loadSettingsAndFetch();
}
Future<void> _loadSettingsAndFetch() async {
final prefs = await SharedPreferences.getInstance();
final url = prefs.getString('APIURL') ?? '';
_threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
_controller.text = url;
await _fetchField8(url);
}
Future<void> _saveApiUrl(String text) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString("APIURL", text);
}
Future<void> _saveThreshold() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setDouble("TEMP_THRESHOLD", _threshold);
}
Future<void> _fetchField8([String? customUrl]) async {
setState(() {
_field8Value = 'Ładowanie…';
});
try {
final prefs = await SharedPreferences.getInstance();
final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
final url = (customUrl ?? _controller.text).trim();
if (url.isEmpty) {
setState(() => _field8Value = 'Brak URL.');
return;
}
final response =
await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
if (response.statusCode == 200) {
final data = json.decode(response.body);
final field8 = data['channel']?['last_values'] != null
? json.decode(data['channel']['last_values'])['field8']
: null;
if (field8 != null && field8['value'] != null) {
final double temp = field8['value'].toDouble();
setState(() => _field8Value =
'Temperatura w lodówce: $temp °C');
// if (temp > threshold) {
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// '⚠️ ALERT',
// 'Temperatura wzrosła powyżej progu: $temp°C < ${threshold}°C',
// _alertDetails,
// );
// }
} else {
setState(() => _field8Value = 'Brak danych field8.');
}
} else {
setState(() => _field8Value = 'Błąd: ${response.statusCode}');
}
} catch (e) {
setState(() => _field8Value = 'Wyjątek: $e');
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'API Alert App',
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true),
home: Scaffold(
appBar: AppBar(
title: const Text('UbiBot - powiadomienia'),
centerTitle: true,
backgroundColor: Colors.blue,
),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'API URL',
),
onChanged: _saveApiUrl,
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
children: [
const Text(
'Próg temperatury (°C)',
style: TextStyle(fontSize: 16),
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {
setState(() {
_threshold =
(_threshold - 0.1).clamp(-100.0, 100.0);
});
_saveThreshold();
},
icon: const Icon(Icons.remove),
),
Text(
_threshold.toStringAsFixed(1),
style: const TextStyle(fontSize: 20),
),
IconButton(
onPressed: () {
setState(() {
_threshold =
(_threshold + 0.1).clamp(-100.0, 100.0);
});
_saveThreshold();
},
icon: const Icon(Icons.add),
),
],
),
],
),
),
ElevatedButton(
onPressed: () => _fetchField8(),
child: const Text('Sprawdź teraz'),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_field8Value,
style: const TextStyle(fontSize: 20),
),
),
],
),
),
),
),
);
}
}
// import 'dart:convert';
// import 'dart:io' show Platform;
//
// import 'package:flutter/material.dart';
// import 'package:flutter/foundation.dart';
// import 'package:http/http.dart' as http;
// import 'package:workmanager/workmanager.dart';
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:shared_preferences/shared_preferences.dart';
// import 'dart:developer' as dev;
//
// const _channelId = 'alert_channel';
// const _channelName = 'Alerty';
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
// final _notifs = FlutterLocalNotificationsPlugin();
//
// Future<void> _ensureNotificationChannel() async {
// final android = _notifs.resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// await android?.createNotificationChannel(
// const AndroidNotificationChannel(
// _channelId,
// _channelName,
// description: _channelDescription,
// importance: Importance.max,
// ),
// );
// }
//
// NotificationDetails get _alertDetails => const NotificationDetails(
// android: AndroidNotificationDetails(
// _channelId,
// _channelName,
// channelDescription: _channelDescription,
// importance: Importance.max,
// priority: Priority.high,
// ),
// );
//
// @pragma('vm:entry-point')
// void callbackDispatcher() {
// WidgetsFlutterBinding.ensureInitialized();
// Workmanager().executeTask((taskName, _inputData) async {
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// await _notifs.initialize(
// const InitializationSettings(android: initAndroid),
// );
//
// await _ensureNotificationChannel();
//
// try {
// final prefs = await SharedPreferences.getInstance();
// final url = prefs.getString('APIURL') ?? '';
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
//
// final response =
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
//
// if (response.statusCode == 200) {
// final data = json.decode(response.body);
// final field8 = data['channel']?['last_values'] != null
// ? json.decode(data['channel']['last_values'])['field8']
// : null;
//
// if (field8 != null && field8['value'] != null) {
// final double temp = field8['value'].toDouble();
// if (temp > threshold) {
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// '⚠️ ALERT',
// 'Temperatura wzrosła powyżej progu: $temp°C > $threshold°C',
// _alertDetails,
// );
// }
// }
// }
// } catch (e) {
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// 'Błąd API',
// e.toString(),
// _alertDetails,
// );
// }
//
// return true;
// });
// }
//
// Future<void> main() async {
// dev.log('starting...', name: 'lodowka_ubibot');
// WidgetsFlutterBinding.ensureInitialized();
//
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString(
// 'APIURL',
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
// );
//
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
//
// if (Platform.isAndroid) {
// final android = _notifs.resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// final granted = await android?.requestNotificationsPermission();
// if (granted == null || !granted) {
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
// }
// }
//
// await _ensureNotificationChannel();
//
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
// await Workmanager().registerPeriodicTask(
// 'checkApiPeriodic',
// 'checkApi',
// frequency: const Duration(minutes: 15),
// existingWorkPolicy: ExistingWorkPolicy.keep,
// );
//
// runApp(const MyApp());
// }
//
// class MyApp extends StatefulWidget {
// const MyApp({super.key});
//
// @override
// State<MyApp> createState() => _MyAppState();
// }
//
// class _MyAppState extends State<MyApp> {
// final TextEditingController _controller = TextEditingController();
// final TextEditingController _thresholdController = TextEditingController();
// String _field8Value = '';
//
// @override
// void initState() {
// super.initState();
// _loadSettingsAndFetch();
// }
//
// Future<void> _loadSettingsAndFetch() async {
// final prefs = await SharedPreferences.getInstance();
// final url = prefs.getString('APIURL') ?? '';
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
//
// _controller.text = url;
// _thresholdController.text = threshold.toString();
//
// await _fetchField8(url);
// }
//
// Future<void> _saveApiUrl(String text) async {
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString("APIURL", text);
// }
//
// Future<void> _saveThreshold(String text) async {
// final prefs = await SharedPreferences.getInstance();
// final value = double.tryParse(text);
// if (value != null) {
// await prefs.setDouble("TEMP_THRESHOLD", value);
// }
// }
//
// Future<void> _fetchField8([String? customUrl]) async {
// setState(() {
// _field8Value = 'Ładowanie…';
// });
//
// try {
// final prefs = await SharedPreferences.getInstance();
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
// final url = (customUrl ?? _controller.text).trim();
//
// if (url.isEmpty) {
// setState(() => _field8Value = 'Brak URL.');
// return;
// }
//
// final response =
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
//
// if (response.statusCode == 200) {
// final data = json.decode(response.body);
// final field8 = data['channel']?['last_values'] != null
// ? json.decode(data['channel']['last_values'])['field8']
// : null;
//
// if (field8 != null && field8['value'] != null) {
// final double temp = field8['value'].toDouble();
// setState(() => _field8Value =
// 'Temperatura zewnętrzna (field8): $temp °C');
//
// if (temp < threshold) {
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// '⚠️ ALERT',
// 'Temperatura spadła poniżej progu: $temp°C < ${threshold}°C',
// _alertDetails,
// );
// }
// } else {
// setState(() => _field8Value = 'Brak danych field8.');
// }
// } else {
// setState(() => _field8Value = 'Błąd: ${response.statusCode}');
// }
// } catch (e) {
// setState(() => _field8Value = 'Wyjątek: $e');
// }
// }
//
// @override
// void dispose() {
// _controller.dispose();
// _thresholdController.dispose();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return MaterialApp(
// title: 'API Alert App',
// debugShowCheckedModeBanner: false,
// theme: ThemeData(useMaterial3: true),
// home: Scaffold(
// body: SafeArea(
// child: SingleChildScrollView(
// child: Column(
// children: [
// const Padding(
// padding: EdgeInsets.all(16.0),
// child: Text('Aplikacja nasłuchuje alertów…'),
// ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: TextField(
// controller: _controller,
// decoration: const InputDecoration(
// border: OutlineInputBorder(),
// labelText: 'API URL',
// ),
// onChanged: _saveApiUrl,
// ),
// ),
// Padding(
// padding:
// const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
// child: TextField(
// controller: _thresholdController,
// decoration: const InputDecoration(
// labelText: 'Próg temperatury (°C)',
// border: OutlineInputBorder(),
// ),
// keyboardType:
// const TextInputType.numberWithOptions(decimal: true),
// onChanged: _saveThreshold,
// ),
// ),
// ElevatedButton(
// onPressed: () => _fetchField8(),
// child: const Text('Sprawdź teraz'),
// ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: Text(
// _field8Value,
// style: const TextStyle(fontSize: 16),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }
// import 'dart:convert';
// import 'dart:io' show Platform;
//
// import 'package:flutter/material.dart';
// import 'package:flutter/foundation.dart';
// import 'package:http/http.dart' as http;
// import 'package:workmanager/workmanager.dart';
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:shared_preferences/shared_preferences.dart';
// import 'dart:developer' as dev;
//
// // ─────────────────────────────────────────────────────────────
// // Stałe / współdzielone
// // ─────────────────────────────────────────────────────────────
// const _channelId = 'alert_channel';
// const _channelName = 'Alerty';
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
// final _notifs = FlutterLocalNotificationsPlugin();
//
// Future<void> _ensureNotificationChannel() async {
// final android = _notifs.resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// await android?.createNotificationChannel(
// const AndroidNotificationChannel(
// _channelId,
// _channelName,
// description: _channelDescription,
// importance: Importance.max,
// ),
// );
// }
//
// NotificationDetails get _alertDetails => const NotificationDetails(
// android: AndroidNotificationDetails(
// _channelId,
// _channelName,
// channelDescription: _channelDescription,
// importance: Importance.max,
// priority: Priority.high,
// ),
// );
//
// // ─────────────────────────────────────────────────────────────
// // CALLBACK (WorkManager)
// // ─────────────────────────────────────────────────────────────
// @pragma('vm:entry-point')
// void callbackDispatcher() {
// WidgetsFlutterBinding.ensureInitialized();
// Workmanager().executeTask((taskName, _inputData) async {
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// await _notifs.initialize(
// const InitializationSettings(android: initAndroid),
// );
//
// await _ensureNotificationChannel();
//
// try {
// final prefs = await SharedPreferences.getInstance();
// final url = prefs.getString('APIURL') ?? '';
// final response =
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
//
// if (response.statusCode == 200) {
// final data = json.decode(response.body) as Map<String, dynamic>;
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// '⚠️ ALERT',
// 'Urządzenie zgłosiło alarm! $data)',
// _alertDetails,
// );
// }
// } catch (e) {
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// 'Błąd API',
// e.toString(),
// _alertDetails,
// );
// }
//
// return true;
// });
// }
//
// // ─────────────────────────────────────────────────────────────
// // MAIN
// // ─────────────────────────────────────────────────────────────
// Future<void> main() async {
// dev.log('starting...', name: 'lodowka_ubibot');
// WidgetsFlutterBinding.ensureInitialized();
//
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString(
// 'APIURL',
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
// );
//
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
//
// if (Platform.isAndroid) {
// final android = _notifs.resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// final granted = await android?.requestNotificationsPermission();
// if (granted == null || !granted) {
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
// }
// }
//
// await _ensureNotificationChannel();
//
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
// await Workmanager().registerPeriodicTask(
// 'checkApiPeriodic',
// 'checkApi',
// frequency: const Duration(minutes: 15),
// existingWorkPolicy: ExistingWorkPolicy.keep,
// );
//
// runApp(const MyApp());
// }
//
// // ─────────────────────────────────────────────────────────────
// // UI (Stateful Widget)
// // ─────────────────────────────────────────────────────────────
// class MyApp extends StatefulWidget {
// const MyApp({super.key});
//
// @override
// State<MyApp> createState() => _MyAppState();
// }
//
// class _MyAppState extends State<MyApp> {
// final TextEditingController _controller = TextEditingController();
// String _field8Value = '';
//
// @override
// void initState() {
// super.initState();
// _loadApiUrlAndFetch();
// }
//
// Future<void> _loadApiUrlAndFetch() async {
// final prefs = await SharedPreferences.getInstance();
// final url = prefs.getString('APIURL') ?? '';
// _controller.text = url;
// await _fetchField8(url);
// }
//
// Future<void> _saveApiUrl(String text) async {
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString("APIURL", text);
// }
//
// Future<void> _fetchField8([String? customUrl]) async {
// setState(() {
// _field8Value = 'Ładowanie…';
// });
//
// try {
// final url = (customUrl ?? _controller.text).trim();
// if (url.isEmpty) {
// setState(() => _field8Value = 'Brak URL.');
// return;
// }
//
// final response =
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
//
// if (response.statusCode == 200) {
// final data = json.decode(response.body);
// final field8 = data['channel']?['last_values'] != null
// ? json.decode(data['channel']['last_values'])['field8']
// : null;
//
// if (field8 != null && field8['value'] != null) {
// setState(() => _field8Value =
// 'Temperatura zewnętrzna (field8): ${field8['value']} °C');
// } else {
// setState(() => _field8Value = 'Brak danych field8.');
// }
// } else {
// setState(() => _field8Value = 'Błąd: ${response.statusCode}');
// }
// } catch (e) {
// setState(() => _field8Value = 'Wyjątek: $e');
// }
// }
//
// @override
// void dispose() {
// _controller.dispose();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return MaterialApp(
// title: 'API Alert App',
// theme: ThemeData(useMaterial3: true),
// home: Scaffold(
// body: SafeArea(
// child: SingleChildScrollView(
// child: Column(
// children: [
// const Padding(
// padding: EdgeInsets.all(16.0),
// child: Text('Aplikacja nasłuchuje alertów…'),
// ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: TextField(
// controller: _controller,
// decoration: const InputDecoration(
// border: OutlineInputBorder(),
// labelText: 'API URL',
// ),
// onChanged: _saveApiUrl,
// ),
// ),
// ElevatedButton(
// onPressed: () => _fetchField8(),
// child: const Text('Sprawdź teraz'),
// ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: Text(
// _field8Value,
// style: const TextStyle(fontSize: 16),
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }
// import 'dart:convert';
// import 'dart:io' show Platform;
//
// import 'package:flutter/material.dart';
// import 'package:flutter/foundation.dart';
// import 'package:http/http.dart' as http;
// import 'package:workmanager/workmanager.dart';
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// import 'package:shared_preferences/shared_preferences.dart';
// import 'dart:developer' as dev;
//
// // ─────────────────────────────────────────────────────────────
// // Stałe / współdzielone
// // ─────────────────────────────────────────────────────────────
// const _channelId = 'alert_channel';
// const _channelName = 'Alerty';
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
// final _notifs = FlutterLocalNotificationsPlugin();
//
// Future<void> _ensureNotificationChannel() async {
// final android = _notifs
// .resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// await android?.createNotificationChannel(
// const AndroidNotificationChannel(
// _channelId,
// _channelName,
// description: _channelDescription,
// importance: Importance.max,
// ),
// );
// }
//
// NotificationDetails get _alertDetails => const NotificationDetails(
// android: AndroidNotificationDetails(
// _channelId,
// _channelName,
// channelDescription: _channelDescription,
// importance: Importance.max,
// priority: Priority.high,
// ),
// );
//
// // ─────────────────────────────────────────────────────────────
// // CALLBACK (WorkManager)
// // ─────────────────────────────────────────────────────────────
// @pragma('vm:entry-point')
// void callbackDispatcher() {
// print('lodowka_ubibot: ensureInitialized()...');
// WidgetsFlutterBinding.ensureInitialized();
// print('lodowka_ubibot: Workmanager().executeTask...');
// Workmanager().executeTask((taskName, _inputData) async {
// print('lodowka_ubibot: initAndroid = AndroidInitializationSettings...');
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// print('lodowka_ubibot: _notifs.initialize...');
// await _notifs.initialize(
// const InitializationSettings(android: initAndroid),
// );
//
// print('lodowka_ubibot: _ensureNotificationChannel()...');
// await _ensureNotificationChannel();
//
// try {
// print('lodowka_ubibot: SharedPreferences.getInstance()...');
// final prefs = await SharedPreferences.getInstance();
// print('lodowka_ubibot: prefs.getString...');
// final url = prefs.getString('APIURL') ?? '';
//
// print('lodowka_ubibot: final response = await http...');
// final response = await http
// .get(Uri.parse(url))
// .timeout(const Duration(seconds: 30));
//
// print('lodowka_ubibot: response.statusCode == 200...');
// if (response.statusCode == 200) {
// final data = json.decode(response.body) as Map<String, dynamic>;
// print('lodowka_ubibot: _notifs.show...');
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// '⚠️ ALERT',
// 'Urządzenie zgłosiło alarm! $data)',
// _alertDetails,
// );
// }
// } catch (e) {
// print('lodowka_ubibot: error: $e...');
// await _notifs.show(
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
// 'Błąd API',
// e.toString(),
// _alertDetails,
// );
// }
//
// return true;
// });
// }
//
// // ─────────────────────────────────────────────────────────────
// // MAIN
// // ─────────────────────────────────────────────────────────────
// Future<void> main() async {
// dev.log('starting...', name: 'lodowka_ubibot');
// WidgetsFlutterBinding.ensureInitialized();
//
// print('lodowka_ubibot: SharedPreferences.getInstance()...');
// final prefs = await SharedPreferences.getInstance();
// print('lodowka_ubibot: prefs.setString...');
// await prefs.setString(
// 'APIURL',
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
// );
//
// print('lodowka_ubibot: AndroidInitializationSettings...');
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
// print('lodowka_ubibot: _notifs.initialize...');
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
//
// if (Platform.isAndroid) {
// final android = _notifs
// .resolvePlatformSpecificImplementation<
// AndroidFlutterLocalNotificationsPlugin>();
// final granted = await android?.requestNotificationsPermission();
//
// if (granted == null || !granted) {
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
// }
// }
//
// print('lodowka_ubibot: _ensureNotificationChannel()...');
// await _ensureNotificationChannel();
//
// print('lodowka_ubibot: Workmanager().initialize...');
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
//
// print('lodowka_ubibot: Workmanager().registerPeriodicTask...');
// await Workmanager().registerPeriodicTask(
// 'checkApiPeriodic',
// 'checkApi',
// frequency: const Duration(minutes: 15),
// existingWorkPolicy: ExistingWorkPolicy.keep,
// );
//
// print('lodowka_ubibot: runApp...');
// runApp(const MyApp());
// }
//
// // ─────────────────────────────────────────────────────────────
// // UI (Stateful Widget)
// // ─────────────────────────────────────────────────────────────
// class MyApp extends StatefulWidget {
// const MyApp({super.key});
//
// @override
// State<MyApp> createState() => _MyAppState();
// }
//
// class _MyAppState extends State<MyApp> {
// final TextEditingController _controller = TextEditingController();
//
// @override
// void initState() {
// super.initState();
// _loadApiUrl();
// }
//
// Future<void> _loadApiUrl() async {
// final prefs = await SharedPreferences.getInstance();
// final url = prefs.getString('APIURL') ?? '';
// setState(() {
// _controller.text = url;
// });
// }
//
// Future<void> _saveApiUrl(String text) async {
// final prefs = await SharedPreferences.getInstance();
// await prefs.setString("APIURL", text);
// }
//
// @override
// void dispose() {
// _controller.dispose();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// return MaterialApp(
// title: 'API Alert App',
// theme: ThemeData(useMaterial3: true),
// home: Scaffold(
// body: SafeArea(
// child: Column(
// children: [
// const Padding(
// padding: EdgeInsets.all(16.0),
// child: Text('Aplikacja nasłuchuje alertów…'),
// ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: TextField(
// controller: _controller,
// decoration: const InputDecoration(
// border: OutlineInputBorder(),
// labelText: 'API URL',
// ),
// onChanged: _saveApiUrl,
// ),
// ),
// ],
// ),
// ),
// ),
// );
// }
// }