From 610520397d7d53c7e4085cc2ad76e8d8994a3d1e Mon Sep 17 00:00:00 2001 From: Krzysztof Famulski Date: Mon, 21 Jul 2025 13:42:43 +0200 Subject: [PATCH] add enabled/disabled --- lib/main.dart | 978 +++++++------------------------------------------- 1 file changed, 137 insertions(+), 841 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0aabc10..c338c07 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,8 @@ import 'dart:developer' as dev; const _channelId = 'alert_channel'; const _channelName = 'Alerty'; const _channelDescription = 'Alerty z API (lodówka Ubibot)'; +const String NOTIFS_ENABLED_KEY = 'NOTIFICATIONS_ENABLED'; + final _notifs = FlutterLocalNotificationsPlugin(); Future _ensureNotificationChannel() async { @@ -37,6 +39,18 @@ NotificationDetails get _alertDetails => const NotificationDetails( ), ); +Future _safeGet(String url) async { + try { + return await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30)); + } catch (_) { + try { + return await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30)); + } catch (e) { + return null; + } + } +} + @pragma('vm:entry-point') void callbackDispatcher() { WidgetsFlutterBinding.ensureInitialized(); @@ -48,13 +62,19 @@ void callbackDispatcher() { await _ensureNotificationChannel(); + final prefs = await SharedPreferences.getInstance(); + final notificationsEnabled = prefs.getBool(NOTIFS_ENABLED_KEY) ?? true; + if (!notificationsEnabled) return true; + 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)); + final response = await _safeGet(url); + + if (response == null) { + throw Exception("Brak odpowiedzi z API (nawet po ponowieniu)."); + } if (response.statusCode == 200) { final data = json.decode(response.body); @@ -73,6 +93,8 @@ void callbackDispatcher() { ); } } + } else { + throw Exception('Błąd API: ${response.statusCode}'); } } catch (e) { await _notifs.show( @@ -133,6 +155,7 @@ class _MyAppState extends State { final TextEditingController _controller = TextEditingController(); String _field8Value = ''; double _threshold = 5.0; + bool _notificationsEnabled = true; @override void initState() { @@ -144,9 +167,11 @@ class _MyAppState extends State { final prefs = await SharedPreferences.getInstance(); final url = prefs.getString('APIURL') ?? ''; _threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0; + _notificationsEnabled = prefs.getBool(NOTIFS_ENABLED_KEY) ?? true; _controller.text = url; await _fetchField8(url); + setState(() {}); } Future _saveApiUrl(String text) async { @@ -159,6 +184,19 @@ class _MyAppState extends State { await prefs.setDouble("TEMP_THRESHOLD", _threshold); } + Future _toggleNotifications(BuildContext context, bool enabled) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool(NOTIFS_ENABLED_KEY, enabled); + setState(() => _notificationsEnabled = enabled); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Powiadomienia ${enabled ? "włączone" : "wyłączone"}'), + duration: const Duration(seconds: 2), + ), + ); + } + Future _fetchField8([String? customUrl]) async { setState(() { _field8Value = 'Ładowanie…'; @@ -166,7 +204,6 @@ class _MyAppState extends State { try { final prefs = await SharedPreferences.getInstance(); - final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0; final url = (customUrl ?? _controller.text).trim(); if (url.isEmpty) { @@ -174,8 +211,12 @@ class _MyAppState extends State { return; } - final response = - await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15)); + final response = await _safeGet(url); + + if (response == null) { + setState(() => _field8Value = 'Brak odpowiedzi z API.'); + return; + } if (response.statusCode == 200) { final data = json.decode(response.body); @@ -185,17 +226,7 @@ class _MyAppState extends State { 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, - // ); - // } + setState(() => _field8Value = 'Temperatura w lodówce: $temp °C'); } else { setState(() => _field8Value = 'Brak danych field8.'); } @@ -207,10 +238,88 @@ class _MyAppState extends State { } } - @override - void dispose() { - _controller.dispose(); - super.dispose(); + Widget _buildBody(BuildContext context) { + return 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), + ), + ], + ), + ], + ), + ), + SwitchListTile( + title: const Text('Powiadomienia'), + value: _notificationsEnabled, + onChanged: (val) => _toggleNotifications(context, val), + secondary: Icon( + _notificationsEnabled + ? Icons.notifications_active + : Icons.notifications_off, + ), + ), + ElevatedButton( + onPressed: () => _fetchField8(), + child: const Text('Sprawdź teraz'), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + _field8Value, + style: const TextStyle(fontSize: 20), + ), + ), + ], + ), + ), + ); } @override @@ -219,829 +328,16 @@ class _MyAppState extends State { 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), - - ), - ), - ], - ), + home: Builder( + builder: (context) => Scaffold( + appBar: AppBar( + title: const Text('UbiBot - powiadomienia'), + centerTitle: true, + backgroundColor: Colors.blue, ), + body: _buildBody(context), ), ), ); } } - - -// 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 _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 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 createState() => _MyAppState(); -// } -// -// class _MyAppState extends State { -// final TextEditingController _controller = TextEditingController(); -// final TextEditingController _thresholdController = TextEditingController(); -// String _field8Value = ''; -// -// @override -// void initState() { -// super.initState(); -// _loadSettingsAndFetch(); -// } -// -// Future _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 _saveApiUrl(String text) async { -// final prefs = await SharedPreferences.getInstance(); -// await prefs.setString("APIURL", text); -// } -// -// Future _saveThreshold(String text) async { -// final prefs = await SharedPreferences.getInstance(); -// final value = double.tryParse(text); -// if (value != null) { -// await prefs.setDouble("TEMP_THRESHOLD", value); -// } -// } -// -// Future _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 _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; -// 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 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 createState() => _MyAppState(); -// } -// -// class _MyAppState extends State { -// final TextEditingController _controller = TextEditingController(); -// String _field8Value = ''; -// -// @override -// void initState() { -// super.initState(); -// _loadApiUrlAndFetch(); -// } -// -// Future _loadApiUrlAndFetch() async { -// final prefs = await SharedPreferences.getInstance(); -// final url = prefs.getString('APIURL') ?? ''; -// _controller.text = url; -// await _fetchField8(url); -// } -// -// Future _saveApiUrl(String text) async { -// final prefs = await SharedPreferences.getInstance(); -// await prefs.setString("APIURL", text); -// } -// -// Future _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 _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; -// 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 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 createState() => _MyAppState(); -// } -// -// class _MyAppState extends State { -// final TextEditingController _controller = TextEditingController(); -// -// @override -// void initState() { -// super.initState(); -// _loadApiUrl(); -// } -// -// Future _loadApiUrl() async { -// final prefs = await SharedPreferences.getInstance(); -// final url = prefs.getString('APIURL') ?? ''; -// setState(() { -// _controller.text = url; -// }); -// } -// -// Future _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, -// ), -// ), -// ], -// ), -// ), -// ), -// ); -// } -// }