feat: pracovat na oznámení před obědem

This commit is contained in:
Matyáš Caras 2022-05-31 17:55:28 +00:00 committed by GitHub
parent 7ec2ded7ec
commit 93ec1e852f
9 changed files with 191 additions and 63 deletions

View file

@ -0,0 +1,5 @@
{
"name": "Flutter",
"image": "matspfeiffer/flutter:beta",
"extensions": ["dart-code.dart-code", "dart-code.flutter"]
}

View file

@ -1,3 +1,6 @@
# 1.3.0
- Odstranit connectivity_plus
- Přidat možnost oznámení s info o obědu v daný čas
# 1.2.0 # 1.2.0
- Přidat možnost zobrazení oznámení v případě neobjednaného jídla na příští týden - Přidat možnost zobrazení oznámení v případě neobjednaného jídla na příští týden
- Přidat oznámení o rozbitých uložených údajích - Přidat oznámení o rozbitých uložených údajích

View file

@ -145,6 +145,10 @@ abstract class Languages {
String get checkOrdered; String get checkOrdered;
String get notifyLunch;
String get notifyAt;
// Offline // Offline
String get offline; String get offline;

View file

@ -207,4 +207,11 @@ class LanguageCz extends Languages {
@override @override
String get corrupted => String get corrupted =>
"Nastal problém s dešifrováním uložených údajů, prosím zkuste vyčistit veškerá data této aplikace."; "Nastal problém s dešifrováním uložených údajů, prosím zkuste vyčistit veškerá data této aplikace.";
@override
String get notifyAt => "Odeslat v";
@override
String get notifyLunch =>
"V určený čas odeslat notifikaci s informacemi o obědě";
} }

View file

@ -206,4 +206,10 @@ class LanguageEn extends Languages {
@override @override
String get corrupted => String get corrupted =>
"The saved credentials seem to be corrupted, please try clearing the application's data."; "The saved credentials seem to be corrupted, please try clearing the application's data.";
@override
String get notifyAt => "Send notification at";
@override
String get notifyLunch => "Send a notification with meal info";
} }

View file

