diff --git a/.metadata b/.metadata
index 05f4d5d..9e70ade 100644
--- a/.metadata
+++ b/.metadata
@@ -1,10 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
-# This file should be version controlled and should not be manually edited.
+# This file should be version controlled.
version:
- revision: 097d3313d8e2c7f901932d63e537c1acefb87800
+ revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
channel: stable
project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: android
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: ios
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: linux
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: macos
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: web
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ - platform: windows
+ create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+ base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a6408d..3345f31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 1.6.0
+- rozdělit iOS a Android UI zvlášť pro možnost využití Cupertino knihovny
+- opravit chybu s FlutterLocalNotifications na iOS
+- upravit vzhled
# 1.5.1
- aktualizovat knihovnu canteenlib
- přidat podporu pro splitování APK podle ABI
diff --git a/README.md b/README.md
index 8d9c48b..111fe69 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
Open-Source **neoficiální** aplikace pro přístup do iCanteen
[![wakatime](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/e3ff9994-0026-4041-a529-1cb2041bdf4b.svg)](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/e3ff9994-0026-4041-a529-1cb2041bdf4b)
-[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhernikplays%2Fopencanteen.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhernikplays%2Fopencanteen?ref=badge_shield) [![Codemagic build status](https://api.codemagic.io/apps/62863e4c96304ce0518a1694/62863e4c96304ce0518a1693/status_badge.svg)](https://codemagic.io/apps/62863e4c96304ce0518a1694/62863e4c96304ce0518a1693/latest_build) [![Commit Style: Conventional Commits](https://img.shields.io/badge/commit%20style-conventional%20commits-pink)](https://www.conventionalcommits.org/en/v1.0.0/)
+ [![Codemagic build status](https://api.codemagic.io/apps/62863e4c96304ce0518a1694/62863e4c96304ce0518a1693/status_badge.svg)](https://codemagic.io/apps/62863e4c96304ce0518a1694/62863e4c96304ce0518a1693/latest_build) [![Commit Style: Conventional Commits](https://img.shields.io/badge/commit%20style-conventional%20commits-pink)](https://www.conventionalcommits.org/en/v1.0.0/)
+
+### Upstream repozitář je nyní na adrese [https://git.mnau.xyz/hernik/opencanteen](https://git.mnau.xyz/hernik/opencanteen), všechny problémy hlaste tam.
## Co umí
Aplikace vás přihlásí do vaší iCanteen ***pokud ji podporuje [canteenlib](https://github.com/hernikplays/canteenlib/blob/main/COMPATIBILITY.md), jinak experimentálně***, a umožní vám zobrazit, objednávat obědy, objednávat nebo přidávat jídlo na burzu.
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f..9625e10 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 11.0
diff --git a/ios/Podfile b/ios/Podfile
index 1e8c3c9..88359b2 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 6cb9f25..03e4a2b 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,37 +1,41 @@
PODS:
- - connectivity_plus (0.0.1):
- - Flutter
- - ReachabilitySwift
- Flutter (1.0.0)
+ - flutter_local_notifications (0.0.1):
+ - Flutter
+ - flutter_native_timezone (0.0.1):
+ - Flutter
- flutter_secure_storage (3.3.1):
- Flutter
+ - package_info_plus (0.4.5):
+ - Flutter
- path_provider_ios (0.0.1):
- Flutter
- - ReachabilitySwift (5.0.0)
- shared_preferences_ios (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- Flutter (from `Flutter`)
+ - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
+ - flutter_native_timezone (from `.symlinks/plugins/flutter_native_timezone/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
-SPEC REPOS:
- trunk:
- - ReachabilitySwift
-
EXTERNAL SOURCES:
- connectivity_plus:
- :path: ".symlinks/plugins/connectivity_plus/ios"
Flutter:
:path: Flutter
+ flutter_local_notifications:
+ :path: ".symlinks/plugins/flutter_local_notifications/ios"
+ flutter_native_timezone:
+ :path: ".symlinks/plugins/flutter_native_timezone/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
+ package_info_plus:
+ :path: ".symlinks/plugins/package_info_plus/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
shared_preferences_ios:
@@ -40,14 +44,15 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
- connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
- Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
+ flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
+ flutter_native_timezone: 5f05b2de06c9776b4cc70e1839f03de178394d22
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
+ package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
- ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index dad830c..a52916f 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -340,7 +340,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -417,7 +417,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -466,7 +466,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 57d7799..78e1f39 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,5 +1,6 @@
import UIKit
import Flutter
+import flutter_local_notifications
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
diff --git a/lib/main.dart b/lib/main.dart
index a7dfc66..c92756e 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,16 +1,14 @@
import 'dart:io';
import 'package:flutter/material.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_native_timezone/flutter_native_timezone.dart';
-import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:opencanteen/lang/lang_cz.dart';
import 'package:opencanteen/loginmanager.dart';
import 'package:canteenlib/canteenlib.dart';
-import 'package:opencanteen/okna/offline_jidelnicek.dart';
-import 'package:opencanteen/okna/welcome.dart';
+import 'package:opencanteen/okna/android/login.dart';
+import 'package:opencanteen/okna/ios/login.dart';
import 'package:opencanteen/util.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';
@@ -19,7 +17,6 @@ import 'package:timezone/timezone.dart' as tz;
import 'lang/lang.dart';
import 'lang/lang_en.dart';
-import 'okna/jidelnicek.dart';
/*
Copyright (C) 2022 Matyáš Caras a přispěvatelé
@@ -113,9 +110,10 @@ void main() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('notif_icon');
- const InitializationSettings initializationSettings = InitializationSettings(
- android: initializationSettingsAndroid,
- );
+ const ios = DarwinInitializationSettings();
+
+ const InitializationSettings initializationSettings =
+ InitializationSettings(android: initializationSettingsAndroid, iOS: ios);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
// spustit aplikaci
@@ -142,290 +140,11 @@ class MyApp extends StatelessWidget {
brightness: Brightness.dark,
primarySwatch: Colors.purple,
),
- home: const LoginPage(),
+ home: (Platform.isAndroid) ? const AndroidLogin() : const IOSLogin(),
);
}
}
-class LoginPage extends StatefulWidget {
- const LoginPage({Key? key}) : super(key: key);
-
- @override
- State createState() => _LoginPageState();
-}
-
-class _LoginPageState extends State {
- TextEditingController userControl = TextEditingController();
- TextEditingController passControl = TextEditingController();
- TextEditingController canteenControl = TextEditingController();
- bool rememberMe = false;
- bool _showUrl = false;
- String dropdownUrl = instance.first["url"] ?? "";
-
- @override
- void initState() {
- super.initState();
- LoginManager.getDetails().then((r) async {
- if (Platform.isIOS) {
- // žádat o oprávnění na iOS
- await flutterLocalNotificationsPlugin
- .resolvePlatformSpecificImplementation<
- IOSFlutterLocalNotificationsPlugin>()
- ?.requestPermissions(
- alert: true,
- badge: true,
- sound: true,
- );
- } else if (Platform.isAndroid) {
- // žádat o oprávnění na android
- flutterLocalNotificationsPlugin
- .resolvePlatformSpecificImplementation<
- AndroidFlutterLocalNotificationsPlugin>()
- ?.requestPermission();
- }
- if (r != null) {
- // Automaticky přihlásit
- showDialog(
- context: context,
- barrierDismissible: false,
- builder: (_) => Dialog(
- child: SizedBox(
- height: 100,
- child: Row(children: [
- const Padding(
- padding: EdgeInsets.all(10),
- child: CircularProgressIndicator(),
- ),
- Text(Languages.of(context)!.loggingIn)
- ]),
- ),
- ));
- var canteen = Canteen(r["url"]!);
- try {
- var l = await canteen.login(r["user"]!, r["pass"]!);
- if (!l) {
- if (!mounted) return;
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(Languages.of(context)!.loginFailed),
- ),
- );
- return;
- }
- const storage = FlutterSecureStorage();
- var odsouhlasil = await storage.read(key: "oc_souhlas");
- if (!mounted) return;
- if (odsouhlasil == null || odsouhlasil != "ano") {
- Navigator.pushAndRemoveUntil(
- context,
- MaterialPageRoute(
- builder: (c) => WelcomeScreen(
- canteen: canteen, n: flutterLocalNotificationsPlugin),
- ),
- (route) => false);
- } else {
- Navigator.pushAndRemoveUntil(
- context,
- MaterialPageRoute(
- builder: (context) => JidelnicekPage(
- canteen: canteen, n: flutterLocalNotificationsPlugin),
- ),
- (route) => false);
- }
- } on PlatformException {
- if (!mounted) return;
- Navigator.of(context).pop();
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(Languages.of(context)!.corrupted),
- ),
- );
- } catch (_) {
- if (!mounted) return;
- Navigator.of(context).pop();
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(Languages.of(context)!.errorContacting),
- ),
- );
- goOffline();
- }
- }
- });
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text(Languages.of(context)!.logIn),
- automaticallyImplyLeading: false,
- ),
- body: Center(
- child: SingleChildScrollView(
- child: SizedBox(
- width: MediaQuery.of(context).size.width - 50,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(
- Languages.of(context)!.appName,
- textAlign: TextAlign.center,
- style: const TextStyle(
- fontWeight: FontWeight.bold, fontSize: 40),
- ),
- Text(
- Languages.of(context)!.logIn,
- textAlign: TextAlign.center,
- ),
- TextField(
- controller: userControl,
- autofillHints: const [AutofillHints.username],
- decoration: InputDecoration(
- labelText: Languages.of(context)!.username),
- ),
- TextField(
- autofillHints: const [AutofillHints.password],
- decoration: InputDecoration(
- labelText: Languages.of(context)!.password),
- controller: passControl,
- obscureText: true,
- ),
- const SizedBox(
- height: 10,
- ),
- DropdownButton(
- isExpanded: true,
- value: dropdownUrl,
- items: instance.map>((e) {
- return DropdownMenuItem(
- value: e["url"],
- child: Text(e["name"]!),
- );
- }).toList(),
- onChanged: (String? value) {
- setState(() {
- if (value == "") {
- _showUrl = true;
- } else {
- _showUrl = false;
- }
- dropdownUrl = value!;
- });
- },
- ),
- AnimatedOpacity(
- opacity: _showUrl ? 1.0 : 0.0,
- duration: const Duration(milliseconds: 300),
- child: TextField(
- autofillHints: const [AutofillHints.url],
- decoration: InputDecoration(
- labelText: Languages.of(context)!.iCanteenUrl),
- keyboardType: TextInputType.url,
- controller: canteenControl,
- ),
- ),
- Row(mainAxisAlignment: MainAxisAlignment.center, children: [
- Switch(
- value: rememberMe,
- onChanged: (value) {
- setState(() {
- rememberMe = value;
- });
- }),
- Text(Languages.of(context)!.rememberMe)
- ]),
- TextButton(
- onPressed: () async {
- var canteenUrl = (dropdownUrl == "")
- ? canteenControl.text
- : dropdownUrl;
- if (!canteenUrl.startsWith("https://") &&
- !canteenUrl.startsWith("http://")) {
- canteenUrl = "https://$canteenUrl";
- }
- var canteen = Canteen(canteenUrl);
- try {
- var l = await canteen.login(
- userControl.text, passControl.text);
- if (!l) {
- if (!mounted) return;
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content:
- Text(Languages.of(context)!.loginFailed),
- ),
- );
- return;
- }
- if (rememberMe) {
- LoginManager.setDetails(
- userControl.text, passControl.text, canteenUrl);
- }
- // souhlas
- const storage = FlutterSecureStorage();
- var odsouhlasil =
- await storage.read(key: "oc_souhlas");
- if (!mounted) return;
- if (odsouhlasil == null || odsouhlasil != "ano") {
- Navigator.pushAndRemoveUntil(
- context,
- MaterialPageRoute(
- builder: (c) => WelcomeScreen(
- canteen: canteen,
- n: flutterLocalNotificationsPlugin)),
- (route) => false);
- } else {
- Navigator.pushAndRemoveUntil(
- context,
- MaterialPageRoute(
- builder: (context) => JidelnicekPage(
- canteen: canteen,
- n: flutterLocalNotificationsPlugin)),
- (route) => false);
- }
- } on PlatformException {
- if (!mounted) return;
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(Languages.of(context)!.corrupted),
- ),
- );
- } on Exception catch (_) {
- if (!mounted) return;
- ScaffoldMessenger.of(context).hideCurrentSnackBar();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content:
- Text(Languages.of(context)!.errorContacting),
- ),
- );
- goOffline();
- }
- },
- child: Text(Languages.of(context)!.logIn)),
- ],
- ),
- ),
- ),
- ));
- }
-
- /// Získá offline soubor a zobrazí údaje
- void goOffline() async {
- if (!mounted) return;
- Navigator.pushAndRemoveUntil(
- context,
- MaterialPageRoute(builder: ((context) => const OfflineJidelnicek())),
- (route) => false);
- }
-}
-
class AppLocalizationsDelegate extends LocalizationsDelegate {
const AppLocalizationsDelegate();
diff --git a/lib/okna/burza.dart b/lib/okna/android/burza.dart
similarity index 89%
rename from lib/okna/burza.dart
rename to lib/okna/android/burza.dart
index fce72a3..4e7dfd7 100644
--- a/lib/okna/burza.dart
+++ b/lib/okna/android/burza.dart
@@ -1,21 +1,18 @@
import 'package:canteenlib/canteenlib.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:opencanteen/okna/android/login.dart';
import 'package:opencanteen/util.dart';
-import '../lang/lang.dart';
-import '../main.dart';
+import '../../lang/lang.dart';
-class BurzaPage extends StatefulWidget {
- const BurzaPage({Key? key, required this.canteen, required this.n})
- : super(key: key);
+class AndroidBurza extends StatefulWidget {
+ const AndroidBurza({Key? key, required this.canteen}) : super(key: key);
final Canteen canteen;
- final FlutterLocalNotificationsPlugin n;
@override
- State createState() => _BurzaPageState();
+ State createState() => _AndroidBurzaState();
}
-class _BurzaPageState extends State {
+class _AndroidBurzaState extends State {
List obsah = [];
double kredit = 0.0;
Future nactiBurzu(BuildContext context) async {
@@ -101,7 +98,7 @@ class _BurzaPageState extends State {
}).catchError((o) {
if (!widget.canteen.prihlasen) {
Navigator.pushReplacement(
- context, MaterialPageRoute(builder: (c) => const LoginPage()));
+ context, MaterialPageRoute(builder: (c) => const AndroidLogin()));
}
});
}
@@ -115,7 +112,7 @@ class _BurzaPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
- drawer: drawerGenerator(context, widget.canteen, 3, widget.n),
+ drawer: drawerGenerator(context, widget.canteen, 3),
appBar: AppBar(
title: Text(Languages.of(context)!.exchange),
),
diff --git a/lib/okna/jidelnicek.dart b/lib/okna/android/jidelnicek.dart
similarity index 93%
rename from lib/okna/jidelnicek.dart
rename to lib/okna/android/jidelnicek.dart
index 52cbe1c..24749d1 100644
--- a/lib/okna/jidelnicek.dart
+++ b/lib/okna/android/jidelnicek.dart
@@ -3,28 +3,25 @@ import 'dart:io';
import 'package:canteenlib/canteenlib.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
-import 'package:opencanteen/okna/nastaveni.dart';
+import 'package:opencanteen/okna/android/login.dart';
+import 'package:opencanteen/okna/android/nastaveni.dart';
import 'package:opencanteen/util.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
-import '../lang/lang.dart';
-import '../main.dart';
+import '../../lang/lang.dart';
-class JidelnicekPage extends StatefulWidget {
- const JidelnicekPage({Key? key, required this.canteen, required this.n})
- : super(key: key);
+class AndroidJidelnicek extends StatefulWidget {
+ const AndroidJidelnicek({Key? key, required this.canteen}) : super(key: key);
final Canteen canteen;
- final FlutterLocalNotificationsPlugin n;
@override
- State createState() => _JidelnicekPageState();
+ State createState() => _AndroidJidelnicekState();
}
-class _JidelnicekPageState extends State {
+class _AndroidJidelnicekState extends State {
List obsah = [const CircularProgressIndicator()];
DateTime den = DateTime.now();
String denTydne = "";
@@ -120,7 +117,7 @@ class _JidelnicekPageState extends State {
Checkbox(
value: j.objednano,
fillColor: (j.lzeObjednat)
- ? MaterialStateProperty.all(Colors.blue)
+ ? MaterialStateProperty.all(Colors.purple)
: MaterialStateProperty.all(Colors.grey),
onChanged: (v) async {
if (!j.lzeObjednat) {
@@ -312,13 +309,12 @@ class _JidelnicekPageState extends State {
}).catchError((o) {
if (!widget.canteen.prihlasen) {
Navigator.pushReplacement(
- context, MaterialPageRoute(builder: (c) => const LoginPage()));
+ context, MaterialPageRoute(builder: (c) => const AndroidLogin()));
}
});
}
- Future kliknuti(String value, BuildContext context,
- FlutterLocalNotificationsPlugin n) async {
+ Future kliknuti(String value, BuildContext context) async {
if (value == Languages.of(context)!.signOut) {
await showDialog(
context: context,
@@ -332,7 +328,7 @@ class _JidelnicekPageState extends State {
storage.deleteAll();
Navigator.pushAndRemoveUntil(
context,
- MaterialPageRoute(builder: (c) => const LoginPage()),
+ MaterialPageRoute(builder: (c) => const AndroidLogin()),
(route) => false);
},
child: Text(Languages.of(context)!.yes)),
@@ -343,14 +339,8 @@ class _JidelnicekPageState extends State {
),
);
} else if (value == Languages.of(context)!.review) {
- (Platform.isAndroid)
- ? launchUrl(
- Uri.parse("market://details?id=cz.hernikplays.opencanteen"),
- mode: LaunchMode.externalApplication)
- : launchUrl(
- Uri.parse(
- "https://apps.apple.com/cz/app/opencanteen/id1621124445"),
- mode: LaunchMode.externalApplication);
+ launchUrl(Uri.parse("market://details?id=cz.hernikplays.opencanteen"),
+ mode: LaunchMode.externalApplication);
} else if (value == Languages.of(context)!.reportBugs) {
launchUrl(Uri.parse("https://forms.gle/jKN7QeFJwpaApSbC8"),
mode: LaunchMode.externalApplication);
@@ -366,12 +356,12 @@ class _JidelnicekPageState extends State {
children: [
TextButton(
onPressed: (() => launchUrl(
- Uri.parse("https://github.com/hernikplays/opencanteen"))),
+ Uri.parse("https://git.mnau.xyz/hernik/opencanteen"))),
child: Text(Languages.of(context)!.source))
]);
} else if (value == Languages.of(context)!.settings) {
Navigator.push(
- context, MaterialPageRoute(builder: (c) => Nastaveni(n: n)));
+ context, MaterialPageRoute(builder: (c) => const AndroidNastaveni()));
}
}
@@ -403,7 +393,7 @@ class _JidelnicekPageState extends State {
j = await widget.canteen.jidelnicekDen(den: d);
} catch (e) {
if (!widget.canteen.prihlasen) {
- if (!mounted) return; // ! Přidat chybu, pokud není mounted
+ if (!mounted) return;
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(Languages.of(context)!.errorSaving),
@@ -442,12 +432,12 @@ class _JidelnicekPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
- drawer: drawerGenerator(context, widget.canteen, 1, widget.n),
+ drawer: drawerGenerator(context, widget.canteen, 1),
appBar: AppBar(
title: Text(Languages.of(context)!.menu),
actions: [
PopupMenuButton(
- onSelected: ((String value) => kliknuti(value, context, widget.n)),
+ onSelected: ((String value) => kliknuti(value, context)),
itemBuilder: (BuildContext context) {
return {
Languages.of(context)!.reportBugs,
diff --git a/lib/okna/android/login.dart b/lib/okna/android/login.dart
new file mode 100644
index 0000000..1269ef6
--- /dev/null
+++ b/lib/okna/android/login.dart
@@ -0,0 +1,281 @@
+import 'dart:io';
+
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:opencanteen/okna/android/welcome.dart';
+
+import '../../lang/lang.dart';
+import '../../loginmanager.dart';
+import '../../main.dart';
+import '../../util.dart';
+import 'jidelnicek.dart';
+import 'offline_jidelnicek.dart';
+
+class AndroidLogin extends StatefulWidget {
+ const AndroidLogin({Key? key}) : super(key: key);
+ @override
+ State createState() => _AndroidLoginState();
+}
+
+class _AndroidLoginState extends State {
+ TextEditingController userControl = TextEditingController();
+ TextEditingController passControl = TextEditingController();
+ TextEditingController canteenControl = TextEditingController();
+ bool rememberMe = false;
+ bool _showUrl = false;
+ String dropdownUrl = instance.first["url"] ?? "";
+
+ @override
+ void initState() {
+ super.initState();
+ LoginManager.getDetails().then((r) async {
+ // žádat o oprávnění na android
+ flutterLocalNotificationsPlugin
+ .resolvePlatformSpecificImplementation<
+ AndroidFlutterLocalNotificationsPlugin>()
+ ?.requestPermission();
+
+ if (r != null) {
+ // Automaticky přihlásit
+ showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (_) => Dialog(
+ child: SizedBox(
+ height: 100,
+ child: Row(children: [
+ const Padding(
+ padding: EdgeInsets.all(10),
+ child: CircularProgressIndicator(),
+ ),
+ Text(Languages.of(context)!.loggingIn)
+ ]),
+ ),
+ ));
+ var canteen = Canteen(r["url"]!);
+ try {
+ var l = await canteen.login(r["user"]!, r["pass"]!);
+ if (!l) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.loginFailed),
+ ),
+ );
+ return;
+ }
+ const storage = FlutterSecureStorage();
+ var odsouhlasil = await storage.read(key: "oc_souhlas");
+ if (!mounted) return;
+ if (odsouhlasil == null || odsouhlasil != "ano") {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (c) => AndroidWelcome(canteen: canteen),
+ ),
+ (route) => false);
+ } else {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (context) => AndroidJidelnicek(canteen: canteen),
+ ),
+ (route) => false);
+ }
+ } on PlatformException {
+ if (!mounted) return;
+ Navigator.of(context).pop();
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.corrupted),
+ ),
+ );
+ } catch (_) {
+ if (!mounted) return;
+ Navigator.of(context).pop();
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.errorContacting),
+ ),
+ );
+ goOffline();
+ }
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.logIn),
+ automaticallyImplyLeading: false,
+ ),
+ body: Center(
+ child: SingleChildScrollView(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width - 50,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ Languages.of(context)!.appName,
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ fontWeight: FontWeight.bold, fontSize: 40),
+ ),
+ Text(
+ Languages.of(context)!.logIn,
+ textAlign: TextAlign.center,
+ ),
+ TextField(
+ controller: userControl,
+ autofillHints: const [AutofillHints.username],
+ decoration: InputDecoration(
+ labelText: Languages.of(context)!.username),
+ ),
+ TextField(
+ autofillHints: const [AutofillHints.password],
+ decoration: InputDecoration(
+ labelText: Languages.of(context)!.password),
+ controller: passControl,
+ obscureText: true,
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+ DropdownButton(
+ isExpanded: true,
+ value: dropdownUrl,
+ items: instance.map>((e) {
+ return DropdownMenuItem(
+ value: e["url"],
+ child: Text(e["name"]!),
+ );
+ }).toList(),
+ onChanged: (String? value) {
+ setState(() {
+ if (value == "") {
+ _showUrl = true;
+ } else {
+ _showUrl = false;
+ }
+ dropdownUrl = value!;
+ });
+ },
+ ),
+ AnimatedOpacity(
+ opacity: _showUrl ? 1.0 : 0.0,
+ duration: const Duration(milliseconds: 300),
+ child: TextField(
+ autofillHints: const [AutofillHints.url],
+ decoration: InputDecoration(
+ labelText: Languages.of(context)!.iCanteenUrl),
+ keyboardType: TextInputType.url,
+ controller: canteenControl,
+ ),
+ ),
+ Row(mainAxisAlignment: MainAxisAlignment.center, children: [
+ Switch(
+ value: rememberMe,
+ onChanged: (value) {
+ setState(() {
+ rememberMe = value;
+ });
+ }),
+ Text(Languages.of(context)!.rememberMe)
+ ]),
+ TextButton(
+ onPressed: () async {
+ var canteenUrl = (dropdownUrl == "")
+ ? canteenControl.text
+ : dropdownUrl;
+ if (!canteenUrl.startsWith("https://") &&
+ !canteenUrl.startsWith("http://")) {
+ canteenUrl = "https://$canteenUrl";
+ }
+ var canteen = Canteen(canteenUrl);
+ try {
+ var l = await canteen.login(
+ userControl.text, passControl.text);
+ if (!l) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content:
+ Text(Languages.of(context)!.loginFailed),
+ ),
+ );
+ return;
+ }
+ if (rememberMe) {
+ LoginManager.setDetails(
+ userControl.text, passControl.text, canteenUrl);
+ }
+ // souhlas
+ const storage = FlutterSecureStorage();
+ var odsouhlasil =
+ await storage.read(key: "oc_souhlas");
+ if (!mounted) return;
+ if (odsouhlasil == null || odsouhlasil != "ano") {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (c) => AndroidWelcome(
+ canteen: canteen,
+ )),
+ (route) => false);
+ } else {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (context) => AndroidJidelnicek(
+ canteen: canteen,
+ )),
+ (route) => false);
+ }
+ } on PlatformException {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.corrupted),
+ ),
+ );
+ } on Exception catch (_) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content:
+ Text(Languages.of(context)!.errorContacting),
+ ),
+ );
+ goOffline();
+ }
+ },
+ child: Text(Languages.of(context)!.logIn)),
+ ],
+ ),
+ ),
+ ),
+ ));
+ }
+
+ /// Získá offline soubor a zobrazí údaje
+ void goOffline() async {
+ if (!mounted) return;
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: ((context) => const AndroidOfflineJidelnicek())),
+ (route) => false);
+ }
+}
diff --git a/lib/okna/nastaveni.dart b/lib/okna/android/nastaveni.dart
similarity index 93%
rename from lib/okna/nastaveni.dart
rename to lib/okna/android/nastaveni.dart
index 9ad82a7..a4a80e2 100644
--- a/lib/okna/nastaveni.dart
+++ b/lib/okna/android/nastaveni.dart
@@ -9,20 +9,19 @@ import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:timezone/timezone.dart' as tz;
-import '../lang/lang.dart';
-import '../loginmanager.dart';
-import '../util.dart';
+import '../../lang/lang.dart';
+import '../../loginmanager.dart';
+import '../../main.dart';
+import '../../util.dart';
-class Nastaveni extends StatefulWidget {
- const Nastaveni({Key? key, required this.n}) : super(key: key);
-
- final FlutterLocalNotificationsPlugin n;
+class AndroidNastaveni extends StatefulWidget {
+ const AndroidNastaveni({Key? key}) : super(key: key);
@override
- State createState() => _NastaveniState();
+ State createState() => _AndroidNastaveniState();
}
-class _NastaveniState extends State {
+class _AndroidNastaveniState extends State {
bool _ukladatOffline = false;
bool _preskakovatVikend = false;
bool _kontrolovatTyden = false;
@@ -81,6 +80,7 @@ class _NastaveniState extends State {
Text(Languages.of(context)!.saveOffline),
Switch(
value: _ukladatOffline,
+ activeColor: Colors.purple,
onChanged: (value) {
setState(() {
_ukladatOffline = value;
@@ -116,6 +116,7 @@ class _NastaveniState extends State {
children: [
Text(Languages.of(context)!.skipWeekend),
Switch(
+ activeColor: Colors.purple,
value: _preskakovatVikend,
onChanged: (value) {
setState(() {
@@ -130,6 +131,7 @@ class _NastaveniState extends State {
children: [
Flexible(child: Text(Languages.of(context)!.checkOrdered)),
Switch(
+ activeColor: Colors.purple,
value: _kontrolovatTyden,
onChanged: (value) {
setState(() {
@@ -144,6 +146,7 @@ class _NastaveniState extends State {
children: [
Flexible(child: Text(Languages.of(context)!.notifyLunch)),
Switch(
+ activeColor: Colors.purple,
value: _oznameniObed,
thumbColor: (!_zapamatovany
? MaterialStateProperty.all(Colors.grey)
@@ -241,7 +244,7 @@ class _NastaveniState extends State {
}
void vytvoritOznameni(DateTime den) async {
- await widget.n.cancelAll();
+ await flutterLocalNotificationsPlugin.cancelAll();
var d = await LoginManager.getDetails(); // získat údaje
if (d != null) {
// Nové oznámení
@@ -260,7 +263,7 @@ class _NastaveniState extends State {
var l =
tz.getLocation(await FlutterNativeTimezone.getLocalTimezone());
if (!mounted) return;
- await widget.n.zonedSchedule(
+ await flutterLocalNotificationsPlugin.zonedSchedule(
// Vytvoří nové oznámení pro daný čas a datum
0,
Languages.of(context)!.lunchNotif,
diff --git a/lib/okna/offline_jidelnicek.dart b/lib/okna/android/offline_jidelnicek.dart
similarity index 88%
rename from lib/okna/offline_jidelnicek.dart
rename to lib/okna/android/offline_jidelnicek.dart
index fb25934..df8814f 100644
--- a/lib/okna/offline_jidelnicek.dart
+++ b/lib/okna/android/offline_jidelnicek.dart
@@ -3,22 +3,23 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:opencanteen/okna/android/login.dart';
import 'package:opencanteen/util.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
-import '../lang/lang.dart';
-import '../main.dart';
+import '../../lang/lang.dart';
-class OfflineJidelnicek extends StatefulWidget {
- const OfflineJidelnicek({Key? key}) : super(key: key);
+class AndroidOfflineJidelnicek extends StatefulWidget {
+ const AndroidOfflineJidelnicek({Key? key}) : super(key: key);
@override
- State createState() => _OfflineJidelnicekState();
+ State createState() =>
+ _AndroidOfflineJidelnicekState();
}
-class _OfflineJidelnicekState extends State {
+class _AndroidOfflineJidelnicekState extends State {
List obsah = [const CircularProgressIndicator()];
var _skipWeekend = false;
DateTime den = DateTime.now();
@@ -94,11 +95,12 @@ class _OfflineJidelnicekState extends State {
? Languages.of(context)!.inExchange
: "${j.cena} Kč"),
Checkbox(
- value: j.objednano,
- fillColor: MaterialStateProperty.all(Colors.grey),
- onChanged: (v) async {
- return;
- })
+ value: j.objednano,
+ fillColor: MaterialStateProperty.all(Colors.grey),
+ onChanged: (v) async {
+ return;
+ },
+ )
],
),
),
@@ -113,16 +115,10 @@ class _OfflineJidelnicekState extends State {
const storage = FlutterSecureStorage();
storage.deleteAll();
Navigator.pushReplacement(
- context, MaterialPageRoute(builder: (c) => const LoginPage()));
+ context, MaterialPageRoute(builder: (c) => const AndroidLogin()));
} else if (value == Languages.of(context)!.review) {
- (Platform.isAndroid)
- ? launchUrl(
- Uri.parse("market://details?id=cz.hernikplays.opencanteen"),
- mode: LaunchMode.externalApplication)
- : launchUrl(
- Uri.parse(
- "https://apps.apple.com/cz/app/opencanteen/id1621124445"),
- mode: LaunchMode.externalApplication);
+ launchUrl(Uri.parse("market://details?id=cz.hernikplays.opencanteen"),
+ mode: LaunchMode.externalApplication);
} else if (value == Languages.of(context)!.reportBugs) {
launchUrl(Uri.parse("https://forms.gle/jKN7QeFJwpaApSbC8"),
mode: LaunchMode.externalApplication);
@@ -138,7 +134,7 @@ class _OfflineJidelnicekState extends State {
children: [
TextButton(
onPressed: (() => launchUrl(
- Uri.parse("https://github.com/hernikplays/opencanteen"))),
+ Uri.parse("https://git.mnau.xyz/hernik/opencanteen"))),
child: Text(Languages.of(context)!.source))
]);
}
@@ -261,7 +257,7 @@ class _OfflineJidelnicekState extends State {
),
),
onRefresh: () => Navigator.pushReplacement(context,
- MaterialPageRoute(builder: ((context) => const LoginPage()))),
+ MaterialPageRoute(builder: ((context) => const AndroidLogin()))),
),
);
}
diff --git a/lib/okna/welcome.dart b/lib/okna/android/welcome.dart
similarity index 80%
rename from lib/okna/welcome.dart
rename to lib/okna/android/welcome.dart
index 676e023..9141ff9 100644
--- a/lib/okna/welcome.dart
+++ b/lib/okna/android/welcome.dart
@@ -1,23 +1,20 @@
import 'package:canteenlib/canteenlib.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:opencanteen/lang/lang.dart';
-import 'package:opencanteen/okna/jidelnicek.dart';
+import 'package:opencanteen/okna/android/jidelnicek.dart';
-class WelcomeScreen extends StatefulWidget {
- const WelcomeScreen({Key? key, required this.canteen, required this.n})
- : super(key: key);
+class AndroidWelcome extends StatefulWidget {
+ const AndroidWelcome({Key? key, required this.canteen}) : super(key: key);
final Canteen canteen;
- final FlutterLocalNotificationsPlugin n;
@override
- State createState() => _WelcomeScreenState();
+ State createState() => _AndroidWelcomeState();
}
-class _WelcomeScreenState extends State {
+class _AndroidWelcomeState extends State {
@override
Widget build(BuildContext context) {
var listPagesViewModel = [
@@ -72,8 +69,7 @@ class _WelcomeScreenState extends State {
if (!mounted) return;
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
- builder: (c) =>
- JidelnicekPage(canteen: widget.canteen, n: widget.n)),
+ builder: (c) => AndroidJidelnicek(canteen: widget.canteen)),
(route) => false);
},
),
diff --git a/lib/okna/ios/burza.dart b/lib/okna/ios/burza.dart
new file mode 100644
index 0000000..c2340ed
--- /dev/null
+++ b/lib/okna/ios/burza.dart
@@ -0,0 +1,143 @@
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:opencanteen/okna/ios/login.dart';
+import 'package:opencanteen/util.dart';
+
+import '../../lang/lang.dart';
+
+class IOSBurza extends StatefulWidget {
+ const IOSBurza({Key? key, required this.canteen}) : super(key: key);
+ final Canteen canteen;
+ @override
+ State createState() => _IOSBurzaState();
+}
+
+class _IOSBurzaState extends State {
+ List obsah = [];
+ double kredit = 0.0;
+ Future nactiBurzu(BuildContext context) async {
+ obsah = [const CircularProgressIndicator()];
+ widget.canteen.ziskejUzivatele().then((kr) {
+ kredit = kr.kredit;
+ widget.canteen.ziskatBurzu().then((burza) {
+ setState(() {
+ obsah = [];
+ if (burza.isEmpty) {
+ obsah = [
+ Text(
+ Languages.of(context)!.noExchange,
+ style: const TextStyle(fontSize: 20),
+ ),
+ Text(Languages.of(context)!.pullToReload)
+ ];
+ } else {
+ for (var b in burza) {
+ obsah.add(
+ Padding(
+ padding: const EdgeInsets.only(top: 15),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text("${b.den.day}. ${b.den.month}."),
+ const SizedBox(width: 10),
+ Flexible(
+ child: Text(
+ b.nazev,
+ ),
+ ),
+ Text("${b.pocet}x"),
+ CupertinoButton(
+ onPressed: () {
+ widget.canteen.objednatZBurzy(b).then((a) {
+ if (a) {
+ showDialog(
+ context: context,
+ builder: (context) => CupertinoAlertDialog(
+ title: Text(Languages.of(context)!.ordered),
+ content: Text(
+ Languages.of(context)!.orderSuccess),
+ actions: [
+ CupertinoButton(
+ child: Text(Languages.of(context)!.ok),
+ onPressed: () =>
+ Navigator.of(context).pop(),
+ )
+ ],
+ ),
+ );
+ } else {
+ showDialog(
+ context: context,
+ builder: (context) => CupertinoAlertDialog(
+ title: Text(
+ Languages.of(context)!.cannotOrder),
+ content: Text(
+ Languages.of(context)!.errorOrdering),
+ actions: [
+ CupertinoButton(
+ child: Text(Languages.of(context)!.ok),
+ onPressed: () =>
+ Navigator.of(context).pop(),
+ )
+ ],
+ ),
+ );
+ }
+ nactiBurzu(context);
+ });
+ },
+ child: Text(Languages.of(context)!.order)),
+ ],
+ ),
+ ),
+ );
+ }
+ }
+ });
+ });
+ }).catchError((o) {
+ if (!widget.canteen.prihlasen) {
+ Navigator.pushReplacement(
+ context, MaterialPageRoute(builder: (c) => const IOSLogin()));
+ }
+ });
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ nactiBurzu(context);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ drawer: drawerGenerator(context, widget.canteen, 3),
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.exchange),
+ ),
+ body: RefreshIndicator(
+ child: Center(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width - 50,
+ child: Column(
+ children: [
+ const SizedBox(height: 10),
+ Text("${Languages.of(context)!.balance}$kredit Kč"),
+ const SizedBox(height: 10),
+ SingleChildScrollView(
+ physics: const AlwaysScrollableScrollPhysics(),
+ child: SizedBox(
+ height: MediaQuery.of(context).size.height / 1.3,
+ child: Column(children: obsah),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ onRefresh: () => nactiBurzu(context)),
+ );
+ }
+}
diff --git a/lib/okna/ios/jidelnicek.dart b/lib/okna/ios/jidelnicek.dart
new file mode 100644
index 0000000..ff6a60d
--- /dev/null
+++ b/lib/okna/ios/jidelnicek.dart
@@ -0,0 +1,568 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:opencanteen/okna/ios/login.dart';
+import 'package:opencanteen/okna/ios/nastaveni.dart';
+import 'package:opencanteen/util.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+import '../../lang/lang.dart';
+
+class IOSJidelnicek extends StatefulWidget {
+ const IOSJidelnicek({Key? key, required this.canteen}) : super(key: key);
+ final Canteen canteen;
+ @override
+ State createState() => _IOSJidelnicekState();
+}
+
+class _IOSJidelnicekState extends State {
+ List obsah = [const CircularProgressIndicator()];
+ DateTime den = DateTime.now();
+ String denTydne = "";
+ double kredit = 0.0;
+ bool _skipWeekend = false;
+
+ void kontrolaTyden(BuildContext context) async {
+ var prefs = await SharedPreferences.getInstance();
+ if (prefs.getBool("tyden") ?? false) {
+ // Zjistit jestli je objednáno na přístí týden
+ var pristi = den.add(const Duration(days: 6));
+ for (var i = 0; i < 5; i++) {
+ var jidelnicek = await widget.canteen
+ .jidelnicekDen(den: pristi.add(Duration(days: i + 1)));
+ if (jidelnicek.jidla.isNotEmpty &&
+ !jidelnicek.jidla.any((element) => element.objednano == true)) {
+ if (!mounted) break;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.noOrder),
+ duration: const Duration(seconds: 5),
+ action: SnackBarAction(
+ onPressed: () => setState(
+ () {
+ den = pristi.add(Duration(days: i + 1));
+ nactiJidlo();
+ },
+ ),
+ label: Languages.of(context)!.jump,
+ ),
+ ),
+ );
+ break;
+ }
+ }
+ }
+ }
+
+ Future nactiJidlo() async {
+ obsah = [const CircularProgressIndicator()];
+ switch (den.weekday) {
+ case 2:
+ denTydne = Languages.of(context)!.tuesday;
+ break;
+ case 3:
+ denTydne = Languages.of(context)!.wednesday;
+ break;
+ case 4:
+ denTydne = Languages.of(context)!.thursday;
+ break;
+ case 5:
+ denTydne = Languages.of(context)!.friday;
+ break;
+ case 6:
+ denTydne = Languages.of(context)!.saturday;
+ break;
+ case 7:
+ denTydne = Languages.of(context)!.sunday;
+ break;
+ default:
+ denTydne = Languages.of(context)!.monday;
+ }
+ widget.canteen.ziskejUzivatele().then((kr) {
+ kredit = kr.kredit;
+ widget.canteen.jidelnicekDen(den: den).then((jd) async {
+ setState(() {
+ obsah = [];
+ if (jd.jidla.isEmpty) {
+ obsah.add(Text(
+ Languages.of(context)!.noFood,
+ style: const TextStyle(fontSize: 15),
+ ));
+ } else {
+ for (var j in jd.jidla) {
+ obsah.add(
+ Padding(
+ padding: const EdgeInsets.only(top: 15),
+ child: InkWell(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(j.varianta),
+ const SizedBox(width: 10),
+ Flexible(
+ child: Text(
+ j.nazev,
+ ),
+ ),
+ Text((j.naBurze)
+ ? Languages.of(context)!.inExchange
+ : "${j.cena} Kč"),
+ Checkbox(
+ value: j.objednano,
+ fillColor: (j.lzeObjednat)
+ ? MaterialStateProperty.all(Colors.purple)
+ : MaterialStateProperty.all(Colors.grey),
+ onChanged: (v) async {
+ if (!j.lzeObjednat) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return CupertinoAlertDialog(
+ title: Text(Languages.of(context)!
+ .errorOrdering),
+ content: Text(
+ Languages.of(context)!.cannotOrder),
+ actions: [
+ CupertinoButton(
+ child:
+ Text(Languages.of(context)!.ok),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ )
+ ],
+ );
+ });
+ } else {
+ showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (_) => Dialog(
+ child: SizedBox(
+ height: 100,
+ child: Row(children: [
+ const Padding(
+ padding: EdgeInsets.all(10),
+ child:
+ CircularProgressIndicator(),
+ ),
+ Text(Languages.of(context)!
+ .ordering)
+ ]),
+ ),
+ ));
+ widget.canteen.objednat(j).then((_) {
+ Navigator.of(context, rootNavigator: true)
+ .pop();
+ nactiJidlo();
+ }).catchError((o) {
+ Navigator.of(context, rootNavigator: true)
+ .pop();
+ showDialog(
+ context: context,
+ builder: (bc) => CupertinoAlertDialog(
+ title: Text(Languages.of(context)!
+ .errorOrdering),
+ content: Text(o.toString()),
+ actions: [
+ CupertinoButton(
+ child: Text(
+ Languages.of(context)!
+ .close),
+ onPressed: () {
+ Navigator.pop(bc);
+ },
+ )
+ ],
+ ));
+ });
+ }
+ })
+ ],
+ ),
+ onTap: () async {
+ if (!j.lzeObjednat) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return CupertinoAlertDialog(
+ title:
+ Text(Languages.of(context)!.errorOrdering),
+ content:
+ Text(Languages.of(context)!.cannotOrder),
+ actions: [
+ CupertinoButton(
+ child: Text(Languages.of(context)!.ok),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ )
+ ],
+ );
+ });
+ } else {
+ showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (_) => Dialog(
+ child: SizedBox(
+ height: 100,
+ child: Row(children: [
+ const Padding(
+ padding: EdgeInsets.all(10),
+ child: CircularProgressIndicator(),
+ ),
+ Text(Languages.of(context)!.ordering)
+ ]),
+ ),
+ ));
+ widget.canteen.objednat(j).then((_) {
+ Navigator.of(context, rootNavigator: true).pop();
+ nactiJidlo();
+ }).catchError(
+ (o) {
+ Navigator.of(context, rootNavigator: true).pop();
+ showDialog(
+ context: context,
+ builder: (bc) => CupertinoAlertDialog(
+ title:
+ Text(Languages.of(context)!.errorOrdering),
+ content: Text(o.toString()),
+ actions: [
+ CupertinoButton(
+ child: Text(Languages.of(context)!.close),
+ onPressed: () {
+ Navigator.pop(bc);
+ },
+ )
+ ],
+ ),
+ );
+ },
+ );
+ }
+ },
+ onLongPress: () async {
+ if (!j.objednano || j.burzaUrl == null) return;
+ if (!j.naBurze) {
+ // pokud není na burze, radši se zeptáme
+ var d = await showDialog(
+ context: context,
+ builder: (bc) => SimpleDialog(
+ title: Text(
+ Languages.of(context)!.verifyExchange),
+ children: [
+ SimpleDialogOption(
+ onPressed: () {
+ Navigator.pop(bc, true);
+ },
+ child: Text(Languages.of(context)!.yes),
+ ),
+ SimpleDialogOption(
+ onPressed: () {
+ Navigator.pop(bc, false);
+ },
+ child: Text(Languages.of(context)!.no),
+ ),
+ ],
+ ));
+ if (d) {
+ widget.canteen
+ .doBurzy(j)
+ .then((_) => nactiJidlo())
+ .catchError((o) {
+ showDialog(
+ context: context,
+ builder: (bc) => CupertinoAlertDialog(
+ title: Text(
+ Languages.of(context)!.exchangeError),
+ content: Text(o.toString()),
+ actions: [
+ CupertinoButton(
+ child: Text(
+ Languages.of(context)!.close),
+ onPressed: () {
+ Navigator.pop(bc);
+ },
+ )
+ ],
+ ));
+ });
+ }
+ } else {
+ // jinak ne
+ widget.canteen.doBurzy(j).then((_) => nactiJidlo());
+ }
+ },
+ ),
+ ),
+ );
+ }
+ }
+ });
+ });
+ }).catchError((o) {
+ if (!widget.canteen.prihlasen) {
+ Navigator.pushReplacement(
+ context, MaterialPageRoute(builder: (c) => const IOSLogin()));
+ }
+ });
+ }
+
+ Future kliknuti(String value, BuildContext context) async {
+ if (value == Languages.of(context)!.signOut) {
+ await showDialog(
+ context: context,
+ builder: (c) => CupertinoAlertDialog(
+ title: Text(Languages.of(context)!.warning),
+ content: Text(Languages.of(context)!.signOutWarn),
+ actions: [
+ CupertinoButton(
+ onPressed: () {
+ const storage = FlutterSecureStorage();
+ storage.deleteAll();
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(builder: (c) => const IOSLogin()),
+ (route) => false);
+ },
+ child: Text(Languages.of(context)!.yes)),
+ CupertinoButton(
+ onPressed: () => Navigator.of(context).pop(),
+ child: Text(Languages.of(context)!.no))
+ ],
+ ),
+ );
+ } else if (value == Languages.of(context)!.review) {
+ launchUrl(
+ Uri.parse("https://apps.apple.com/cz/app/opencanteen/id1621124445"),
+ mode: LaunchMode.externalApplication);
+ } else if (value == Languages.of(context)!.reportBugs) {
+ launchUrl(Uri.parse("https://forms.gle/jKN7QeFJwpaApSbC8"),
+ mode: LaunchMode.externalApplication);
+ } else if (value == Languages.of(context)!.about) {
+ var packageInfo = await PackageInfo.fromPlatform();
+ if (!mounted) return;
+ showAboutDialog(
+ context: context,
+ applicationName: "OpenCanteen",
+ applicationLegalese:
+ "${Languages.of(context)!.copyright}\n${Languages.of(context)!.license}",
+ applicationVersion: packageInfo.version,
+ children: [
+ CupertinoButton(
+ onPressed: (() => launchUrl(
+ Uri.parse("https://git.mnau.xyz/hernik/opencanteen"))),
+ child: Text(Languages.of(context)!.source))
+ ]);
+ } else if (value == Languages.of(context)!.settings) {
+ Navigator.push(
+ context, MaterialPageRoute(builder: (c) => const IOSNastaveni()));
+ }
+ }
+
+ void nactiNastaveni() async {
+ var prefs = await SharedPreferences.getInstance();
+ _skipWeekend = prefs.getBool("skip") ?? false;
+ if (!mounted) return;
+ kontrolaTyden(context);
+ }
+
+ void ulozitDoOffline() async {
+ var prefs = await SharedPreferences.getInstance();
+ if (prefs.getBool("offline") ?? false) {
+ // vyčistit offline
+ Directory appDocDir = await getApplicationDocumentsDirectory();
+ for (var f in appDocDir.listSync()) {
+ if (f.path.contains("jidelnicek")) {
+ f.deleteSync();
+ }
+ }
+
+ // uložit *pocet* jídelníčků pro offline použití
+ var pocet = prefs.getInt("offline_pocet") ?? 1;
+ if (pocet > 7) pocet = 7;
+ for (var i = 0; i < pocet; i++) {
+ var d = den.add(Duration(days: i));
+ Jidelnicek? j;
+ try {
+ j = await widget.canteen.jidelnicekDen(den: d);
+ } catch (e) {
+ if (!widget.canteen.prihlasen) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text(Languages.of(context)!.errorSaving),
+ duration: const Duration(seconds: 5),
+ ));
+ break;
+ }
+ }
+ var soubor = File(
+ "${appDocDir.path}/jidelnicek_${d.year}-${d.month}-${d.day}.json");
+ soubor.createSync();
+ var jidla = [];
+ for (var jidlo in j!.jidla) {
+ jidla.add({
+ "nazev": jidlo.nazev,
+ "varianta": jidlo.varianta,
+ "objednano": jidlo.objednano,
+ "cena": jidlo.cena,
+ "naBurze": jidlo.naBurze,
+ "den": d.toString()
+ });
+ }
+ await soubor.writeAsString(json.encode(jidla));
+ }
+ }
+ }
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ nactiNastaveni();
+ ulozitDoOffline();
+ nactiJidlo();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ drawer: drawerGenerator(context, widget.canteen, 1),
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.menu),
+ actions: [
+ PopupMenuButton(
+ onSelected: ((String value) => kliknuti(value, context)),
+ itemBuilder: (BuildContext context) {
+ return {
+ Languages.of(context)!.reportBugs,
+ Languages.of(context)!.review,
+ Languages.of(context)!.settings,
+ Languages.of(context)!.about,
+ Languages.of(context)!.signOut
+ }.map((String choice) {
+ return PopupMenuItem(
+ value: choice,
+ child: Text(choice),
+ );
+ }).toList();
+ },
+ ),
+ ],
+ ),
+ body: RefreshIndicator(
+ onRefresh: nactiJidlo,
+ child: Center(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width - 45,
+ child: Column(
+ children: [
+ const SizedBox(height: 10),
+ Text("${Languages.of(context)!.balance}$kredit Kč"),
+ Row(mainAxisAlignment: MainAxisAlignment.center, children: [
+ IconButton(
+ onPressed: () {
+ setState(() {
+ den = den.subtract(const Duration(days: 1));
+ if (den.weekday == 7 && _skipWeekend) {
+ den = den.subtract(const Duration(days: 2));
+ }
+ nactiJidlo();
+ });
+ },
+ icon: const Icon(Icons.arrow_left)),
+ CupertinoButton(
+ onPressed: () async {
+ await showCupertinoModalPopup(
+ context: context,
+ builder: (c) => Container(
+ height: 216,
+ padding: const EdgeInsets.only(top: 6),
+ margin: EdgeInsets.only(
+ bottom: MediaQuery.of(context).viewInsets.bottom,
+ ),
+ color: CupertinoColors.systemBackground
+ .resolveFrom(context),
+ child: SafeArea(
+ top: false,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.date,
+ onDateTimeChanged: (t) {
+ den = t;
+ },
+ ),
+ ),
+ ),
+ );
+ nactiJidlo();
+ },
+ child: Text(
+ "${den.day}. ${den.month}. ${den.year} - $denTydne")),
+ IconButton(
+ onPressed: () {
+ setState(() {
+ den = den.add(const Duration(days: 1));
+ if (den.weekday == 6 && _skipWeekend) {
+ den = den.add(const Duration(days: 2));
+ }
+ nactiJidlo();
+ });
+ },
+ icon: const Icon(Icons.arrow_right),
+ ),
+ IconButton(
+ onPressed: () => setState(() {
+ den = DateTime.now();
+ nactiJidlo();
+ }),
+ icon: const Icon(Icons.today))
+ ]),
+ SingleChildScrollView(
+ physics: const AlwaysScrollableScrollPhysics(),
+ child: GestureDetector(
+ child: Container(
+ color: Theme.of(context)
+ .colorScheme
+ .onPrimary
+ .withOpacity(0),
+ height: MediaQuery.of(context).size.height / 1.3,
+ child: Column(children: obsah),
+ ),
+ onHorizontalDragEnd: (details) {
+ if (details.primaryVelocity?.compareTo(0) == -1) {
+ setState(() {
+ den = den.add(const Duration(days: 1));
+ if (den.weekday == 6 && _skipWeekend) {
+ den = den.add(const Duration(days: 2));
+ }
+ nactiJidlo();
+ });
+ } else {
+ setState(() {
+ den = den.subtract(const Duration(days: 1));
+ if (den.weekday == 7 && _skipWeekend) {
+ den = den.subtract(const Duration(days: 2));
+ }
+ nactiJidlo();
+ });
+ }
+ },
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/okna/ios/login.dart b/lib/okna/ios/login.dart
new file mode 100644
index 0000000..b3bf79b
--- /dev/null
+++ b/lib/okna/ios/login.dart
@@ -0,0 +1,282 @@
+import 'dart:io';
+
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:opencanteen/okna/ios/welcome.dart';
+
+import '../../lang/lang.dart';
+import '../../loginmanager.dart';
+import '../../main.dart';
+import '../../util.dart';
+import 'jidelnicek.dart';
+import 'offline_jidelnicek.dart';
+
+class IOSLogin extends StatefulWidget {
+ const IOSLogin({Key? key}) : super(key: key);
+ @override
+ State createState() => _IOSLoginState();
+}
+
+class _IOSLoginState extends State {
+ TextEditingController userControl = TextEditingController();
+ TextEditingController passControl = TextEditingController();
+ TextEditingController canteenControl = TextEditingController();
+ bool rememberMe = false;
+ bool _showUrl = false;
+ String dropdownUrl = instance.first["url"] ?? "";
+
+ @override
+ void initState() {
+ super.initState();
+ LoginManager.getDetails().then((r) async {
+ // žádat o oprávnění na iOS
+ await flutterLocalNotificationsPlugin
+ .resolvePlatformSpecificImplementation<
+ IOSFlutterLocalNotificationsPlugin>()
+ ?.requestPermissions(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+
+ if (r != null) {
+ // Automaticky přihlásit
+ showDialog(
+ context: context,
+ barrierDismissible: false,
+ builder: (_) => Dialog(
+ child: SizedBox(
+ height: 100,
+ child: Row(children: [
+ const Padding(
+ padding: EdgeInsets.all(10),
+ child: CircularProgressIndicator(),
+ ),
+ Text(Languages.of(context)!.loggingIn)
+ ]),
+ ),
+ ));
+ var canteen = Canteen(r["url"]!);
+ try {
+ var l = await canteen.login(r["user"]!, r["pass"]!);
+ if (!l) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.loginFailed),
+ ),
+ );
+ return;
+ }
+ const storage = FlutterSecureStorage();
+ var odsouhlasil = await storage.read(key: "oc_souhlas");
+ if (!mounted) return;
+ if (odsouhlasil == null || odsouhlasil != "ano") {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (c) => IOSWelcome(canteen: canteen),
+ ),
+ (route) => false);
+ } else {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (context) => IOSJidelnicek(canteen: canteen),
+ ),
+ (route) => false);
+ }
+ } on PlatformException {
+ if (!mounted) return;
+ Navigator.of(context).pop();
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.corrupted),
+ ),
+ );
+ } catch (_) {
+ if (!mounted) return;
+ Navigator.of(context).pop();
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.errorContacting),
+ ),
+ );
+ goOffline();
+ }
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.logIn),
+ automaticallyImplyLeading: false,
+ ),
+ body: Center(
+ child: SingleChildScrollView(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width - 50,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ Languages.of(context)!.appName,
+ textAlign: TextAlign.center,
+ style: const TextStyle(
+ fontWeight: FontWeight.bold, fontSize: 40),
+ ),
+ Text(
+ Languages.of(context)!.logIn,
+ textAlign: TextAlign.center,
+ ),
+ CupertinoTextField(
+ controller: userControl,
+ autofillHints: const [AutofillHints.username],
+ prefix: Text(Languages.of(context)!.username),
+ ),
+ CupertinoTextField(
+ autofillHints: const [AutofillHints.password],
+ prefix: Text(Languages.of(context)!.password),
+ controller: passControl,
+ obscureText: true,
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+ DropdownButton(
+ isExpanded: true,
+ value: dropdownUrl,
+ items: instance.map>((e) {
+ return DropdownMenuItem(
+ value: e["url"],
+ child: Text(e["name"]!),
+ );
+ }).toList(),
+ onChanged: (String? value) {
+ setState(() {
+ if (value == "") {
+ _showUrl = true;
+ } else {
+ _showUrl = false;
+ }
+ dropdownUrl = value!;
+ });
+ },
+ ),
+ AnimatedOpacity(
+ opacity: _showUrl ? 1.0 : 0.0,
+ duration: const Duration(milliseconds: 300),
+ child: TextField(
+ autofillHints: const [AutofillHints.url],
+ decoration: InputDecoration(
+ labelText: Languages.of(context)!.iCanteenUrl),
+ keyboardType: TextInputType.url,
+ controller: canteenControl,
+ ),
+ ),
+ Row(mainAxisAlignment: MainAxisAlignment.center, children: [
+ CupertinoSwitch(
+ value: rememberMe,
+ onChanged: (value) {
+ setState(() {
+ rememberMe = value;
+ });
+ }),
+ Text(Languages.of(context)!.rememberMe)
+ ]),
+ CupertinoButton(
+ onPressed: () async {
+ var canteenUrl = (dropdownUrl == "")
+ ? canteenControl.text
+ : dropdownUrl;
+ if (!canteenUrl.startsWith("https://") &&
+ !canteenUrl.startsWith("http://")) {
+ canteenUrl = "https://$canteenUrl";
+ }
+ var canteen = Canteen(canteenUrl);
+ try {
+ var l = await canteen.login(
+ userControl.text, passControl.text);
+ if (!l) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content:
+ Text(Languages.of(context)!.loginFailed),
+ ),
+ );
+ return;
+ }
+ if (rememberMe) {
+ LoginManager.setDetails(
+ userControl.text, passControl.text, canteenUrl);
+ }
+ // souhlas
+ const storage = FlutterSecureStorage();
+ var odsouhlasil =
+ await storage.read(key: "oc_souhlas");
+ if (!mounted) return;
+ if (odsouhlasil == null || odsouhlasil != "ano") {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (c) => IOSWelcome(
+ canteen: canteen,
+ )),
+ (route) => false);
+ } else {
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(
+ builder: (context) =>
+ IOSJidelnicek(canteen: canteen)),
+ (route) => false);
+ }
+ } on PlatformException {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(Languages.of(context)!.corrupted),
+ ),
+ );
+ } on Exception catch (_) {
+ if (!mounted) return;
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content:
+ Text(Languages.of(context)!.errorContacting),
+ ),
+ );
+ goOffline();
+ }
+ },
+ child: Text(Languages.of(context)!.logIn)),
+ ],
+ ),
+ ),
+ ),
+ ));
+ }
+
+ /// Získá offline soubor a zobrazí údaje
+ void goOffline() async {
+ if (!mounted) return;
+ Navigator.pushAndRemoveUntil(
+ context,
+ MaterialPageRoute(builder: ((context) => const IOSOfflineJidelnicek())),
+ (route) => false);
+ }
+}
diff --git a/lib/okna/ios/nastaveni.dart b/lib/okna/ios/nastaveni.dart
new file mode 100644
index 0000000..d0da422
--- /dev/null
+++ b/lib/okna/ios/nastaveni.dart
@@ -0,0 +1,282 @@
+import 'dart:io';
+
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:flutter_native_timezone/flutter_native_timezone.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:timezone/timezone.dart' as tz;
+
+import '../../lang/lang.dart';
+import '../../loginmanager.dart';
+import '../../main.dart';
+import '../../util.dart';
+
+class IOSNastaveni extends StatefulWidget {
+ const IOSNastaveni({Key? key}) : super(key: key);
+
+ @override
+ State createState() => _IOSNastaveniState();
+}
+
+class _IOSNastaveniState extends State {
+ bool _ukladatOffline = false;
+ bool _preskakovatVikend = false;
+ bool _kontrolovatTyden = false;
+ bool _oznameniObed = false;
+ bool _zapamatovany = false;
+ TimeOfDay _oznameniCas = TimeOfDay.now();
+ final TextEditingController _countController =
+ TextEditingController(text: "1");
+ SharedPreferences? preferences;
+ void najitNastaveni() async {
+ preferences = await SharedPreferences.getInstance();
+ _zapamatovany = await LoginManager.zapamatovat();
+ setState(() {
+ _ukladatOffline = preferences!.getBool("offline") ?? false;
+ _preskakovatVikend = preferences!.getBool("skip") ?? false;
+ _kontrolovatTyden = preferences!.getBool("tyden") ?? false;
+ _oznameniObed = preferences!.getBool("oznamit") ?? false;
+ _countController.text =
+ (preferences!.getInt("offline_pocet") ?? 1).toString();
+ var casStr = preferences!.getString("oznameni_cas");
+ if (casStr == null) {
+ var now = DateTime.now();
+ _oznameniCas = TimeOfDay.fromDateTime(
+ DateTime.now().add(const Duration(hours: 1)));
+ preferences!.setString("oznameni_cas", now.toString());
+ } else {
+ _oznameniCas = TimeOfDay.fromDateTime(DateTime.parse(casStr));
+ }
+ });
+ }
+
+ void zmenitNastaveni(String key, bool value) async {
+ preferences!.setBool(key, value);
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ najitNastaveni();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.settings),
+ ),
+ body: Center(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width / 1.1,
+ child: Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(Languages.of(context)!.saveOffline),
+ CupertinoSwitch(
+ activeColor: Colors.purple,
+ value: _ukladatOffline,
+ onChanged: (value) {
+ setState(() {
+ _ukladatOffline = value;
+ cistit(value);
+ zmenitNastaveni("offline", value);
+ });
+ })
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(Languages.of(context)!.saveCount),
+ SizedBox(
+ width: 35,
+ child: CupertinoTextField(
+ controller: _countController,
+ enabled: _ukladatOffline,
+ keyboardType: TextInputType.number,
+ inputFormatters: [FilteringTextInputFormatter.digitsOnly],
+ onChanged: (c) {
+ var cislo = int.tryParse(c);
+ if (cislo != null) {
+ preferences!.setInt("offline_pocet", cislo);
+ }
+ },
+ ),
+ )
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(Languages.of(context)!.skipWeekend),
+ CupertinoSwitch(
+ activeColor: Colors.purple,
+ value: _preskakovatVikend,
+ onChanged: (value) {
+ setState(() {
+ _preskakovatVikend = value;
+ zmenitNastaveni("skip", value);
+ });
+ })
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Flexible(child: Text(Languages.of(context)!.checkOrdered)),
+ CupertinoSwitch(
+ activeColor: Colors.purple,
+ value: _kontrolovatTyden,
+ onChanged: (value) {
+ setState(() {
+ _kontrolovatTyden = value;
+ zmenitNastaveni("tyden", value);
+ });
+ })
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Flexible(child: Text(Languages.of(context)!.notifyLunch)),
+ CupertinoSwitch(
+ activeColor: Colors.purple,
+ value: _oznameniObed,
+ onChanged: (value) {
+ if (!_zapamatovany) {
+ showDialog(
+ context: context,
+ builder: (bc) => CupertinoAlertDialog(
+ title: Text(Languages.of(context)!.error),
+ content:
+ Text(Languages.of(context)!.needRemember),
+ actions: [
+ CupertinoButton(
+ child: Text(Languages.of(context)!.ok),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ )
+ ],
+ ));
+ } else {
+ setState(() {
+ _oznameniObed = value;
+ if (_oznameniObed) {
+ showDialog(
+ context: context,
+ builder: (context) => CupertinoAlertDialog(
+ title:
+ Text(Languages.of(context)!.warning),
+ content: Text(
+ Languages.of(context)!.notifyWarning),
+ actions: [
+ CupertinoButton(
+ child:
+ Text(Languages.of(context)!.ok),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ )
+ ],
+ ));
+ vytvoritOznameni(casNaDate(_oznameniCas));
+ }
+ zmenitNastaveni("oznamit", value);
+ });
+ }
+ })
+ ],
+ ),
+ Text(Languages.of(context)!.notifyAt),
+ CupertinoButton(
+ onPressed: () async {
+ if (_oznameniObed) {
+ showCupertinoModalPopup(
+ context: context,
+ builder: (c) {
+ return Container(
+ height: 216,
+ padding: const EdgeInsets.only(top: 6),
+ margin: EdgeInsets.only(
+ bottom: MediaQuery.of(context).viewInsets.bottom,
+ ),
+ color: CupertinoColors.systemBackground
+ .resolveFrom(context),
+ child: SafeArea(
+ top: false,
+ child: CupertinoDatePicker(
+ mode: CupertinoDatePickerMode.time,
+ onDateTimeChanged: (cas) {
+ setState(() {
+ _oznameniCas = TimeOfDay.fromDateTime(cas);
+ });
+ },
+ ),
+ ),
+ );
+ },
+ );
+ }
+ },
+ child: Text(
+ "${(_oznameniCas.hour < 10 ? "0" : "") + _oznameniCas.hour.toString()}:${(_oznameniCas.minute < 10 ? "0" : "") + _oznameniCas.minute.toString()}",
+ style: TextStyle(
+ color: (!_oznameniObed) ? Colors.grey : Colors.purple),
+ ),
+ ),
+ ],
+ ),
+ )),
+ );
+ }
+
+ void cistit(bool value) async {
+ if (!value) {
+ Directory appDocDir = await getApplicationDocumentsDirectory();
+ for (var f in appDocDir.listSync()) {
+ // Vymažeme obsah
+ if (f.path.contains("jidelnicek")) {
+ f.deleteSync();
+ }
+ }
+ }
+ }
+
+ void vytvoritOznameni(DateTime den) async {
+ await flutterLocalNotificationsPlugin.cancelAll();
+ var d = await LoginManager.getDetails(); // získat údaje
+ if (d != null) {
+ // Nové oznámení
+ var c = Canteen(d["url"]!);
+ if (await c.login(d["user"]!, d["pass"]!)) {
+ var jidla = await c.jidelnicekDen();
+ try {
+ var jidlo = jidla.jidla.singleWhere((element) => element.objednano);
+ var l =
+ tz.getLocation(await FlutterNativeTimezone.getLocalTimezone());
+ if (!mounted) return;
+ await flutterLocalNotificationsPlugin.zonedSchedule(
+ // Vytvoří nové oznámení pro daný čas a datum
+ 0,
+ Languages.of(context)!.lunchNotif,
+ "${jidlo.varianta} - ${jidlo.nazev}",
+ tz.TZDateTime.from(den, l),
+ const NotificationDetails(),
+ androidAllowWhileIdle: true,
+ uiLocalNotificationDateInterpretation:
+ UILocalNotificationDateInterpretation.absoluteTime);
+ } on StateError catch (_) {
+ // nenalezeno
+ }
+ }
+ }
+ }
+}
diff --git a/lib/okna/ios/offline_jidelnicek.dart b/lib/okna/ios/offline_jidelnicek.dart
new file mode 100644
index 0000000..23bdbc6
--- /dev/null
+++ b/lib/okna/ios/offline_jidelnicek.dart
@@ -0,0 +1,265 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:opencanteen/okna/ios/login.dart';
+import 'package:opencanteen/util.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+import '../../lang/lang.dart';
+
+class IOSOfflineJidelnicek extends StatefulWidget {
+ const IOSOfflineJidelnicek({Key? key}) : super(key: key);
+ @override
+ State createState() => _IOSOfflineJidelnicekState();
+}
+
+class _IOSOfflineJidelnicekState extends State {
+ List obsah = [const CircularProgressIndicator()];
+ var _skipWeekend = false;
+ DateTime den = DateTime.now();
+ String denTydne = "";
+ List> data = [];
+ var jidloIndex = 0;
+
+ void nactiZeSouboru() async {
+ Directory appDocDir = await getApplicationDocumentsDirectory();
+ for (var f in appDocDir.listSync()) {
+ if (f.path.contains("jidelnicek")) {
+ var soubor = File(f.path);
+ var input = await soubor.readAsString();
+ var r = jsonDecode(input);
+ List jidla = [];
+ for (var j in r) {
+ jidla.add(OfflineJidlo(
+ nazev: j["nazev"],
+ varianta: j["varianta"],
+ objednano: j["objednano"],
+ cena: j["cena"],
+ naBurze: j["naBurze"],
+ den: DateTime.parse(j["den"])));
+ }
+ data.add(jidla);
+ }
+ }
+ nactiJidlo();
+ }
+
+ Future nactiJidlo() async {
+ var jidelnicek = data[jidloIndex];
+ den = jidelnicek[0].den;
+ switch (den.weekday) {
+ case 2:
+ denTydne = Languages.of(context)!.tuesday;
+ break;
+ case 3:
+ denTydne = Languages.of(context)!.wednesday;
+ break;
+ case 4:
+ denTydne = Languages.of(context)!.thursday;
+ break;
+ case 5:
+ denTydne = Languages.of(context)!.friday;
+ break;
+ case 6:
+ denTydne = Languages.of(context)!.saturday;
+ break;
+ case 7:
+ denTydne = Languages.of(context)!.sunday;
+ break;
+ default:
+ denTydne = Languages.of(context)!.monday;
+ }
+ obsah = [];
+ for (OfflineJidlo j in jidelnicek) {
+ obsah.add(
+ Padding(
+ padding: const EdgeInsets.only(top: 15),
+ child: InkWell(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(j.varianta),
+ const SizedBox(width: 10),
+ Flexible(
+ child: Text(
+ j.nazev,
+ ),
+ ),
+ Text((j.naBurze)
+ ? Languages.of(context)!.inExchange
+ : "${j.cena} Kč"),
+ Checkbox(
+ value: j.objednano,
+ fillColor: MaterialStateProperty.all(Colors.grey),
+ onChanged: (v) async {
+ return;
+ },
+ )
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+ setState(() {});
+ }
+
+ void kliknuti(String value, BuildContext context) async {
+ if (value == Languages.of(context)!.signOut) {
+ const storage = FlutterSecureStorage();
+ storage.deleteAll();
+ Navigator.pushReplacement(
+ context, MaterialPageRoute(builder: (c) => const IOSLogin()));
+ } else if (value == Languages.of(context)!.review) {
+ launchUrl(
+ Uri.parse("https://apps.apple.com/cz/app/opencanteen/id1621124445"),
+ mode: LaunchMode.externalApplication);
+ } else if (value == Languages.of(context)!.reportBugs) {
+ launchUrl(Uri.parse("https://forms.gle/jKN7QeFJwpaApSbC8"),
+ mode: LaunchMode.externalApplication);
+ } else if (value == Languages.of(context)!.about) {
+ var packageInfo = await PackageInfo.fromPlatform();
+ if (!mounted) return;
+ showAboutDialog(
+ context: context,
+ applicationName: "OpenCanteen",
+ applicationLegalese:
+ "${Languages.of(context)!.copyright}\n${Languages.of(context)!.license}",
+ applicationVersion: packageInfo.version,
+ children: [
+ CupertinoButton(
+ onPressed: (() => launchUrl(
+ Uri.parse("https://git.mnau.xyz/hernik/opencanteen"))),
+ child: Text(Languages.of(context)!.source))
+ ]);
+ }
+ }
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ nactiNastaveni();
+ }
+
+ void nactiNastaveni() async {
+ var prefs = await SharedPreferences.getInstance();
+ _skipWeekend = prefs.getBool("skip") ?? false;
+ if (!mounted) return;
+ nactiZeSouboru();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(Languages.of(context)!.menu),
+ automaticallyImplyLeading: false,
+ actions: [
+ PopupMenuButton(
+ onSelected: ((String value) => kliknuti(value, context)),
+ itemBuilder: (BuildContext context) {
+ return {
+ Languages.of(context)!.reportBugs,
+ Languages.of(context)!.review,
+ Languages.of(context)!.about,
+ Languages.of(context)!.signOut
+ }.map((String choice) {
+ return PopupMenuItem(
+ value: choice,
+ child: Text(choice),
+ );
+ }).toList();
+ },
+ ),
+ ],
+ ),
+ body: RefreshIndicator(
+ child: Center(
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width - 50,
+ child: Column(
+ children: [
+ const SizedBox(height: 10),
+ Text(
+ Languages.of(context)!.offline,
+ style: const TextStyle(fontWeight: FontWeight.bold),
+ ),
+ Text(Languages.of(context)!.mustLogout),
+ const SizedBox(height: 10),
+ Row(mainAxisAlignment: MainAxisAlignment.center, children: [
+ IconButton(
+ onPressed: () {
+ if (data.length <= 1) return;
+ obsah = [const CircularProgressIndicator()];
+ setState(() {
+ if (den.weekday == 1 && _skipWeekend) {
+ // pokud je pondělí a chceme přeskočit víkend
+ if (jidloIndex - 2 >= 0) {
+ jidloIndex -= data.length - 3;
+ } else {
+ jidloIndex = data.length - 1;
+ }
+ } else if (jidloIndex == 0) {
+ jidloIndex = data.length - 1;
+ } else {
+ jidloIndex -= 1;
+ }
+
+ nactiJidlo();
+ });
+ },
+ icon: const Icon(Icons.arrow_left)),
+ CupertinoButton(
+ onPressed: () async {},
+ child: Text(
+ "${den.day}. ${den.month}. ${den.year} - $denTydne")),
+ IconButton(
+ onPressed: () {
+ if (data.length <= 1) return;
+ obsah = [const CircularProgressIndicator()];
+ setState(() {
+ if (den.weekday == 5 && _skipWeekend) {
+ // pokud je pondělí a chceme přeskočit víkend
+ if (jidloIndex + 2 <= data.length - 1) {
+ jidloIndex += 2;
+ } else {
+ jidloIndex = 0;
+ }
+ } else if (jidloIndex == data.length) {
+ jidloIndex = 0;
+ } else {
+ jidloIndex += 1;
+ }
+ nactiJidlo();
+ });
+ },
+ icon: const Icon(Icons.arrow_right),
+ ),
+ IconButton(
+ onPressed: () {
+ jidloIndex = 0;
+ },
+ icon: const Icon(Icons.today))
+ ]),
+ SingleChildScrollView(
+ physics: const AlwaysScrollableScrollPhysics(),
+ child: Column(
+ children: obsah,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ onRefresh: () => Navigator.pushReplacement(context,
+ MaterialPageRoute(builder: ((context) => const IOSLogin()))),
+ ),
+ );
+ }
+}
diff --git a/lib/okna/ios/welcome.dart b/lib/okna/ios/welcome.dart
new file mode 100644
index 0000000..c2bef07
--- /dev/null
+++ b/lib/okna/ios/welcome.dart
@@ -0,0 +1,78 @@
+import 'package:canteenlib/canteenlib.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:introduction_screen/introduction_screen.dart';
+import 'package:opencanteen/lang/lang.dart';
+import 'package:opencanteen/okna/ios/jidelnicek.dart';
+
+class IOSWelcome extends StatefulWidget {
+ const IOSWelcome({Key? key, required this.canteen}) : super(key: key);
+
+ final Canteen canteen;
+
+ @override
+ State createState() => _IOSWelcomeState();
+}
+
+class _IOSWelcomeState extends State {
+ @override
+ Widget build(BuildContext context) {
+ var listPagesViewModel = [
+ PageViewModel(
+ title: Languages.of(context)!.welcome,
+ body: Languages.of(context)!.appDesc,
+ image: const Center(
+ child: Icon(Icons.waving_hand_outlined, size: 175),
+ ),
+ ),
+ PageViewModel(
+ title: Languages.of(context)!.aboutOrder,
+ body: Languages.of(context)!.howOrder,
+ image: Center(
+ child: Image.asset('assets/objednavam.png',
+ width: MediaQuery.of(context).size.width * 0.85),
+ ),
+ ),
+ PageViewModel(
+ title: Languages.of(context)!.aboutToExch,
+ body: Languages.of(context)!.howToExch,
+ image: Center(
+ child: Image.asset('assets/doburzy.png',
+ width: MediaQuery.of(context).size.width * 0.85),
+ ),
+ ),
+ PageViewModel(
+ title: Languages.of(context)!.aboutFromExch,
+ body: Languages.of(context)!.howFromExch,
+ image: Center(
+ child: Image.asset('assets/burza.png',
+ width: MediaQuery.of(context).size.width * 0.85),
+ ),
+ ),
+ PageViewModel(
+ title: Languages.of(context)!.warning,
+ body: Languages.of(context)!.notOfficial,
+ image: const Center(
+ child: Icon(Icons.warning_amber_outlined, size: 175),
+ ),
+ ),
+ ];
+ return Scaffold(
+ body: IntroductionScreen(
+ pages: listPagesViewModel,
+ next: Text(Languages.of(context)!.next),
+ done: Text(Languages.of(context)!.ok,
+ style: const TextStyle(fontWeight: FontWeight.w600)),
+ onDone: () async {
+ const storage = FlutterSecureStorage();
+ await storage.write(key: "oc_souhlas", value: "ano");
+ if (!mounted) return;
+ Navigator.of(context).pushAndRemoveUntil(
+ MaterialPageRoute(
+ builder: (c) => IOSJidelnicek(canteen: widget.canteen)),
+ (route) => false);
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/util.dart b/lib/util.dart
index adc34fa..bce7f90 100644
--- a/lib/util.dart
+++ b/lib/util.dart
@@ -1,13 +1,14 @@
+import 'dart:io';
+
import 'package:canteenlib/canteenlib.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart';
-import 'package:opencanteen/okna/burza.dart';
-
+import 'package:opencanteen/okna/android/burza.dart';
+import 'package:opencanteen/okna/android/jidelnicek.dart';
+import 'package:opencanteen/okna/ios/burza.dart';
+import 'package:opencanteen/okna/ios/jidelnicek.dart';
import 'lang/lang.dart';
-import 'okna/jidelnicek.dart';
-Drawer drawerGenerator(BuildContext context, Canteen canteen, int p,
- FlutterLocalNotificationsPlugin n) {
+Drawer drawerGenerator(BuildContext context, Canteen canteen, int p) {
Drawer drawer = const Drawer();
switch (p) {
case 1:
@@ -30,7 +31,9 @@ Drawer drawerGenerator(BuildContext context, Canteen canteen, int p,
onTap: () => Navigator.push(
context,
MaterialPageRoute(
- builder: (context) => BurzaPage(canteen: canteen, n: n),
+ builder: (context) => (Platform.isAndroid)
+ ? AndroidBurza(canteen: canteen)
+ : IOSBurza(canteen: canteen),
),
),
),
@@ -52,7 +55,9 @@ Drawer drawerGenerator(BuildContext context, Canteen canteen, int p,
onTap: () => Navigator.push(
context,
MaterialPageRoute(
- builder: (c) => JidelnicekPage(canteen: canteen, n: n))),
+ builder: (c) => (Platform.isAndroid)
+ ? AndroidJidelnicek(canteen: canteen)
+ : IOSJidelnicek(canteen: canteen))),
),
ListTile(
leading: const Icon(Icons.store),
diff --git a/metadata/cs-CZ/changelogs/25.txt b/metadata/cs-CZ/changelogs/25.txt
new file mode 100644
index 0000000..9fa724c
--- /dev/null
+++ b/metadata/cs-CZ/changelogs/25.txt
@@ -0,0 +1,2 @@
+- Optimalizace ze strany kodu
+- Úpravy vzhledu
\ No newline at end of file
diff --git a/metadata/en-US/changelogs/25.txt b/metadata/en-US/changelogs/25.txt
new file mode 100644
index 0000000..62fe449
--- /dev/null
+++ b/metadata/en-US/changelogs/25.txt
@@ -0,0 +1,2 @@
+- Code optimization
+- Theme edits
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
index d258dce..d2938c4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,7 @@ publish_to: 'none'
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
-version: 1.5.1+24
+version: 1.6.0+25
environment:
sdk: ">=2.16.1 <3.0.0"