@ -1,18 +1,20 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:opencanteen/lang/lang_cz.dart'; import 'package:opencanteen/lang/lang_cz.dart';
import 'package:opencanteen/loginmanager.dart'; import 'package:opencanteen/loginmanager.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:canteenlib/canteenlib.dart'; import 'package:canteenlib/canteenlib.dart';
import 'package:opencanteen/okna/offline_jidelnicek.dart'; import 'package:opencanteen/okna/offline_jidelnicek.dart';
import 'package:opencanteen/okna/welcome.dart'; import 'package:opencanteen/okna/welcome.dart';
import 'package:opencanteen/util.dart'; import 'package:opencanteen/util.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'lang/lang.dart'; import 'lang/lang.dart';
import 'lang/lang_en.dart'; import 'lang/lang_en.dart';
@ -35,14 +37,75 @@ Copyright (C) 2022 Matyáš Caras a přispěvatelé
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
void main() { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// Pouze pro Android
void backgroundFetchHeadlessTask(HeadlessTask task) async {
String taskId = task.taskId;
bool isTimeout = task.timeout;
if (isTimeout) {
// Timeout
debugPrint("[BackgroundFetch] Headless task má time-out: $taskId");
BackgroundFetch.finish(taskId);
return;
}
var prefs = await SharedPreferences.getInstance();
debugPrint('[BackgroundFetch] Přišel headless event.');
if (prefs.getBool("oznamit") ?? false) {
// Oznámení před obědem
if (prefs.getBool("offline") ?? false) {
// TODO možnost brát z offline dat
} else {
// bere online
var d = await LoginManager.getDetails(); // získat údaje
if (d != null) {
// TODO
}
}
}
BackgroundFetch.finish(taskId);
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('notif_icon');
/// Note: permissions aren't requested here just to demonstrate that can be
/// done later
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification: (
int id,
String? title,
String? body,
String? payload,
) async {
debugPrint(body);
});
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String? payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
});
runApp(const MyApp()); runApp(const MyApp());
BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key); const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
@ -78,22 +141,49 @@ class _LoginPageState extends State<LoginPage> {
TextEditingController canteenControl = TextEditingController(); TextEditingController canteenControl = TextEditingController();
bool rememberMe = false; bool rememberMe = false;
void nastavitPozadi() async {
// Configure BackgroundFetch.
int status = await BackgroundFetch.configure(
BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.ANY), (String taskId) async {
// Callback
debugPrint("[BackgroundFetch] Event získán $taskId");
var d = await LoginManager.getDetails();
if (d != null) {
// TODO
}
BackgroundFetch.finish(taskId);
}, (String taskId) async {
debugPrint("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
BackgroundFetch.finish(taskId);
});
debugPrint('[BackgroundFetch] úspěšně nakonfigurováno: $status');
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
LoginManager.getDetails().then((r) async { LoginManager.getDetails().then((r) async {
var connectivityResult = await (Connectivity().checkConnectivity()); if (Platform.isIOS) {
if (connectivityResult == ConnectivityResult.none) { // žádat o oprávnění na iOS
ScaffoldMessenger.of(context).hideCurrentSnackBar(); await flutterLocalNotificationsPlugin
ScaffoldMessenger.of(context).showSnackBar( .resolvePlatformSpecificImplementation<
SnackBar( IOSFlutterLocalNotificationsPlugin>()
content: Text(Languages.of(context)!.errorContacting), ?.requestPermissions(
), alert: true,
badge: true,
sound: true,
); );
goOffline();
} }
if (r != null) { if (r != null) {
// Automaticky přihlásit
showDialog( showDialog(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
@ -123,6 +213,7 @@ class _LoginPageState extends State<LoginPage> {
} }
const storage = FlutterSecureStorage(); const storage = FlutterSecureStorage();
var odsouhlasil = await storage.read(key: "oc_souhlas"); var odsouhlasil = await storage.read(key: "oc_souhlas");
nastavitPozadi();
if (odsouhlasil == null || odsouhlasil != "ano") { if (odsouhlasil == null || odsouhlasil != "ano") {
Navigator.pushReplacement( Navigator.pushReplacement(
context, context,
@ -260,6 +351,7 @@ class _LoginPageState extends State<LoginPage> {
LoginManager.setDetails(userControl.text, LoginManager.setDetails(userControl.text,
passControl.text, canteenControl.text); passControl.text, canteenControl.text);
} }
nastavitPozadi();
// souhlas // souhlas
const storage = FlutterSecureStorage(); const storage = FlutterSecureStorage();
var odsouhlasil = var odsouhlasil =

View file

@ -17,6 +17,8 @@ class _NastaveniState extends State<Nastaveni> {
bool _ukladatOffline = false; bool _ukladatOffline = false;
bool _preskakovatVikend = false; bool _preskakovatVikend = false;
bool _kontrolovatTyden = false; bool _kontrolovatTyden = false;
bool _oznameniObed = false;
String? _oznameniCas;
void najitNastaveni() async { void najitNastaveni() async {
var preferences = await SharedPreferences.getInstance(); var preferences = await SharedPreferences.getInstance();
@ -24,6 +26,8 @@ class _NastaveniState extends State<Nastaveni> {
_ukladatOffline = preferences.getBool("offline") ?? false; _ukladatOffline = preferences.getBool("offline") ?? false;
_preskakovatVikend = preferences.getBool("skip") ?? false; _preskakovatVikend = preferences.getBool("skip") ?? false;
_kontrolovatTyden = preferences.getBool("tyden") ?? false; _kontrolovatTyden = preferences.getBool("tyden") ?? false;
_oznameniObed = preferences.getBool("oznamit") ?? false;
_oznameniCas = preferences.getString("oznameni_cas");
}); });
} }
@ -91,6 +95,26 @@ class _NastaveniState extends State<Nastaveni> {
}); });
}) })
], ],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(Languages.of(context)!.skipWeekend),
Switch(
value: _oznameniObed,
onChanged: (value) {
setState(() {
_oznameniObed = value;
zmenitNastaveni("oznamit", value);
});
})
],
),
Text(Languages.of(context)!.notifyAt),
TimePickerDialog(
initialTime: (_oznameniCas == null)
? TimeOfDay.now()
: TimeOfDay.fromDateTime(DateTime.parse(_oznameniCas!)),
) )
], ],
), ),

View file

@ -22,6 +22,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.8.2" version: "2.8.2"
background_fetch:
dependency: "direct main"
description:
name: background_fetch
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
canteenlib: canteenlib:
dependency: "direct main" dependency: "direct main"
description: description:
@ -57,48 +64,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.16.0" version: "1.16.0"
connectivity_plus:
dependency: "direct main"
description:
name: connectivity_plus
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
connectivity_plus_linux:
dependency: transitive
description:
name: connectivity_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
connectivity_plus_macos:
dependency: transitive
description:
name: connectivity_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
connectivity_plus_web:
dependency: transitive
description:
name: connectivity_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
connectivity_plus_windows:
dependency: transitive
description:
name: connectivity_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@ -153,6 +118,27 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
url: "https://pub.dartlang.org"
source: hosted
version: "9.5.3+1"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
flutter_localizations: flutter_localizations:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -268,13 +254,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.7.0"
nm:
dependency: transitive
description:
name: nm
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -441,6 +420,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
timezone:
dependency: transitive
description:
name: timezone
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

View file

@ -17,12 +17,13 @@ dependencies:
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
canteenlib: ^0.1.0-alpha.16 canteenlib: ^0.1.0-alpha.16
connectivity_plus: ^2.2.1
flutter_secure_storage: ^5.0.2 flutter_secure_storage: ^5.0.2
url_launcher: ^6.0.20 url_launcher: ^6.0.20
path_provider: ^2.0.9 path_provider: ^2.0.9
shared_preferences: ^2.0.13 shared_preferences: ^2.0.13
introduction_screen: ^3.0.1 introduction_screen: ^3.0.1
flutter_local_notifications: ^9.5.3+1
background_fetch: ^1.1.0
dev_dependencies: dev_dependencies:
flutter_lints: ^1.0.0 flutter_lints: ^1.0.0