From 27f3f40c74d481a6f894a340625dafff3e3adf66 Mon Sep 17 00:00:00 2001 From: tpkowastaken Date: Wed, 25 Sep 2024 22:53:46 +0200 Subject: [PATCH 01/57] removed messaging --- lib/src/_global/app.dart | 35 ------- lib/src/_global/init_app.dart | 1 - lib/src/_messaging/messaging.dart | 92 ------------------- lib/src/_messaging/messaging_provider.dart | 22 ----- lib/src/_routing/app_router.dart | 7 -- lib/src/_routing/guards.dart | 53 ----------- lib/src/ui/material_app.dart | 2 - lib/src/ui/pages/debug_page.dart | 5 - lib/src/ui/pages/request_permission_page.dart | 14 --- macos/Flutter/GeneratedPluginRegistrant.swift | 2 - pubspec.lock | 24 ----- pubspec.yaml | 1 - web/firebase-messaging-sw.js | 18 ---- web/index.html | 10 +- 14 files changed, 1 insertion(+), 285 deletions(-) delete mode 100644 lib/src/_messaging/messaging.dart delete mode 100644 lib/src/_messaging/messaging_provider.dart delete mode 100644 lib/src/_routing/guards.dart delete mode 100644 web/firebase-messaging-sw.js diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index 493a7fc7..6983b84a 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -1,8 +1,6 @@ import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_global/providers/remote_config.dart'; -import 'package:autojidelna/src/_messaging/messaging.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -30,7 +28,6 @@ class App { static bool _initRemoteConfigExecuted = false; static bool _initHiveExecuted = false; static bool _initRotationExecuted = false; - static bool _initFirebaseMessagingExecuted = false; static bool _initCodePushExecuted = false; static Future initCodePush() async { @@ -108,38 +105,6 @@ class App { secureStorage = const FlutterSecureStorage(); } - static Future initFirebaseMessaging() async { - assert(_initFirebaseMessagingExecuted == false, 'App.initFirebaseMessaging() must be called only once'); - if (_initFirebaseMessagingExecuted) return; - if (!kIsWeb) { - NotificationSettings settings = await FirebaseMessaging.instance.getNotificationSettings(); - await Messaging.setupInteractedMessage(); - FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); - FirebaseMessaging.onMessage.listen(Messaging.handleMessage); - - if (settings.authorizationStatus == AuthorizationStatus.notDetermined && - Hive.box(Boxes.settings).get(HiveKeys.shouldAskForNotificationPermission, defaultValue: true)) { - App.shouldAskForNotification = true; - } else { - App.shouldAskForNotification = false; - } - - if (settings.authorizationStatus == AuthorizationStatus.authorized || settings.authorizationStatus == AuthorizationStatus.provisional) { - await Messaging.onNotificationPermissionGranted(); - } - } else if (Hive.box(Boxes.settings).get(HiveKeys.shouldAskForNotificationPermission, defaultValue: true)) { - App.shouldAskForNotification = true; - } else { - App.shouldAskForNotification = false; - } - - if (kIsWeb && Hive.box(Boxes.settings).get(HiveKeys.webNotificationsAccepted, defaultValue: false)) { - await Messaging.onNotificationPermissionGranted(); - } - - _initFirebaseMessagingExecuted = true; - } - static late final FlutterSecureStorage secureStorage; static late final FirebaseRemoteConfig remoteConfig; diff --git a/lib/src/_global/init_app.dart b/lib/src/_global/init_app.dart index 2421b388..c4a55090 100644 --- a/lib/src/_global/init_app.dart +++ b/lib/src/_global/init_app.dart @@ -15,7 +15,6 @@ class InitApp { await App.initRemoteConfig(); await Future.wait([ App.initLocalization(), - App.initFirebaseMessaging(), App.initSecureStorage(), App.initPlatform(), App.initRotation(), diff --git a/lib/src/_messaging/messaging.dart b/lib/src/_messaging/messaging.dart deleted file mode 100644 index 962f8da7..00000000 --- a/lib/src/_messaging/messaging.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:autojidelna/src/_conf/hive.dart'; -import 'package:autojidelna/src/_conf/messaging.dart'; -import 'package:autojidelna/src/_conf/tokens.dart'; -import 'package:autojidelna/src/_messaging/exponential_backoff.dart'; -import 'package:autojidelna/src/_messaging/messaging_provider.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hive/hive.dart'; - -class Messaging { - // ignore: cancel_subscriptions - static StreamSubscription? onTokenRefresh; - //. /\ - // | - // As for firebase docs there is no need to cancel this subscription. - // It dies along with the app being closed. - - static RemoteMessage? currentMessage; - static String? fcmToken; - static String? apnsToken; - static bool grantedPermission = false; - static MessagingProvider messagingProvider = MessagingProvider(); - - static Future onNotificationPermissionGranted() async { - grantedPermission = true; - if (kIsWeb) unawaited(Hive.box(Boxes.settings).put(HiveKeys.webNotificationsAccepted, true)); - if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) { - final apnsTokenLocal = - await retryWithExponentialBackoff(() async => await FirebaseMessaging.instance.getAPNSToken(), ignoreError: true, infinite: true); - if (apnsTokenLocal == null) { - return; - } - apnsToken = apnsTokenLocal; - } - final fcmToken = await retryWithExponentialBackoff( - () async { - final token = await FirebaseMessaging.instance.getToken(vapidKey: kIsWeb ? Tokens.messagingVapidToken : null); - if (token == null) { - throw Exception('Token is null'); - } - return token; - }, - infinite: true, - ); - await onSuccessfulToken(fcmToken); - } - - static Future onSuccessfulToken(String token) async { - onTokenRefresh ??= FirebaseMessaging.instance.onTokenRefresh.listen( - (fcmToken) { - onSuccessfulToken(fcmToken); - }, - onError: (_) => null, - ); - retryWithExponentialBackoff( - () async => await FirebaseMessaging.instance.subscribeToTopic(MessagingConf.allTopic), - ignoreError: true, - infinite: true, - ); - fcmToken = token; - - // Save the token to the server - // Here will be the code to save the token to the server (for instance a REST API call to a go server or a ) - } - - static Future setupInteractedMessage() async { - // Get any messages which caused the application to open from - // a terminated state. - final message = await FirebaseMessaging.instance.getInitialMessage(); - if (message != null) { - messagingProvider.handleNotificationMessage(message); - } - } - - static Future handleMessage(RemoteMessage message) async { - // Handle the message in foreground. - // This should popup a notification (not the native one, something like instagram has) - return; - } -} - -@pragma('vm:entry-point') -Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { - // If you're going to use other Firebase services in the background, such as Firestore, - // make sure you call `initializeApp` before using other Firebase services. - // This should send out a notification to the user or perform a quick fetch - - debugPrint('Handling a background message: ${message.messageId}'); -} diff --git a/lib/src/_messaging/messaging_provider.dart b/lib/src/_messaging/messaging_provider.dart deleted file mode 100644 index 1b7cb503..00000000 --- a/lib/src/_messaging/messaging_provider.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:autojidelna/src/_messaging/messaging.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/material.dart'; - -class MessagingProvider extends ChangeNotifier { - MessagingProvider() { - FirebaseMessaging.onMessageOpenedApp.listen(handleNotificationMessage); - } - RemoteMessage? _message; - RemoteMessage? get message => _message; - - void handleNotificationMessage(RemoteMessage message) { - _message = message; - Messaging.currentMessage = message; - notifyListeners(); - } - - void notificationMessageHandled() { - _message = null; - Messaging.currentMessage = null; - } -} diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index c05162d2..34327e00 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -1,21 +1,14 @@ import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; -import 'package:autojidelna/src/_routing/guards.dart'; @AutoRouterConfig(replaceInRouteName: 'Screen,Route') class AppRouter extends RootStackRouter { - @override - late final List guards = [ - MessagingDeepLinkGuard(), - ]; - @override List get routes => staticRoutes; static final List staticRoutes = [ AutoRoute( page: RouterPage.page, initial: true, - guards: [NotificationGuard()], path: '/', children: [ AutoRoute(page: DemoPage.page, path: 'demo'), diff --git a/lib/src/_routing/guards.dart b/lib/src/_routing/guards.dart deleted file mode 100644 index 182af8e3..00000000 --- a/lib/src/_routing/guards.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'dart:async'; - -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/_conf/messaging.dart'; -import 'package:autojidelna/src/_global/app.dart'; -import 'package:autojidelna/src/_messaging/messaging.dart'; -import 'package:autojidelna/src/_routing/app_router.dart'; -import 'package:autojidelna/src/_routing/app_router.gr.dart'; - -class MessagingDeepLinkGuard extends AutoRouteGuard { - @override - void onNavigation(NavigationResolver resolver, StackRouter router) { - bool isValid(AutoRoute route, String baseRoute, {String prevRoute = ''}) { - if (route.children != null && route.children!.routes.isNotEmpty) { - final match = route.children!.routes.any((child) => isValid(child, baseRoute, prevRoute: prevRoute + route.path)); - if (match) return true; - } - final regexPattern = RegExp('^${(prevRoute + route.path).replaceAllMapped(RegExp(r':\w+'), (match) => r'[^/]+')}\$'); - return regexPattern.hasMatch(baseRoute); - } - - bool isRouteValid(String routeName) { - final uri = Uri.parse(routeName); - String baseRoute = uri.path; - return AppRouter.staticRoutes.any((route) => isValid(route, baseRoute)); - } - - final message = Messaging.messagingProvider.message; - Messaging.messagingProvider.notificationMessageHandled(); - if (message?.data[MessagingConf.dataPushRoute] != null && isRouteValid(message!.data[MessagingConf.dataPushRoute]!)) { - final routeName = message.data[MessagingConf.dataPushRoute]!; - final uri = Uri.parse(routeName); - final route = uri.path + (uri.hasQuery ? '?${uri.query}' : ''); - Future.delayed( - Duration.zero, - () => unawaited(router.root.navigateNamed(route)), - ); - } - resolver.next(); - } -} - -class NotificationGuard extends AutoRouteGuard { - @override - void onNavigation(NavigationResolver resolver, StackRouter router) { - if (Messaging.grantedPermission || resolver.route.name == RequestPermissionPage.name || !App.shouldAskForNotification) { - resolver.next(); - return; - } else { - unawaited(resolver.redirect(RequestPermissionPage(onResult: (didLogin) => resolver.next(didLogin)))); - } - } -} diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index a862a090..a9af699c 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_global/app.dart'; -import 'package:autojidelna/src/_messaging/messaging.dart'; import 'package:autojidelna/src/_sentry/sentry.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/_routing/app_router.dart'; @@ -59,7 +58,6 @@ class _MyAppState extends State { debugShowCheckedModeBanner: false, routerConfig: _appRouter.config( navigatorObservers: () => [SentryNavigatorObserver(), SentryTabObserver()], - reevaluateListenable: Messaging.messagingProvider, includePrefixMatches: true, deepLinkTransformer: (uri) async => deepLinkTransformer(uri), ), diff --git a/lib/src/ui/pages/debug_page.dart b/lib/src/ui/pages/debug_page.dart index 445f523a..bcb9b70f 100644 --- a/lib/src/ui/pages/debug_page.dart +++ b/lib/src/ui/pages/debug_page.dart @@ -1,5 +1,4 @@ import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/_messaging/messaging.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/logic/crash_logic.dart'; import 'package:flutter/material.dart'; @@ -11,8 +10,6 @@ class DebugPage extends StatelessWidget { @override Widget build(BuildContext context) { final lang = context.l10n; - debugPrint('fcmToken: ${Messaging.fcmToken}'); - debugPrint('apnsToken: ${Messaging.apnsToken}'); return Scaffold( appBar: AppBar( title: const Text('Debug'), @@ -20,8 +17,6 @@ class DebugPage extends StatelessWidget { body: Center( child: Column( children: [ - SelectableText('fcmToken: ${Messaging.fcmToken}'), - SelectableText('apnsToken: ${Messaging.apnsToken}'), TextField( onChanged: (value) async => value == 'crash' ? crashTestFunction() : null, decoration: InputDecoration( diff --git a/lib/src/ui/pages/request_permission_page.dart b/lib/src/ui/pages/request_permission_page.dart index 4941794f..cd69184b 100644 --- a/lib/src/ui/pages/request_permission_page.dart +++ b/lib/src/ui/pages/request_permission_page.dart @@ -2,9 +2,7 @@ import 'dart:async'; import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_conf/hive.dart'; -import 'package:autojidelna/src/_messaging/messaging.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; @@ -35,18 +33,6 @@ class RequestPermissionPage extends StatelessWidget { onPressed: () async { onResult!(true); if (kIsWeb) unawaited(Hive.box(Boxes.settings).put(HiveKeys.shouldAskForNotificationPermission, false)); - await FirebaseMessaging.instance.requestPermission( - alert: true, - announcement: false, - badge: true, - carPlay: false, - criticalAlert: false, - provisional: false, - sound: true, - ); - Future.delayed(const Duration(seconds: 1), () { - Messaging.onNotificationPermissionGranted(); - }); }, child: Text(lang.requestNotificationPermission), ), diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cb043e78..b7e42cb4 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,7 +8,6 @@ import Foundation import firebase_analytics import firebase_core import firebase_crashlytics -import firebase_messaging import firebase_remote_config import flutter_secure_storage_macos import package_info_plus @@ -21,7 +20,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) - FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FLTFirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseRemoteConfigPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) diff --git a/pubspec.lock b/pubspec.lock index cb342a76..1fb7f201 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -385,30 +385,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.40" - firebase_messaging: - dependency: "direct main" - description: - name: firebase_messaging - sha256: "1b0a4f9ecbaf9007771bac152afad738ddfacc4b8431a7591c00829480d99553" - url: "https://pub.dev" - source: hosted - version: "15.0.4" - firebase_messaging_platform_interface: - dependency: transitive - description: - name: firebase_messaging_platform_interface - sha256: c5a6443e66ae064fe186901d740ee7ce648ca2a6fd0484b8c5e963849ac0fc28 - url: "https://pub.dev" - source: hosted - version: "4.5.42" - firebase_messaging_web: - dependency: transitive - description: - name: firebase_messaging_web - sha256: "232ef63b986467ae5b5577a09c2502b26e2e2aebab5b85e6c966a5ca9b038b89" - url: "https://pub.dev" - source: hosted - version: "3.8.12" firebase_remote_config: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6c954b3f..3c05707a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,7 +49,6 @@ dependencies: firebase_crashlytics: ^4.0.4 firebase_analytics: ^11.0.1 firebase_remote_config: ^5.0.2 - firebase_messaging: ^15.0.3 flutter_adaptive_scaffold: ^0.2.1 package_info_plus: ^8.0.0 # Package info used in about page diff --git a/web/firebase-messaging-sw.js b/web/firebase-messaging-sw.js deleted file mode 100644 index b792a265..00000000 --- a/web/firebase-messaging-sw.js +++ /dev/null @@ -1,18 +0,0 @@ -importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"); -importScripts( - "https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js" -); - -firebase.initializeApp({ - apiKey: "AIzaSyBlMC15yTKNCS-J3Fncd3LxjiNaZgjKgaw", - appId: "1:108088693003:web:0843b05cd66085bf96d20e", - messagingSenderId: "108088693003", - projectId: "autojidelna", - authDomain: "autojidelna.firebaseapp.com", - databaseURL: - "https://autojidelna-default-rtdb.europe-west1.firebasedatabase.app", - storageBucket: "autojidelna.appspot.com", - measurementId: "G-3SKH2E1QEC", -}); - -const messaging = firebase.messaging(); \ No newline at end of file diff --git a/web/index.html b/web/index.html index c3b481e6..581115ab 100644 --- a/web/index.html +++ b/web/index.html @@ -113,14 +113,6 @@ - + From ce5e3442161f24437adb9bbe5c217a9450a8554f Mon Sep 17 00:00:00 2001 From: tpkowastaken Date: Thu, 26 Sep 2024 00:30:18 +0200 Subject: [PATCH 02/57] Notifications work --- android/app/src/main/AndroidManifest.xml | 9 +- android/build.gradle | 1 + ios/Podfile | 13 + ios/Podfile.lock | 106 +- ios/PrivacyInfo.xcprivacy | 26 + ios/Runner.xcodeproj/project.pbxproj | 28 +- ios/Runner/Info.plist | 136 +- ios/Runner/InfoPlist.xcstrings | 12 + l10n.yaml | 2 +- lib/main.dart | 2 + lib/src/_conf/dates.dart | 2 + lib/src/_conf/hive.dart | 41 +- lib/src/_conf/notifications.dart | 73 + lib/src/_global/app.dart | 55 + lib/src/_global/init_app.dart | 1 + lib/src/freezed/freezed.dart | 111 - lib/src/freezed/freezed.freezed.dart | 2287 ----------------- lib/src/freezed/freezed.g.dart | 177 -- lib/src/lang/app_cs.arb | 282 +- lib/src/lang/app_en.arb | 148 -- lib/src/lang/output/texts.dart | 1200 +++++++-- lib/src/lang/output/texts_cs.dart | 550 +++- lib/src/lang/output/texts_en.dart | 260 -- lib/src/logic/canteenwrapper.dart | 560 ++++ lib/src/logic/github_release_logic.dart | 13 - lib/src/logic/notifications.dart | 475 ++++ lib/src/types/all.dart | 233 ++ lib/src/ui/pages/settings/settings_page.dart | 2 + .../widgets/buttons/test_notifications.dart | 16 + .../widgets/failed_login_dialog_widget.dart | 42 + macos/Flutter/GeneratedPluginRegistrant.swift | 4 + pubspec.lock | 56 + pubspec.yaml | 5 + 33 files changed, 3544 insertions(+), 3384 deletions(-) create mode 100644 ios/PrivacyInfo.xcprivacy create mode 100644 lib/src/_conf/dates.dart create mode 100644 lib/src/_conf/notifications.dart delete mode 100644 lib/src/freezed/freezed.dart delete mode 100644 lib/src/freezed/freezed.freezed.dart delete mode 100644 lib/src/freezed/freezed.g.dart delete mode 100644 lib/src/lang/app_en.arb delete mode 100644 lib/src/lang/output/texts_en.dart create mode 100644 lib/src/logic/canteenwrapper.dart delete mode 100644 lib/src/logic/github_release_logic.dart create mode 100644 lib/src/logic/notifications.dart create mode 100644 lib/src/types/all.dart create mode 100644 lib/src/ui/widgets/buttons/test_notifications.dart create mode 100644 lib/src/ui/widgets/failed_login_dialog_widget.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d149f7d4..2c9763b9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,9 +1,13 @@ - + + + + + + 7.13) - - GoogleUtilities/UserDefaults (~> 7.13) - - PromisesObjC (~> 2.3) - - connectivity_plus (0.0.1): + - awesome_notifications (0.9.3): + - Flutter + - IosAwnCore (~> 0.9.3) + - awesome_notifications_core (0.0.1): + - Flutter + - background_fetch (1.3.7): - Flutter - - FlutterMacOS - Firebase/Analytics (10.29.0): - Firebase/Core - Firebase/Auth (10.29.0): @@ -35,15 +29,6 @@ PODS: - Firebase/Analytics (= 10.29.0) - firebase_core - Flutter - - firebase_app_check (0.3.0-4): - - Firebase/CoreOnly (~> 10.29.0) - - firebase_core - - FirebaseAppCheck (~> 10.29.0) - - Flutter - - firebase_auth (5.1.4): - - Firebase/Auth (= 10.29.0) - - firebase_core - - Flutter - firebase_core (3.3.0): - Firebase/CoreOnly (= 10.29.0) - Flutter @@ -51,10 +36,6 @@ PODS: - Firebase/Crashlytics (= 10.29.0) - firebase_core - Flutter - - firebase_messaging (15.0.4): - - Firebase/Messaging (= 10.29.0) - - firebase_core - - Flutter - firebase_remote_config (5.0.4): - Firebase/RemoteConfig (= 10.29.0) - firebase_core @@ -79,13 +60,6 @@ PODS: - GoogleUtilities/Network (~> 7.11) - "GoogleUtilities/NSData+zlib (~> 7.11)" - nanopb (< 2.30911.0, >= 2.30908.0) - - FirebaseAppCheck (10.29.0): - - AppCheckCore (~> 10.19) - - FirebaseAppCheckInterop (~> 10.28) - - FirebaseCore (~> 10.18) - - GoogleUtilities/Environment (~> 7.13) - - GoogleUtilities/UserDefaults (~> 7.13) - - PromisesObjC (~> 2.1) - FirebaseAppCheckInterop (10.29.0) - FirebaseAuth (10.29.0): - FirebaseAppCheckInterop (~> 10.17) @@ -98,7 +72,7 @@ PODS: - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Logger (~> 7.12) - - Firebaseautojidelnaxtension (10.29.0): + - FirebaseCoreExtension (10.29.0): - FirebaseCore (~> 10.0) - FirebaseCoreInternal (10.29.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" @@ -136,7 +110,7 @@ PODS: - FirebaseRemoteConfigInterop (10.29.0) - FirebaseSessions (10.29.0): - FirebaseCore (~> 10.5) - - Firebaseautojidelnaxtension (~> 10.0) + - FirebaseCoreExtension (~> 10.0) - FirebaseInstallations (~> 10.0) - GoogleDataTransport (~> 9.2) - GoogleUtilities/Environment (~> 7.13) @@ -147,12 +121,6 @@ PODS: - Flutter (1.0.0) - flutter_secure_storage (6.0.0): - Flutter - - google_sign_in_ios (0.0.1): - - AppAuth (>= 1.7.4) - - Flutter - - FlutterMacOS - - GoogleSignIn (~> 7.1) - - GTMSessionFetcher (>= 3.4.0) - GoogleAppMeasurement (10.29.0): - GoogleAppMeasurement/AdIdSupport (= 10.29.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.11) @@ -177,10 +145,6 @@ PODS: - GoogleUtilities/Environment (~> 7.7) - nanopb (< 2.30911.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) - - GoogleSignIn (7.1.0): - - AppAuth (< 2.0, >= 1.7.3) - - GTMAppAuth (< 5.0, >= 4.1.1) - - GTMSessionFetcher/Core (~> 3.3) - GoogleUtilities/AppDelegateSwizzler (7.13.3): - GoogleUtilities/Environment - GoogleUtilities/Logger @@ -209,14 +173,12 @@ PODS: - GoogleUtilities/UserDefaults (7.13.3): - GoogleUtilities/Logger - GoogleUtilities/Privacy - - GTMAppAuth (4.1.1): - - AppAuth/Core (~> 1.7) - - GTMSessionFetcher/Core (< 4.0, >= 3.3) - GTMSessionFetcher (3.5.0): - GTMSessionFetcher/Full (= 3.5.0) - GTMSessionFetcher/Core (3.5.0) - GTMSessionFetcher/Full (3.5.0): - GTMSessionFetcher/Core + - IosAwnCore (0.9.3) - nanopb (2.30910.0): - nanopb/decode (= 2.30910.0) - nanopb/encode (= 2.30910.0) @@ -246,19 +208,17 @@ PODS: - Flutter DEPENDENCIES: - - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) + - awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`) + - awesome_notifications_core (from `.symlinks/plugins/awesome_notifications_core/ios`) + - background_fetch (from `.symlinks/plugins/background_fetch/ios`) - Firebase/Auth - Firebase/Messaging - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - - firebase_app_check (from `.symlinks/plugins/firebase_app_check/ios`) - - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) - - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`) - Flutter (from `Flutter`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) - GoogleUtilities/AppDelegateSwizzler - GoogleUtilities/Environment - GoogleUtilities/Logger @@ -277,16 +237,13 @@ DEPENDENCIES: SPEC REPOS: trunk: - - AppAuth - - AppCheckCore - Firebase - FirebaseABTesting - FirebaseAnalytics - - FirebaseAppCheck - FirebaseAppCheckInterop - FirebaseAuth - FirebaseCore - - Firebaseautojidelnaxtension + - FirebaseCoreExtension - FirebaseCoreInternal - FirebaseCrashlytics - FirebaseInstallations @@ -297,10 +254,9 @@ SPEC REPOS: - FirebaseSharedSwift - GoogleAppMeasurement - GoogleDataTransport - - GoogleSignIn - GoogleUtilities - - GTMAppAuth - GTMSessionFetcher + - IosAwnCore - nanopb - PromisesObjC - PromisesSwift @@ -308,28 +264,24 @@ SPEC REPOS: - Sentry EXTERNAL SOURCES: - connectivity_plus: - :path: ".symlinks/plugins/connectivity_plus/darwin" + awesome_notifications: + :path: ".symlinks/plugins/awesome_notifications/ios" + awesome_notifications_core: + :path: ".symlinks/plugins/awesome_notifications_core/ios" + background_fetch: + :path: ".symlinks/plugins/background_fetch/ios" firebase_analytics: :path: ".symlinks/plugins/firebase_analytics/ios" - firebase_app_check: - :path: ".symlinks/plugins/firebase_app_check/ios" - firebase_auth: - :path: ".symlinks/plugins/firebase_auth/ios" firebase_core: :path: ".symlinks/plugins/firebase_core/ios" firebase_crashlytics: :path: ".symlinks/plugins/firebase_crashlytics/ios" - firebase_messaging: - :path: ".symlinks/plugins/firebase_messaging/ios" firebase_remote_config: :path: ".symlinks/plugins/firebase_remote_config/ios" Flutter: :path: Flutter flutter_secure_storage: :path: ".symlinks/plugins/flutter_secure_storage/ios" - google_sign_in_ios: - :path: ".symlinks/plugins/google_sign_in_ios/darwin" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -342,24 +294,20 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa - AppCheckCore: 9feb4300caa596a36416cde10674dc5bec1e022e - connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db + awesome_notifications: 66d28ab7174ca2823b04d275cb043e0a4a3eb9cf + awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef + background_fetch: 39f11371c0dce04b001c4bfd5e782bcccb0a85e2 Firebase: cec914dab6fd7b1bd8ab56ea07ce4e03dd251c2d firebase_analytics: 04491d1ee74c8e7c2330c96afc54188a969b06ee - firebase_app_check: bf48979c0d6d350452f3615eb1d557bacd3ff256 - firebase_auth: 8dbfcdd635cc4fb2ea213aeee8c9a979b3d3373b firebase_core: 57aeb91680e5d5e6df6b888064be7c785f146efb firebase_crashlytics: e3d3e0c99bad5aaab5908385133dea8ec344693f - firebase_messaging: c862b3d2b973ecc769194dc8de09bd22c77ae757 firebase_remote_config: 622c7e72a9349b7db48658ea902d9f2f1f2d7aaa FirebaseABTesting: d87f56707159bae64e269757a6e963d490f2eebe FirebaseAnalytics: 23717de130b779aa506e757edb9713d24b6ffeda - FirebaseAppCheck: a071fc2cfbc877898f7546b2d59d4a30a728ebae FirebaseAppCheckInterop: 6a1757cfd4067d8e00fccd14fcc1b8fd78cfac07 FirebaseAuth: e2ebfaf9fb4638a1c9a3b0efd17d1b90943987cd FirebaseCore: 30e9c1cbe3d38f5f5e75f48bfcea87d7c358ec16 - Firebaseautojidelnaxtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f + FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 FirebaseCrashlytics: 34647b41e18de773717fdd348a22206f2f9bc774 FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd @@ -370,13 +318,11 @@ SPEC CHECKSUMS: FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 - google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38 GoogleAppMeasurement: f9de05ee17401e3355f68e8fc8b5064d429f5918 GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a - GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 - GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 + IosAwnCore: b8601fbb37f7b3560f31b84ebf55a72f65812e05 nanopb: 438bc412db1928dac798aa6fd75726007be04262 package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 @@ -388,6 +334,6 @@ SPEC CHECKSUMS: shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe -PODFILE CHECKSUM: b8bcaddefa150d50294bf13f9c4329d413af05af +PODFILE CHECKSUM: cadf6a00bfda77fdad48b972deb0b4892d5466ca COCOAPODS: 1.15.2 diff --git a/ios/PrivacyInfo.xcprivacy b/ios/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..09207b3a --- /dev/null +++ b/ios/PrivacyInfo.xcprivacy @@ -0,0 +1,26 @@ + + + + + + NSPrivacyAccessedAPITypes + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index feb004d0..6d90a817 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ E2C435852C8BA645003D8704 /* imgdebug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = E2C435842C8BA645003D8704 /* imgdebug.xcconfig */; }; E2C435872C8BA658003D8704 /* imgrelease.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = E2C435862C8BA658003D8704 /* imgrelease.xcconfig */; }; E2D2FD1A2C42B61700B8E71F /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = E2D2FD192C42B61700B8E71F /* InfoPlist.xcstrings */; }; + E2D8BF8E2CA4B5B100514E0D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = E2D8BF8D2CA4B5B100514E0D /* PrivacyInfo.xcprivacy */; }; FA392633454B9C7631DE0F92 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B0676E3E9685E315AB6823D /* GoogleService-Info.plist */; }; /* End PBXBuildFile section */ @@ -103,6 +104,7 @@ E2C435842C8BA645003D8704 /* imgdebug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = imgdebug.xcconfig; sourceTree = ""; }; E2C435862C8BA658003D8704 /* imgrelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = imgrelease.xcconfig; sourceTree = ""; }; E2D2FD192C42B61700B8E71F /* InfoPlist.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = InfoPlist.xcstrings; sourceTree = ""; }; + E2D8BF8D2CA4B5B100514E0D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; E74F63FCF3E4FA417B0F5CBA /* Pods_ImageNotification.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ImageNotification.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -172,6 +174,7 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + E2D8BF8D2CA4B5B100514E0D /* PrivacyInfo.xcprivacy */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, E28B20302C4EF4A40055BE6B /* ImageNotification */, @@ -268,7 +271,6 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 92EF36CB4127693D6D7182E0 /* [CP] Embed Pods Frameworks */, - 1073B0BAE8DE8F072EBE5CB6 /* [CP] Copy Pods Resources */, 204C1D58ADAC0CDC5A519AF8 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */, ); buildRules = ( @@ -356,6 +358,7 @@ buildActionMask = 2147483647; files = ( E2D2FD1A2C42B61700B8E71F /* InfoPlist.xcstrings in Resources */, + E2D8BF8E2CA4B5B100514E0D /* PrivacyInfo.xcprivacy in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, @@ -376,23 +379,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1073B0BAE8DE8F072EBE5CB6 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 204C1D58ADAC0CDC5A519AF8 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -644,7 +630,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -845,7 +833,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -877,7 +867,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index c724e481..2b0bcd3e 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,6 +2,12 @@ + BGTaskSchedulerPermittedIdentifiers + + com.transistorsoft.customtask + + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -12,26 +18,19 @@ $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 + CFBundleLocalizations + + en + cs + CFBundleName autojidelna - FlutterDeepLinkingEnabled - CFBundlePackageType APPL - ITSAppUsesNonExemptEncryption - CFBundleShortVersionString $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) CFBundleSignature ???? - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - GIDClientID - 466976066624-lgcg7thjbakj66btd8og3ld0sntaqdjq.apps.googleusercontent.com CFBundleURLTypes @@ -43,6 +42,25 @@ + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + FlutterDeepLinkingEnabled + + GIDClientID + 466976066624-lgcg7thjbakj66btd8og3ld0sntaqdjq.apps.googleusercontent.com + ITSAppUsesNonExemptEncryption + + LSRequiresIPhoneOS + + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + processing + + UILaunchStoryboardName + LaunchScreen UIMainStoryboardFile Main UISupportedInterfaceOrientations @@ -58,99 +76,5 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - CFBundleLocalizations - - en - cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/InfoPlist.xcstrings b/ios/Runner/InfoPlist.xcstrings index 81f571f0..202cb842 100644 --- a/ios/Runner/InfoPlist.xcstrings +++ b/ios/Runner/InfoPlist.xcstrings @@ -18,6 +18,18 @@ } } }, + "CFBundleName" : { + "comment" : "Bundle name", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "autojidelna" + } + } + } + }, "NSLocationAlwaysAndWhenInUseUsageDescription" : { "extractionState" : "manual", "localizations" : { diff --git a/l10n.yaml b/l10n.yaml index ec576825..a366f40c 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -1,6 +1,6 @@ arb-dir: lib/src/lang output-dir: lib/src/lang/output -template-arb-file: app_en.arb +template-arb-file: app_cs.arb output-localization-file: texts.dart untranslated-messages-file: untranslated_messages.json output-class: Texts diff --git a/lib/main.dart b/lib/main.dart index b0677005..818cac7e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:autojidelna/firebase_options.dart'; import 'package:autojidelna/src/_conf/tokens.dart'; import 'package:autojidelna/src/_global/init_app.dart'; import 'package:autojidelna/src/ui/material_app.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; @@ -77,6 +78,7 @@ void runMyApp() async { } await InitApp.init(); + AwesomeNotifications().requestPermissionToSendNotifications(); if (!kDebugMode) { runApp( diff --git a/lib/src/_conf/dates.dart b/lib/src/_conf/dates.dart new file mode 100644 index 00000000..9cbc5a10 --- /dev/null +++ b/lib/src/_conf/dates.dart @@ -0,0 +1,2 @@ +final DateTime minimalDate = DateTime(DateTime.now().year, DateTime.now().month - 1, 1); +final DateTime maximalDate = DateTime(DateTime.now().year, DateTime.now().month + 2, 0); diff --git a/lib/src/_conf/hive.dart b/lib/src/_conf/hive.dart index fb8dd7b8..d223043a 100644 --- a/lib/src/_conf/hive.dart +++ b/lib/src/_conf/hive.dart @@ -1,13 +1,52 @@ /// Hive boxes. Use these values to open a box. class Boxes { static const String settings = 'settings'; + static const String appState = 'appState'; static const String cache = 'cache'; + static const String statistics = 'statistics'; + static const String notifications = 'notifications'; } /// Hive keys. These are the keys used to store values in Hive. class HiveKeys { + static const String remoteConfigValues = 'remoteConfigValues'; + // appState box static const String locale = 'locale'; + static const String lastVersion = 'lastVersion'; + static const String firstTime = 'firstTime'; + static const String url = 'url'; + static const String hideBurzaAlertDialog = 'hideBurzaAlertDialog'; + static String location(String userName, String url) => 'location_${userName}_$url'; + + //settings box static const String shouldAskForNotificationPermission = 'shouldAskForNotificationPermission'; static const String webNotificationsAccepted = 'webNotificationsAccepted'; - static const String remoteConfigValues = 'remoteConfigValues'; + static const String themeMode = 'themeMode'; + static const String themeStyle = 'themeStyle'; + static const String tabletUi = 'tabletUi'; + static const String listUi = 'listUi'; + static const String pureBlack = 'amoledMode'; + static const String bigCalendarMarkers = 'bigCalendarMarkers'; + static const String dateFormat = 'dateFormat'; + static const String relTimeStamps = 'relativeTimeStamps'; + static const String skipWeekends = 'skipWeekends'; + static const String todaysFood = 'todaysFood'; + static const String sendTodaysFood = 'sendTodaysFood'; + static const String lowCredit = 'lowCredit'; + static const String weekLongFamine = 'weekLongFamine'; + static const String analytics = 'analytics'; + + // notification box + static String lastNotificationCheck(String userName, String url) => 'lastCheck_${userName}_$url'; + static String lastJidloDneCheck(String userName, String url) => 'lastJidloDneCheck_${userName}_$url'; + static String nemateObjednanoNotifications(String userName, String url) => 'ignore_objednat_${userName}_$url'; + static const String onlyNemateObjednanoNotifications = 'ignore_objednat_'; + static String kreditNotifications(String userName, String url) => 'ignore_kredit_${userName}_$url'; + static const String onlykreditNotifications = 'ignore_kredit_'; + static String dailyFoodInfo(String userName, String url) => 'sendFoodInfo_${userName}_$url'; + + // statistics box + static const String statistikaObjednavka = 'statistika:objednavka'; + static const String statistikaAuto = 'statistika:auto'; + static const String statistikaBurzaCatcher = 'statistika:burzaCatcher'; } diff --git a/lib/src/_conf/notifications.dart b/lib/src/_conf/notifications.dart new file mode 100644 index 00000000..dc724e0c --- /dev/null +++ b/lib/src/_conf/notifications.dart @@ -0,0 +1,73 @@ +// Purpose: stores constants used throughout the app. + +import 'package:flutter/material.dart'; + +class Locales { + static Locale get csCZ => const Locale('cs', 'CZ'); +} + +class NotificationIds { + static String kreditChannel(String userName, String url) => 'kredit_channel_${userName}_$url'; + static String objednanoChannel(String userName, String url) => 'objednano_channel_${userName}_$url'; + static String dnesniJidloChannel(String userName, String url) => 'jidlo_channel_${userName}_$url'; + static String channelGroup(String userName, String url) => 'channel_group_${userName}_$url'; + static const String channelGroupElse = 'channel_group_else'; + static const String channelElse = 'else_channel'; + static const String payloadUser = 'user'; + static const String payloadIndex = 'index'; + static const String payloadIndexDne = 'indexDne'; + static String objednatButton(String userName, String url) => 'objednat_${userName}_$url'; + static const String onlyObjednatButton = 'objednat_'; +} + +class Nums { + static int get switchAccountPanelDuration => 300; +} + +class AnalyticsEventIds { + static const String updateButtonClicked = 'updateButtonClicked'; + static const String oldVer = 'oldVersion'; + static const String newVer = 'newVersion'; + static const String updateDownloaded = 'updateDownloaded'; +} + +// Strings shown to the user +class NotificationsTexts { + /// initAwesome and notifications in general have a problem with the localization package so we just force czech + static String notificationsFor(String user) => 'Notifikace pro $user'; + static const String jidloChannelName = 'Dnešní jídlo'; + static String jidloChannelDescription(String user) => 'Notifikace každý den o tom jaké je dnes jídlo pro $user'; + static const String dochazejiciKreditChannelName = 'Docházející kredit'; + static String dochazejiciKreditChannelDescription(String user) => 'Notifikace o tom, zda vám dochází kredit týden dopředu pro $user'; + static const String objednanoChannelName = 'Objednáno?'; + static String objednanoChannelDescription(String user) => 'Notifikace každý den o tom jaké je dnes jídlo pro $user'; + static const String notificationOther = 'Ostatní'; + static const String notificationOtherDescription = 'Ostatní notifikace, např. chybové hlášky...'; + static const String stringtingDataNotifications = 'Získávám data pro notifikace'; + static const String notificationDochaziVamKredit = 'Dochází vám kredit!'; + static String notificationKreditPro(String jmeno, String prijmeni, int kredit) => 'Kredit pro $jmeno $prijmeni: $kredit Kč'; + static const String notificationZtlumit = 'Ztlumit na týden'; + static const String notificationObjednejteSi = 'Objednejte si na příští týden'; + static String notificationObjednejteSiDetail(String jmeno, String prijmeni) => 'Uživatel $jmeno $prijmeni si stále ještě neobjenal na příští týden'; + static const String objednatAction = 'Objednat náhodně'; + static const String notificationNoFood = 'Žádná jídla pro tento den'; + static const String nastalaChyba = 'Nastala chyba'; +} + +class Links { + static const String autojidelna = 'https://autojidelna.cz'; + static const String repo = 'https://github.com/App-Elevate/AUT.aplikace'; + static const String latestVersionApi = 'https://api.github.com/repos/App-Elevate/AUT.aplikace/releases/latest'; + static const String appStore = '$autojidelna/release/appStore.json'; + static String currentVersionCode(String appVersion) => '$repo/blob/v$appVersion'; + + static const String privacyPolicy = '$autojidelna/cs/privacy-policy/'; + static String currentChangelog(String version) => '$autojidelna/cs/changelogs/#$version'; + + static const String latestRelease = '$repo/releases/latest'; + static const String email = 'info@appelevate.cz'; +} + +class Assets { + static const String logo = 'assets/images/logo.svg'; +} diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index 6983b84a..1875e396 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -1,5 +1,11 @@ import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_global/providers/remote_config.dart'; +import 'package:autojidelna/src/logic/canteenwrapper.dart'; +import 'package:autojidelna/src/logic/notifications.dart'; +import 'package:autojidelna/src/types/all.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; +import 'package:background_fetch/background_fetch.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/foundation.dart'; @@ -29,6 +35,7 @@ class App { static bool _initHiveExecuted = false; static bool _initRotationExecuted = false; static bool _initCodePushExecuted = false; + static bool _initNotificationsExecuted = false; static Future initCodePush() async { assert(_initCodePushExecuted == false, 'App.initCodePush() must be called only once'); @@ -50,6 +57,51 @@ class App { _initCodePushExecuted = true; } + static Future initNotifications() async { + assert(_initNotificationsExecuted == false, 'App.initNotifications() must be called only once'); + if (_initNotificationsExecuted) return; + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + String version = packageInfo.version; + String? lastVersion = Hive.box(Boxes.appState).get(HiveKeys.lastVersion); + + // Removing the already set notifications if we updated versions + if (lastVersion != version) { + // Set the new version + Hive.box(Boxes.appState).put(HiveKeys.lastVersion, version); + + try { + LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + + for (LoggedInUser uzivatel in loginData.users) { + AwesomeNotifications().removeChannel(NotificationIds.kreditChannel(uzivatel.username, uzivatel.url)); + await AwesomeNotifications().removeChannel(NotificationIds.objednanoChannel(uzivatel.username, uzivatel.url)); + } + } catch (e) { + //do nothing + } + await AwesomeNotifications().dispose(); + } + + // Initialize the notifications + initAwesome(); + + // Setting listeners for when the app is running and notification button is clicked + AwesomeNotifications().setListeners( + onActionReceivedMethod: NotificationController.onActionReceivedMethod, + onNotificationCreatedMethod: NotificationController.onNotificationCreatedMethod, + onNotificationDisplayedMethod: NotificationController.onNotificationDisplayedMethod, + onDismissActionReceivedMethod: NotificationController.onDismissActionReceivedMethod, + ); + + // Detecting if the app was opened from a notification and handling it if it was + ReceivedAction? receivedAction = await AwesomeNotifications().getInitialNotificationAction(removeFromActionEvents: false); + await NotificationController.handleNotificationAction(receivedAction); + + // Initializing the background fetch + BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); + _initNotificationsExecuted = true; + } + static Future initPlatform() async { assert(_initPlatformExecuted == false, 'App.initPlatform() must be called only once'); if (_initPlatformExecuted) return; @@ -97,6 +149,9 @@ class App { await Hive.initFlutter(); await Hive.openBox(Boxes.settings); await Hive.openBox(Boxes.cache); + await Hive.openBox(Boxes.appState); + await Hive.openBox(Boxes.statistics); + await Hive.openBox(Boxes.notifications); _initHiveExecuted = true; } diff --git a/lib/src/_global/init_app.dart b/lib/src/_global/init_app.dart index c4a55090..44eef1a0 100644 --- a/lib/src/_global/init_app.dart +++ b/lib/src/_global/init_app.dart @@ -19,6 +19,7 @@ class InitApp { App.initPlatform(), App.initRotation(), App.initCodePush(), + App.initNotifications(), ]); // Stop the stopwatch stopwatch.stop(); diff --git a/lib/src/freezed/freezed.dart b/lib/src/freezed/freezed.dart deleted file mode 100644 index 3993a0d8..00000000 --- a/lib/src/freezed/freezed.dart +++ /dev/null @@ -1,111 +0,0 @@ -// This file is "main.dart" -// ignore_for_file: unused_import - -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:flutter/foundation.dart'; - -// required: associates our `freezed.dart` with the code generated by Freezed -part 'freezed.freezed.dart'; - -// optional: Since our Github class is serializable, we must add this line. -// But if Person was not serializable, we could skip it. -part 'freezed.g.dart'; - -@freezed -class GithubRelease with _$GithubRelease { - const factory GithubRelease({ - @JsonKey(name: 'url') required String url, - @JsonKey(name: 'assets_url') required String assetsUrl, - @JsonKey(name: 'upload_url') required String uploadUrl, - @JsonKey(name: 'html_url') required String htmlUrl, - @JsonKey(name: 'id') required int id, - @JsonKey(name: 'assets') required List assets, - @JsonKey(name: 'author') required GithubAuthor author, - @JsonKey(name: 'node_id') required String nodeId, - @JsonKey(name: 'tag_name') required String tagName, - @JsonKey(name: 'target_commitish') required String targetCommitish, - @JsonKey(name: 'name') required String name, - @JsonKey(name: 'draft') required bool draft, - @JsonKey(name: 'prerelease') required bool prerelease, - @JsonKey(name: 'created_at') required DateTime createdAt, - @JsonKey(name: 'published_at') required DateTime publishedAt, - @JsonKey(name: 'tarball_url') required String tarballUrl, - @JsonKey(name: 'zipball_url') required String zipballUrl, - @JsonKey(name: 'body') required String body, - }) = _GithubRelease; - - factory GithubRelease.fromJson(Map json) => _$GithubReleaseFromJson(json); -} - -@freezed -class GithubAuthor with _$GithubAuthor { - const factory GithubAuthor({ - @JsonKey(name: 'login') required String login, - @JsonKey(name: 'id') required int id, - @JsonKey(name: 'node_id') required String nodeId, - @JsonKey(name: 'avatar_url') required String avatarUrl, - @JsonKey(name: 'gravatar_id') required String gravatarId, - @JsonKey(name: 'url') required String url, - @JsonKey(name: 'html_url') required String htmlUrl, - @JsonKey(name: 'followers_url') required String followersUrl, - @JsonKey(name: 'following_url') required String followingUrl, - @JsonKey(name: 'gists_url') required String gistsUrl, - @JsonKey(name: 'starred_url') required String starredUrl, - @JsonKey(name: 'subscriptions_url') required String subscriptionsUrl, - @JsonKey(name: 'organizations_url') required String organizationsUrl, - @JsonKey(name: 'repos_url') required String reposUrl, - @JsonKey(name: 'events_url') required String eventsUrl, - @JsonKey(name: 'received_events_url') required String receivedEventsUrl, - @JsonKey(name: 'type') required String type, - @JsonKey(name: 'site_admin') required bool siteAdmin, - }) = _GithubAuthor; - - factory GithubAuthor.fromJson(Map json) => _$GithubAuthorFromJson(json); -} - -@freezed -class GithubAsset with _$GithubAsset { - const factory GithubAsset({ - @JsonKey(name: 'url') required String url, - @JsonKey(name: 'id') required int id, - @JsonKey(name: 'node_id') required String nodeId, - @JsonKey(name: 'name') required String name, - @JsonKey(name: 'label') String? label, - @JsonKey(name: 'uploader') required GithubUploader uploader, - @JsonKey(name: 'content_type') required String contentType, - @JsonKey(name: 'state') required String state, - @JsonKey(name: 'size') required int size, - @JsonKey(name: 'download_count') required int downloadCount, - @JsonKey(name: 'created_at') required DateTime createdAt, - @JsonKey(name: 'updated_at') required DateTime updatedAt, - @JsonKey(name: 'browser_download_url') required String browserDownloadUrl, - }) = _GithubAsset; - - factory GithubAsset.fromJson(Map json) => _$GithubAssetFromJson(json); -} - -@freezed -class GithubUploader with _$GithubUploader { - const factory GithubUploader({ - @JsonKey(name: 'login') required String login, - @JsonKey(name: 'id') required int id, - @JsonKey(name: 'node_id') required String nodeId, - @JsonKey(name: 'avatar_url') required String avatarUrl, - @JsonKey(name: 'gravatar_id') required String gravatarId, - @JsonKey(name: 'url') required String url, - @JsonKey(name: 'html_url') required String htmlUrl, - @JsonKey(name: 'followers_url') required String followersUrl, - @JsonKey(name: 'following_url') required String followingUrl, - @JsonKey(name: 'gists_url') required String gistsUrl, - @JsonKey(name: 'starred_url') required String starredUrl, - @JsonKey(name: 'subscriptions_url') required String subscriptionsUrl, - @JsonKey(name: 'organizations_url') required String organizationsUrl, - @JsonKey(name: 'repos_url') required String reposUrl, - @JsonKey(name: 'events_url') required String eventsUrl, - @JsonKey(name: 'received_events_url') required String receivedEventsUrl, - @JsonKey(name: 'type') required String type, - @JsonKey(name: 'site_admin') required bool siteAdmin, - }) = _GithubUploader; - - factory GithubUploader.fromJson(Map json) => _$GithubUploaderFromJson(json); -} diff --git a/lib/src/freezed/freezed.freezed.dart b/lib/src/freezed/freezed.freezed.dart deleted file mode 100644 index 74733766..00000000 --- a/lib/src/freezed/freezed.freezed.dart +++ /dev/null @@ -1,2287 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'freezed.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); - -GithubRelease _$GithubReleaseFromJson(Map json) { - return _GithubRelease.fromJson(json); -} - -/// @nodoc -mixin _$GithubRelease { - @JsonKey(name: 'url') - String get url => throw _privateConstructorUsedError; - @JsonKey(name: 'assets_url') - String get assetsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'upload_url') - String get uploadUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'html_url') - String get htmlUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'id') - int get id => throw _privateConstructorUsedError; - @JsonKey(name: 'assets') - List get assets => throw _privateConstructorUsedError; - @JsonKey(name: 'author') - GithubAuthor get author => throw _privateConstructorUsedError; - @JsonKey(name: 'node_id') - String get nodeId => throw _privateConstructorUsedError; - @JsonKey(name: 'tag_name') - String get tagName => throw _privateConstructorUsedError; - @JsonKey(name: 'target_commitish') - String get targetCommitish => throw _privateConstructorUsedError; - @JsonKey(name: 'name') - String get name => throw _privateConstructorUsedError; - @JsonKey(name: 'draft') - bool get draft => throw _privateConstructorUsedError; - @JsonKey(name: 'prerelease') - bool get prerelease => throw _privateConstructorUsedError; - @JsonKey(name: 'created_at') - DateTime get createdAt => throw _privateConstructorUsedError; - @JsonKey(name: 'published_at') - DateTime get publishedAt => throw _privateConstructorUsedError; - @JsonKey(name: 'tarball_url') - String get tarballUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'zipball_url') - String get zipballUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'body') - String get body => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $GithubReleaseCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $GithubReleaseCopyWith<$Res> { - factory $GithubReleaseCopyWith( - GithubRelease value, $Res Function(GithubRelease) then) = - _$GithubReleaseCopyWithImpl<$Res, GithubRelease>; - @useResult - $Res call( - {@JsonKey(name: 'url') String url, - @JsonKey(name: 'assets_url') String assetsUrl, - @JsonKey(name: 'upload_url') String uploadUrl, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'assets') List assets, - @JsonKey(name: 'author') GithubAuthor author, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'tag_name') String tagName, - @JsonKey(name: 'target_commitish') String targetCommitish, - @JsonKey(name: 'name') String name, - @JsonKey(name: 'draft') bool draft, - @JsonKey(name: 'prerelease') bool prerelease, - @JsonKey(name: 'created_at') DateTime createdAt, - @JsonKey(name: 'published_at') DateTime publishedAt, - @JsonKey(name: 'tarball_url') String tarballUrl, - @JsonKey(name: 'zipball_url') String zipballUrl, - @JsonKey(name: 'body') String body}); - - $GithubAuthorCopyWith<$Res> get author; -} - -/// @nodoc -class _$GithubReleaseCopyWithImpl<$Res, $Val extends GithubRelease> - implements $GithubReleaseCopyWith<$Res> { - _$GithubReleaseCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? url = null, - Object? assetsUrl = null, - Object? uploadUrl = null, - Object? htmlUrl = null, - Object? id = null, - Object? assets = null, - Object? author = null, - Object? nodeId = null, - Object? tagName = null, - Object? targetCommitish = null, - Object? name = null, - Object? draft = null, - Object? prerelease = null, - Object? createdAt = null, - Object? publishedAt = null, - Object? tarballUrl = null, - Object? zipballUrl = null, - Object? body = null, - }) { - return _then(_value.copyWith( - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - assetsUrl: null == assetsUrl - ? _value.assetsUrl - : assetsUrl // ignore: cast_nullable_to_non_nullable - as String, - uploadUrl: null == uploadUrl - ? _value.uploadUrl - : uploadUrl // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - assets: null == assets - ? _value.assets - : assets // ignore: cast_nullable_to_non_nullable - as List, - author: null == author - ? _value.author - : author // ignore: cast_nullable_to_non_nullable - as GithubAuthor, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - tagName: null == tagName - ? _value.tagName - : tagName // ignore: cast_nullable_to_non_nullable - as String, - targetCommitish: null == targetCommitish - ? _value.targetCommitish - : targetCommitish // ignore: cast_nullable_to_non_nullable - as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - draft: null == draft - ? _value.draft - : draft // ignore: cast_nullable_to_non_nullable - as bool, - prerelease: null == prerelease - ? _value.prerelease - : prerelease // ignore: cast_nullable_to_non_nullable - as bool, - createdAt: null == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime, - publishedAt: null == publishedAt - ? _value.publishedAt - : publishedAt // ignore: cast_nullable_to_non_nullable - as DateTime, - tarballUrl: null == tarballUrl - ? _value.tarballUrl - : tarballUrl // ignore: cast_nullable_to_non_nullable - as String, - zipballUrl: null == zipballUrl - ? _value.zipballUrl - : zipballUrl // ignore: cast_nullable_to_non_nullable - as String, - body: null == body - ? _value.body - : body // ignore: cast_nullable_to_non_nullable - as String, - ) as $Val); - } - - @override - @pragma('vm:prefer-inline') - $GithubAuthorCopyWith<$Res> get author { - return $GithubAuthorCopyWith<$Res>(_value.author, (value) { - return _then(_value.copyWith(author: value) as $Val); - }); - } -} - -/// @nodoc -abstract class _$$GithubReleaseImplCopyWith<$Res> - implements $GithubReleaseCopyWith<$Res> { - factory _$$GithubReleaseImplCopyWith( - _$GithubReleaseImpl value, $Res Function(_$GithubReleaseImpl) then) = - __$$GithubReleaseImplCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {@JsonKey(name: 'url') String url, - @JsonKey(name: 'assets_url') String assetsUrl, - @JsonKey(name: 'upload_url') String uploadUrl, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'assets') List assets, - @JsonKey(name: 'author') GithubAuthor author, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'tag_name') String tagName, - @JsonKey(name: 'target_commitish') String targetCommitish, - @JsonKey(name: 'name') String name, - @JsonKey(name: 'draft') bool draft, - @JsonKey(name: 'prerelease') bool prerelease, - @JsonKey(name: 'created_at') DateTime createdAt, - @JsonKey(name: 'published_at') DateTime publishedAt, - @JsonKey(name: 'tarball_url') String tarballUrl, - @JsonKey(name: 'zipball_url') String zipballUrl, - @JsonKey(name: 'body') String body}); - - @override - $GithubAuthorCopyWith<$Res> get author; -} - -/// @nodoc -class __$$GithubReleaseImplCopyWithImpl<$Res> - extends _$GithubReleaseCopyWithImpl<$Res, _$GithubReleaseImpl> - implements _$$GithubReleaseImplCopyWith<$Res> { - __$$GithubReleaseImplCopyWithImpl( - _$GithubReleaseImpl _value, $Res Function(_$GithubReleaseImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? url = null, - Object? assetsUrl = null, - Object? uploadUrl = null, - Object? htmlUrl = null, - Object? id = null, - Object? assets = null, - Object? author = null, - Object? nodeId = null, - Object? tagName = null, - Object? targetCommitish = null, - Object? name = null, - Object? draft = null, - Object? prerelease = null, - Object? createdAt = null, - Object? publishedAt = null, - Object? tarballUrl = null, - Object? zipballUrl = null, - Object? body = null, - }) { - return _then(_$GithubReleaseImpl( - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - assetsUrl: null == assetsUrl - ? _value.assetsUrl - : assetsUrl // ignore: cast_nullable_to_non_nullable - as String, - uploadUrl: null == uploadUrl - ? _value.uploadUrl - : uploadUrl // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - assets: null == assets - ? _value._assets - : assets // ignore: cast_nullable_to_non_nullable - as List, - author: null == author - ? _value.author - : author // ignore: cast_nullable_to_non_nullable - as GithubAuthor, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - tagName: null == tagName - ? _value.tagName - : tagName // ignore: cast_nullable_to_non_nullable - as String, - targetCommitish: null == targetCommitish - ? _value.targetCommitish - : targetCommitish // ignore: cast_nullable_to_non_nullable - as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - draft: null == draft - ? _value.draft - : draft // ignore: cast_nullable_to_non_nullable - as bool, - prerelease: null == prerelease - ? _value.prerelease - : prerelease // ignore: cast_nullable_to_non_nullable - as bool, - createdAt: null == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime, - publishedAt: null == publishedAt - ? _value.publishedAt - : publishedAt // ignore: cast_nullable_to_non_nullable - as DateTime, - tarballUrl: null == tarballUrl - ? _value.tarballUrl - : tarballUrl // ignore: cast_nullable_to_non_nullable - as String, - zipballUrl: null == zipballUrl - ? _value.zipballUrl - : zipballUrl // ignore: cast_nullable_to_non_nullable - as String, - body: null == body - ? _value.body - : body // ignore: cast_nullable_to_non_nullable - as String, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$GithubReleaseImpl - with DiagnosticableTreeMixin - implements _GithubRelease { - const _$GithubReleaseImpl( - {@JsonKey(name: 'url') required this.url, - @JsonKey(name: 'assets_url') required this.assetsUrl, - @JsonKey(name: 'upload_url') required this.uploadUrl, - @JsonKey(name: 'html_url') required this.htmlUrl, - @JsonKey(name: 'id') required this.id, - @JsonKey(name: 'assets') required final List assets, - @JsonKey(name: 'author') required this.author, - @JsonKey(name: 'node_id') required this.nodeId, - @JsonKey(name: 'tag_name') required this.tagName, - @JsonKey(name: 'target_commitish') required this.targetCommitish, - @JsonKey(name: 'name') required this.name, - @JsonKey(name: 'draft') required this.draft, - @JsonKey(name: 'prerelease') required this.prerelease, - @JsonKey(name: 'created_at') required this.createdAt, - @JsonKey(name: 'published_at') required this.publishedAt, - @JsonKey(name: 'tarball_url') required this.tarballUrl, - @JsonKey(name: 'zipball_url') required this.zipballUrl, - @JsonKey(name: 'body') required this.body}) - : _assets = assets; - - factory _$GithubReleaseImpl.fromJson(Map json) => - _$$GithubReleaseImplFromJson(json); - - @override - @JsonKey(name: 'url') - final String url; - @override - @JsonKey(name: 'assets_url') - final String assetsUrl; - @override - @JsonKey(name: 'upload_url') - final String uploadUrl; - @override - @JsonKey(name: 'html_url') - final String htmlUrl; - @override - @JsonKey(name: 'id') - final int id; - final List _assets; - @override - @JsonKey(name: 'assets') - List get assets { - if (_assets is EqualUnmodifiableListView) return _assets; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_assets); - } - - @override - @JsonKey(name: 'author') - final GithubAuthor author; - @override - @JsonKey(name: 'node_id') - final String nodeId; - @override - @JsonKey(name: 'tag_name') - final String tagName; - @override - @JsonKey(name: 'target_commitish') - final String targetCommitish; - @override - @JsonKey(name: 'name') - final String name; - @override - @JsonKey(name: 'draft') - final bool draft; - @override - @JsonKey(name: 'prerelease') - final bool prerelease; - @override - @JsonKey(name: 'created_at') - final DateTime createdAt; - @override - @JsonKey(name: 'published_at') - final DateTime publishedAt; - @override - @JsonKey(name: 'tarball_url') - final String tarballUrl; - @override - @JsonKey(name: 'zipball_url') - final String zipballUrl; - @override - @JsonKey(name: 'body') - final String body; - - @override - String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'GithubRelease(url: $url, assetsUrl: $assetsUrl, uploadUrl: $uploadUrl, htmlUrl: $htmlUrl, id: $id, assets: $assets, author: $author, nodeId: $nodeId, tagName: $tagName, targetCommitish: $targetCommitish, name: $name, draft: $draft, prerelease: $prerelease, createdAt: $createdAt, publishedAt: $publishedAt, tarballUrl: $tarballUrl, zipballUrl: $zipballUrl, body: $body)'; - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', 'GithubRelease')) - ..add(DiagnosticsProperty('url', url)) - ..add(DiagnosticsProperty('assetsUrl', assetsUrl)) - ..add(DiagnosticsProperty('uploadUrl', uploadUrl)) - ..add(DiagnosticsProperty('htmlUrl', htmlUrl)) - ..add(DiagnosticsProperty('id', id)) - ..add(DiagnosticsProperty('assets', assets)) - ..add(DiagnosticsProperty('author', author)) - ..add(DiagnosticsProperty('nodeId', nodeId)) - ..add(DiagnosticsProperty('tagName', tagName)) - ..add(DiagnosticsProperty('targetCommitish', targetCommitish)) - ..add(DiagnosticsProperty('name', name)) - ..add(DiagnosticsProperty('draft', draft)) - ..add(DiagnosticsProperty('prerelease', prerelease)) - ..add(DiagnosticsProperty('createdAt', createdAt)) - ..add(DiagnosticsProperty('publishedAt', publishedAt)) - ..add(DiagnosticsProperty('tarballUrl', tarballUrl)) - ..add(DiagnosticsProperty('zipballUrl', zipballUrl)) - ..add(DiagnosticsProperty('body', body)); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$GithubReleaseImpl && - (identical(other.url, url) || other.url == url) && - (identical(other.assetsUrl, assetsUrl) || - other.assetsUrl == assetsUrl) && - (identical(other.uploadUrl, uploadUrl) || - other.uploadUrl == uploadUrl) && - (identical(other.htmlUrl, htmlUrl) || other.htmlUrl == htmlUrl) && - (identical(other.id, id) || other.id == id) && - const DeepCollectionEquality().equals(other._assets, _assets) && - (identical(other.author, author) || other.author == author) && - (identical(other.nodeId, nodeId) || other.nodeId == nodeId) && - (identical(other.tagName, tagName) || other.tagName == tagName) && - (identical(other.targetCommitish, targetCommitish) || - other.targetCommitish == targetCommitish) && - (identical(other.name, name) || other.name == name) && - (identical(other.draft, draft) || other.draft == draft) && - (identical(other.prerelease, prerelease) || - other.prerelease == prerelease) && - (identical(other.createdAt, createdAt) || - other.createdAt == createdAt) && - (identical(other.publishedAt, publishedAt) || - other.publishedAt == publishedAt) && - (identical(other.tarballUrl, tarballUrl) || - other.tarballUrl == tarballUrl) && - (identical(other.zipballUrl, zipballUrl) || - other.zipballUrl == zipballUrl) && - (identical(other.body, body) || other.body == body)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, - url, - assetsUrl, - uploadUrl, - htmlUrl, - id, - const DeepCollectionEquality().hash(_assets), - author, - nodeId, - tagName, - targetCommitish, - name, - draft, - prerelease, - createdAt, - publishedAt, - tarballUrl, - zipballUrl, - body); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$GithubReleaseImplCopyWith<_$GithubReleaseImpl> get copyWith => - __$$GithubReleaseImplCopyWithImpl<_$GithubReleaseImpl>(this, _$identity); - - @override - Map toJson() { - return _$$GithubReleaseImplToJson( - this, - ); - } -} - -abstract class _GithubRelease implements GithubRelease { - const factory _GithubRelease( - {@JsonKey(name: 'url') required final String url, - @JsonKey(name: 'assets_url') required final String assetsUrl, - @JsonKey(name: 'upload_url') required final String uploadUrl, - @JsonKey(name: 'html_url') required final String htmlUrl, - @JsonKey(name: 'id') required final int id, - @JsonKey(name: 'assets') required final List assets, - @JsonKey(name: 'author') required final GithubAuthor author, - @JsonKey(name: 'node_id') required final String nodeId, - @JsonKey(name: 'tag_name') required final String tagName, - @JsonKey(name: 'target_commitish') required final String targetCommitish, - @JsonKey(name: 'name') required final String name, - @JsonKey(name: 'draft') required final bool draft, - @JsonKey(name: 'prerelease') required final bool prerelease, - @JsonKey(name: 'created_at') required final DateTime createdAt, - @JsonKey(name: 'published_at') required final DateTime publishedAt, - @JsonKey(name: 'tarball_url') required final String tarballUrl, - @JsonKey(name: 'zipball_url') required final String zipballUrl, - @JsonKey(name: 'body') required final String body}) = _$GithubReleaseImpl; - - factory _GithubRelease.fromJson(Map json) = - _$GithubReleaseImpl.fromJson; - - @override - @JsonKey(name: 'url') - String get url; - @override - @JsonKey(name: 'assets_url') - String get assetsUrl; - @override - @JsonKey(name: 'upload_url') - String get uploadUrl; - @override - @JsonKey(name: 'html_url') - String get htmlUrl; - @override - @JsonKey(name: 'id') - int get id; - @override - @JsonKey(name: 'assets') - List get assets; - @override - @JsonKey(name: 'author') - GithubAuthor get author; - @override - @JsonKey(name: 'node_id') - String get nodeId; - @override - @JsonKey(name: 'tag_name') - String get tagName; - @override - @JsonKey(name: 'target_commitish') - String get targetCommitish; - @override - @JsonKey(name: 'name') - String get name; - @override - @JsonKey(name: 'draft') - bool get draft; - @override - @JsonKey(name: 'prerelease') - bool get prerelease; - @override - @JsonKey(name: 'created_at') - DateTime get createdAt; - @override - @JsonKey(name: 'published_at') - DateTime get publishedAt; - @override - @JsonKey(name: 'tarball_url') - String get tarballUrl; - @override - @JsonKey(name: 'zipball_url') - String get zipballUrl; - @override - @JsonKey(name: 'body') - String get body; - @override - @JsonKey(ignore: true) - _$$GithubReleaseImplCopyWith<_$GithubReleaseImpl> get copyWith => - throw _privateConstructorUsedError; -} - -GithubAuthor _$GithubAuthorFromJson(Map json) { - return _GithubAuthor.fromJson(json); -} - -/// @nodoc -mixin _$GithubAuthor { - @JsonKey(name: 'login') - String get login => throw _privateConstructorUsedError; - @JsonKey(name: 'id') - int get id => throw _privateConstructorUsedError; - @JsonKey(name: 'node_id') - String get nodeId => throw _privateConstructorUsedError; - @JsonKey(name: 'avatar_url') - String get avatarUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'gravatar_id') - String get gravatarId => throw _privateConstructorUsedError; - @JsonKey(name: 'url') - String get url => throw _privateConstructorUsedError; - @JsonKey(name: 'html_url') - String get htmlUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'followers_url') - String get followersUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'following_url') - String get followingUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'gists_url') - String get gistsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'starred_url') - String get starredUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'subscriptions_url') - String get subscriptionsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'organizations_url') - String get organizationsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'repos_url') - String get reposUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'events_url') - String get eventsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'received_events_url') - String get receivedEventsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'type') - String get type => throw _privateConstructorUsedError; - @JsonKey(name: 'site_admin') - bool get siteAdmin => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $GithubAuthorCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $GithubAuthorCopyWith<$Res> { - factory $GithubAuthorCopyWith( - GithubAuthor value, $Res Function(GithubAuthor) then) = - _$GithubAuthorCopyWithImpl<$Res, GithubAuthor>; - @useResult - $Res call( - {@JsonKey(name: 'login') String login, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'avatar_url') String avatarUrl, - @JsonKey(name: 'gravatar_id') String gravatarId, - @JsonKey(name: 'url') String url, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'followers_url') String followersUrl, - @JsonKey(name: 'following_url') String followingUrl, - @JsonKey(name: 'gists_url') String gistsUrl, - @JsonKey(name: 'starred_url') String starredUrl, - @JsonKey(name: 'subscriptions_url') String subscriptionsUrl, - @JsonKey(name: 'organizations_url') String organizationsUrl, - @JsonKey(name: 'repos_url') String reposUrl, - @JsonKey(name: 'events_url') String eventsUrl, - @JsonKey(name: 'received_events_url') String receivedEventsUrl, - @JsonKey(name: 'type') String type, - @JsonKey(name: 'site_admin') bool siteAdmin}); -} - -/// @nodoc -class _$GithubAuthorCopyWithImpl<$Res, $Val extends GithubAuthor> - implements $GithubAuthorCopyWith<$Res> { - _$GithubAuthorCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? login = null, - Object? id = null, - Object? nodeId = null, - Object? avatarUrl = null, - Object? gravatarId = null, - Object? url = null, - Object? htmlUrl = null, - Object? followersUrl = null, - Object? followingUrl = null, - Object? gistsUrl = null, - Object? starredUrl = null, - Object? subscriptionsUrl = null, - Object? organizationsUrl = null, - Object? reposUrl = null, - Object? eventsUrl = null, - Object? receivedEventsUrl = null, - Object? type = null, - Object? siteAdmin = null, - }) { - return _then(_value.copyWith( - login: null == login - ? _value.login - : login // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - avatarUrl: null == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String, - gravatarId: null == gravatarId - ? _value.gravatarId - : gravatarId // ignore: cast_nullable_to_non_nullable - as String, - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - followersUrl: null == followersUrl - ? _value.followersUrl - : followersUrl // ignore: cast_nullable_to_non_nullable - as String, - followingUrl: null == followingUrl - ? _value.followingUrl - : followingUrl // ignore: cast_nullable_to_non_nullable - as String, - gistsUrl: null == gistsUrl - ? _value.gistsUrl - : gistsUrl // ignore: cast_nullable_to_non_nullable - as String, - starredUrl: null == starredUrl - ? _value.starredUrl - : starredUrl // ignore: cast_nullable_to_non_nullable - as String, - subscriptionsUrl: null == subscriptionsUrl - ? _value.subscriptionsUrl - : subscriptionsUrl // ignore: cast_nullable_to_non_nullable - as String, - organizationsUrl: null == organizationsUrl - ? _value.organizationsUrl - : organizationsUrl // ignore: cast_nullable_to_non_nullable - as String, - reposUrl: null == reposUrl - ? _value.reposUrl - : reposUrl // ignore: cast_nullable_to_non_nullable - as String, - eventsUrl: null == eventsUrl - ? _value.eventsUrl - : eventsUrl // ignore: cast_nullable_to_non_nullable - as String, - receivedEventsUrl: null == receivedEventsUrl - ? _value.receivedEventsUrl - : receivedEventsUrl // ignore: cast_nullable_to_non_nullable - as String, - type: null == type - ? _value.type - : type // ignore: cast_nullable_to_non_nullable - as String, - siteAdmin: null == siteAdmin - ? _value.siteAdmin - : siteAdmin // ignore: cast_nullable_to_non_nullable - as bool, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$GithubAuthorImplCopyWith<$Res> - implements $GithubAuthorCopyWith<$Res> { - factory _$$GithubAuthorImplCopyWith( - _$GithubAuthorImpl value, $Res Function(_$GithubAuthorImpl) then) = - __$$GithubAuthorImplCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {@JsonKey(name: 'login') String login, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'avatar_url') String avatarUrl, - @JsonKey(name: 'gravatar_id') String gravatarId, - @JsonKey(name: 'url') String url, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'followers_url') String followersUrl, - @JsonKey(name: 'following_url') String followingUrl, - @JsonKey(name: 'gists_url') String gistsUrl, - @JsonKey(name: 'starred_url') String starredUrl, - @JsonKey(name: 'subscriptions_url') String subscriptionsUrl, - @JsonKey(name: 'organizations_url') String organizationsUrl, - @JsonKey(name: 'repos_url') String reposUrl, - @JsonKey(name: 'events_url') String eventsUrl, - @JsonKey(name: 'received_events_url') String receivedEventsUrl, - @JsonKey(name: 'type') String type, - @JsonKey(name: 'site_admin') bool siteAdmin}); -} - -/// @nodoc -class __$$GithubAuthorImplCopyWithImpl<$Res> - extends _$GithubAuthorCopyWithImpl<$Res, _$GithubAuthorImpl> - implements _$$GithubAuthorImplCopyWith<$Res> { - __$$GithubAuthorImplCopyWithImpl( - _$GithubAuthorImpl _value, $Res Function(_$GithubAuthorImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? login = null, - Object? id = null, - Object? nodeId = null, - Object? avatarUrl = null, - Object? gravatarId = null, - Object? url = null, - Object? htmlUrl = null, - Object? followersUrl = null, - Object? followingUrl = null, - Object? gistsUrl = null, - Object? starredUrl = null, - Object? subscriptionsUrl = null, - Object? organizationsUrl = null, - Object? reposUrl = null, - Object? eventsUrl = null, - Object? receivedEventsUrl = null, - Object? type = null, - Object? siteAdmin = null, - }) { - return _then(_$GithubAuthorImpl( - login: null == login - ? _value.login - : login // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - avatarUrl: null == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String, - gravatarId: null == gravatarId - ? _value.gravatarId - : gravatarId // ignore: cast_nullable_to_non_nullable - as String, - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - followersUrl: null == followersUrl - ? _value.followersUrl - : followersUrl // ignore: cast_nullable_to_non_nullable - as String, - followingUrl: null == followingUrl - ? _value.followingUrl - : followingUrl // ignore: cast_nullable_to_non_nullable - as String, - gistsUrl: null == gistsUrl - ? _value.gistsUrl - : gistsUrl // ignore: cast_nullable_to_non_nullable - as String, - starredUrl: null == starredUrl - ? _value.starredUrl - : starredUrl // ignore: cast_nullable_to_non_nullable - as String, - subscriptionsUrl: null == subscriptionsUrl - ? _value.subscriptionsUrl - : subscriptionsUrl // ignore: cast_nullable_to_non_nullable - as String, - organizationsUrl: null == organizationsUrl - ? _value.organizationsUrl - : organizationsUrl // ignore: cast_nullable_to_non_nullable - as String, - reposUrl: null == reposUrl - ? _value.reposUrl - : reposUrl // ignore: cast_nullable_to_non_nullable - as String, - eventsUrl: null == eventsUrl - ? _value.eventsUrl - : eventsUrl // ignore: cast_nullable_to_non_nullable - as String, - receivedEventsUrl: null == receivedEventsUrl - ? _value.receivedEventsUrl - : receivedEventsUrl // ignore: cast_nullable_to_non_nullable - as String, - type: null == type - ? _value.type - : type // ignore: cast_nullable_to_non_nullable - as String, - siteAdmin: null == siteAdmin - ? _value.siteAdmin - : siteAdmin // ignore: cast_nullable_to_non_nullable - as bool, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$GithubAuthorImpl with DiagnosticableTreeMixin implements _GithubAuthor { - const _$GithubAuthorImpl( - {@JsonKey(name: 'login') required this.login, - @JsonKey(name: 'id') required this.id, - @JsonKey(name: 'node_id') required this.nodeId, - @JsonKey(name: 'avatar_url') required this.avatarUrl, - @JsonKey(name: 'gravatar_id') required this.gravatarId, - @JsonKey(name: 'url') required this.url, - @JsonKey(name: 'html_url') required this.htmlUrl, - @JsonKey(name: 'followers_url') required this.followersUrl, - @JsonKey(name: 'following_url') required this.followingUrl, - @JsonKey(name: 'gists_url') required this.gistsUrl, - @JsonKey(name: 'starred_url') required this.starredUrl, - @JsonKey(name: 'subscriptions_url') required this.subscriptionsUrl, - @JsonKey(name: 'organizations_url') required this.organizationsUrl, - @JsonKey(name: 'repos_url') required this.reposUrl, - @JsonKey(name: 'events_url') required this.eventsUrl, - @JsonKey(name: 'received_events_url') required this.receivedEventsUrl, - @JsonKey(name: 'type') required this.type, - @JsonKey(name: 'site_admin') required this.siteAdmin}); - - factory _$GithubAuthorImpl.fromJson(Map json) => - _$$GithubAuthorImplFromJson(json); - - @override - @JsonKey(name: 'login') - final String login; - @override - @JsonKey(name: 'id') - final int id; - @override - @JsonKey(name: 'node_id') - final String nodeId; - @override - @JsonKey(name: 'avatar_url') - final String avatarUrl; - @override - @JsonKey(name: 'gravatar_id') - final String gravatarId; - @override - @JsonKey(name: 'url') - final String url; - @override - @JsonKey(name: 'html_url') - final String htmlUrl; - @override - @JsonKey(name: 'followers_url') - final String followersUrl; - @override - @JsonKey(name: 'following_url') - final String followingUrl; - @override - @JsonKey(name: 'gists_url') - final String gistsUrl; - @override - @JsonKey(name: 'starred_url') - final String starredUrl; - @override - @JsonKey(name: 'subscriptions_url') - final String subscriptionsUrl; - @override - @JsonKey(name: 'organizations_url') - final String organizationsUrl; - @override - @JsonKey(name: 'repos_url') - final String reposUrl; - @override - @JsonKey(name: 'events_url') - final String eventsUrl; - @override - @JsonKey(name: 'received_events_url') - final String receivedEventsUrl; - @override - @JsonKey(name: 'type') - final String type; - @override - @JsonKey(name: 'site_admin') - final bool siteAdmin; - - @override - String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'GithubAuthor(login: $login, id: $id, nodeId: $nodeId, avatarUrl: $avatarUrl, gravatarId: $gravatarId, url: $url, htmlUrl: $htmlUrl, followersUrl: $followersUrl, followingUrl: $followingUrl, gistsUrl: $gistsUrl, starredUrl: $starredUrl, subscriptionsUrl: $subscriptionsUrl, organizationsUrl: $organizationsUrl, reposUrl: $reposUrl, eventsUrl: $eventsUrl, receivedEventsUrl: $receivedEventsUrl, type: $type, siteAdmin: $siteAdmin)'; - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', 'GithubAuthor')) - ..add(DiagnosticsProperty('login', login)) - ..add(DiagnosticsProperty('id', id)) - ..add(DiagnosticsProperty('nodeId', nodeId)) - ..add(DiagnosticsProperty('avatarUrl', avatarUrl)) - ..add(DiagnosticsProperty('gravatarId', gravatarId)) - ..add(DiagnosticsProperty('url', url)) - ..add(DiagnosticsProperty('htmlUrl', htmlUrl)) - ..add(DiagnosticsProperty('followersUrl', followersUrl)) - ..add(DiagnosticsProperty('followingUrl', followingUrl)) - ..add(DiagnosticsProperty('gistsUrl', gistsUrl)) - ..add(DiagnosticsProperty('starredUrl', starredUrl)) - ..add(DiagnosticsProperty('subscriptionsUrl', subscriptionsUrl)) - ..add(DiagnosticsProperty('organizationsUrl', organizationsUrl)) - ..add(DiagnosticsProperty('reposUrl', reposUrl)) - ..add(DiagnosticsProperty('eventsUrl', eventsUrl)) - ..add(DiagnosticsProperty('receivedEventsUrl', receivedEventsUrl)) - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('siteAdmin', siteAdmin)); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$GithubAuthorImpl && - (identical(other.login, login) || other.login == login) && - (identical(other.id, id) || other.id == id) && - (identical(other.nodeId, nodeId) || other.nodeId == nodeId) && - (identical(other.avatarUrl, avatarUrl) || - other.avatarUrl == avatarUrl) && - (identical(other.gravatarId, gravatarId) || - other.gravatarId == gravatarId) && - (identical(other.url, url) || other.url == url) && - (identical(other.htmlUrl, htmlUrl) || other.htmlUrl == htmlUrl) && - (identical(other.followersUrl, followersUrl) || - other.followersUrl == followersUrl) && - (identical(other.followingUrl, followingUrl) || - other.followingUrl == followingUrl) && - (identical(other.gistsUrl, gistsUrl) || - other.gistsUrl == gistsUrl) && - (identical(other.starredUrl, starredUrl) || - other.starredUrl == starredUrl) && - (identical(other.subscriptionsUrl, subscriptionsUrl) || - other.subscriptionsUrl == subscriptionsUrl) && - (identical(other.organizationsUrl, organizationsUrl) || - other.organizationsUrl == organizationsUrl) && - (identical(other.reposUrl, reposUrl) || - other.reposUrl == reposUrl) && - (identical(other.eventsUrl, eventsUrl) || - other.eventsUrl == eventsUrl) && - (identical(other.receivedEventsUrl, receivedEventsUrl) || - other.receivedEventsUrl == receivedEventsUrl) && - (identical(other.type, type) || other.type == type) && - (identical(other.siteAdmin, siteAdmin) || - other.siteAdmin == siteAdmin)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, - login, - id, - nodeId, - avatarUrl, - gravatarId, - url, - htmlUrl, - followersUrl, - followingUrl, - gistsUrl, - starredUrl, - subscriptionsUrl, - organizationsUrl, - reposUrl, - eventsUrl, - receivedEventsUrl, - type, - siteAdmin); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$GithubAuthorImplCopyWith<_$GithubAuthorImpl> get copyWith => - __$$GithubAuthorImplCopyWithImpl<_$GithubAuthorImpl>(this, _$identity); - - @override - Map toJson() { - return _$$GithubAuthorImplToJson( - this, - ); - } -} - -abstract class _GithubAuthor implements GithubAuthor { - const factory _GithubAuthor( - {@JsonKey(name: 'login') required final String login, - @JsonKey(name: 'id') required final int id, - @JsonKey(name: 'node_id') required final String nodeId, - @JsonKey(name: 'avatar_url') required final String avatarUrl, - @JsonKey(name: 'gravatar_id') required final String gravatarId, - @JsonKey(name: 'url') required final String url, - @JsonKey(name: 'html_url') required final String htmlUrl, - @JsonKey(name: 'followers_url') required final String followersUrl, - @JsonKey(name: 'following_url') required final String followingUrl, - @JsonKey(name: 'gists_url') required final String gistsUrl, - @JsonKey(name: 'starred_url') required final String starredUrl, - @JsonKey(name: 'subscriptions_url') - required final String subscriptionsUrl, - @JsonKey(name: 'organizations_url') - required final String organizationsUrl, - @JsonKey(name: 'repos_url') required final String reposUrl, - @JsonKey(name: 'events_url') required final String eventsUrl, - @JsonKey(name: 'received_events_url') - required final String receivedEventsUrl, - @JsonKey(name: 'type') required final String type, - @JsonKey(name: 'site_admin') required final bool siteAdmin}) = - _$GithubAuthorImpl; - - factory _GithubAuthor.fromJson(Map json) = - _$GithubAuthorImpl.fromJson; - - @override - @JsonKey(name: 'login') - String get login; - @override - @JsonKey(name: 'id') - int get id; - @override - @JsonKey(name: 'node_id') - String get nodeId; - @override - @JsonKey(name: 'avatar_url') - String get avatarUrl; - @override - @JsonKey(name: 'gravatar_id') - String get gravatarId; - @override - @JsonKey(name: 'url') - String get url; - @override - @JsonKey(name: 'html_url') - String get htmlUrl; - @override - @JsonKey(name: 'followers_url') - String get followersUrl; - @override - @JsonKey(name: 'following_url') - String get followingUrl; - @override - @JsonKey(name: 'gists_url') - String get gistsUrl; - @override - @JsonKey(name: 'starred_url') - String get starredUrl; - @override - @JsonKey(name: 'subscriptions_url') - String get subscriptionsUrl; - @override - @JsonKey(name: 'organizations_url') - String get organizationsUrl; - @override - @JsonKey(name: 'repos_url') - String get reposUrl; - @override - @JsonKey(name: 'events_url') - String get eventsUrl; - @override - @JsonKey(name: 'received_events_url') - String get receivedEventsUrl; - @override - @JsonKey(name: 'type') - String get type; - @override - @JsonKey(name: 'site_admin') - bool get siteAdmin; - @override - @JsonKey(ignore: true) - _$$GithubAuthorImplCopyWith<_$GithubAuthorImpl> get copyWith => - throw _privateConstructorUsedError; -} - -GithubAsset _$GithubAssetFromJson(Map json) { - return _GithubAsset.fromJson(json); -} - -/// @nodoc -mixin _$GithubAsset { - @JsonKey(name: 'url') - String get url => throw _privateConstructorUsedError; - @JsonKey(name: 'id') - int get id => throw _privateConstructorUsedError; - @JsonKey(name: 'node_id') - String get nodeId => throw _privateConstructorUsedError; - @JsonKey(name: 'name') - String get name => throw _privateConstructorUsedError; - @JsonKey(name: 'label') - String? get label => throw _privateConstructorUsedError; - @JsonKey(name: 'uploader') - GithubUploader get uploader => throw _privateConstructorUsedError; - @JsonKey(name: 'content_type') - String get contentType => throw _privateConstructorUsedError; - @JsonKey(name: 'state') - String get state => throw _privateConstructorUsedError; - @JsonKey(name: 'size') - int get size => throw _privateConstructorUsedError; - @JsonKey(name: 'download_count') - int get downloadCount => throw _privateConstructorUsedError; - @JsonKey(name: 'created_at') - DateTime get createdAt => throw _privateConstructorUsedError; - @JsonKey(name: 'updated_at') - DateTime get updatedAt => throw _privateConstructorUsedError; - @JsonKey(name: 'browser_download_url') - String get browserDownloadUrl => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $GithubAssetCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $GithubAssetCopyWith<$Res> { - factory $GithubAssetCopyWith( - GithubAsset value, $Res Function(GithubAsset) then) = - _$GithubAssetCopyWithImpl<$Res, GithubAsset>; - @useResult - $Res call( - {@JsonKey(name: 'url') String url, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'name') String name, - @JsonKey(name: 'label') String? label, - @JsonKey(name: 'uploader') GithubUploader uploader, - @JsonKey(name: 'content_type') String contentType, - @JsonKey(name: 'state') String state, - @JsonKey(name: 'size') int size, - @JsonKey(name: 'download_count') int downloadCount, - @JsonKey(name: 'created_at') DateTime createdAt, - @JsonKey(name: 'updated_at') DateTime updatedAt, - @JsonKey(name: 'browser_download_url') String browserDownloadUrl}); - - $GithubUploaderCopyWith<$Res> get uploader; -} - -/// @nodoc -class _$GithubAssetCopyWithImpl<$Res, $Val extends GithubAsset> - implements $GithubAssetCopyWith<$Res> { - _$GithubAssetCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? url = null, - Object? id = null, - Object? nodeId = null, - Object? name = null, - Object? label = freezed, - Object? uploader = null, - Object? contentType = null, - Object? state = null, - Object? size = null, - Object? downloadCount = null, - Object? createdAt = null, - Object? updatedAt = null, - Object? browserDownloadUrl = null, - }) { - return _then(_value.copyWith( - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - label: freezed == label - ? _value.label - : label // ignore: cast_nullable_to_non_nullable - as String?, - uploader: null == uploader - ? _value.uploader - : uploader // ignore: cast_nullable_to_non_nullable - as GithubUploader, - contentType: null == contentType - ? _value.contentType - : contentType // ignore: cast_nullable_to_non_nullable - as String, - state: null == state - ? _value.state - : state // ignore: cast_nullable_to_non_nullable - as String, - size: null == size - ? _value.size - : size // ignore: cast_nullable_to_non_nullable - as int, - downloadCount: null == downloadCount - ? _value.downloadCount - : downloadCount // ignore: cast_nullable_to_non_nullable - as int, - createdAt: null == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime, - updatedAt: null == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime, - browserDownloadUrl: null == browserDownloadUrl - ? _value.browserDownloadUrl - : browserDownloadUrl // ignore: cast_nullable_to_non_nullable - as String, - ) as $Val); - } - - @override - @pragma('vm:prefer-inline') - $GithubUploaderCopyWith<$Res> get uploader { - return $GithubUploaderCopyWith<$Res>(_value.uploader, (value) { - return _then(_value.copyWith(uploader: value) as $Val); - }); - } -} - -/// @nodoc -abstract class _$$GithubAssetImplCopyWith<$Res> - implements $GithubAssetCopyWith<$Res> { - factory _$$GithubAssetImplCopyWith( - _$GithubAssetImpl value, $Res Function(_$GithubAssetImpl) then) = - __$$GithubAssetImplCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {@JsonKey(name: 'url') String url, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'name') String name, - @JsonKey(name: 'label') String? label, - @JsonKey(name: 'uploader') GithubUploader uploader, - @JsonKey(name: 'content_type') String contentType, - @JsonKey(name: 'state') String state, - @JsonKey(name: 'size') int size, - @JsonKey(name: 'download_count') int downloadCount, - @JsonKey(name: 'created_at') DateTime createdAt, - @JsonKey(name: 'updated_at') DateTime updatedAt, - @JsonKey(name: 'browser_download_url') String browserDownloadUrl}); - - @override - $GithubUploaderCopyWith<$Res> get uploader; -} - -/// @nodoc -class __$$GithubAssetImplCopyWithImpl<$Res> - extends _$GithubAssetCopyWithImpl<$Res, _$GithubAssetImpl> - implements _$$GithubAssetImplCopyWith<$Res> { - __$$GithubAssetImplCopyWithImpl( - _$GithubAssetImpl _value, $Res Function(_$GithubAssetImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? url = null, - Object? id = null, - Object? nodeId = null, - Object? name = null, - Object? label = freezed, - Object? uploader = null, - Object? contentType = null, - Object? state = null, - Object? size = null, - Object? downloadCount = null, - Object? createdAt = null, - Object? updatedAt = null, - Object? browserDownloadUrl = null, - }) { - return _then(_$GithubAssetImpl( - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable - as String, - label: freezed == label - ? _value.label - : label // ignore: cast_nullable_to_non_nullable - as String?, - uploader: null == uploader - ? _value.uploader - : uploader // ignore: cast_nullable_to_non_nullable - as GithubUploader, - contentType: null == contentType - ? _value.contentType - : contentType // ignore: cast_nullable_to_non_nullable - as String, - state: null == state - ? _value.state - : state // ignore: cast_nullable_to_non_nullable - as String, - size: null == size - ? _value.size - : size // ignore: cast_nullable_to_non_nullable - as int, - downloadCount: null == downloadCount - ? _value.downloadCount - : downloadCount // ignore: cast_nullable_to_non_nullable - as int, - createdAt: null == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime, - updatedAt: null == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime, - browserDownloadUrl: null == browserDownloadUrl - ? _value.browserDownloadUrl - : browserDownloadUrl // ignore: cast_nullable_to_non_nullable - as String, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$GithubAssetImpl with DiagnosticableTreeMixin implements _GithubAsset { - const _$GithubAssetImpl( - {@JsonKey(name: 'url') required this.url, - @JsonKey(name: 'id') required this.id, - @JsonKey(name: 'node_id') required this.nodeId, - @JsonKey(name: 'name') required this.name, - @JsonKey(name: 'label') this.label, - @JsonKey(name: 'uploader') required this.uploader, - @JsonKey(name: 'content_type') required this.contentType, - @JsonKey(name: 'state') required this.state, - @JsonKey(name: 'size') required this.size, - @JsonKey(name: 'download_count') required this.downloadCount, - @JsonKey(name: 'created_at') required this.createdAt, - @JsonKey(name: 'updated_at') required this.updatedAt, - @JsonKey(name: 'browser_download_url') required this.browserDownloadUrl}); - - factory _$GithubAssetImpl.fromJson(Map json) => - _$$GithubAssetImplFromJson(json); - - @override - @JsonKey(name: 'url') - final String url; - @override - @JsonKey(name: 'id') - final int id; - @override - @JsonKey(name: 'node_id') - final String nodeId; - @override - @JsonKey(name: 'name') - final String name; - @override - @JsonKey(name: 'label') - final String? label; - @override - @JsonKey(name: 'uploader') - final GithubUploader uploader; - @override - @JsonKey(name: 'content_type') - final String contentType; - @override - @JsonKey(name: 'state') - final String state; - @override - @JsonKey(name: 'size') - final int size; - @override - @JsonKey(name: 'download_count') - final int downloadCount; - @override - @JsonKey(name: 'created_at') - final DateTime createdAt; - @override - @JsonKey(name: 'updated_at') - final DateTime updatedAt; - @override - @JsonKey(name: 'browser_download_url') - final String browserDownloadUrl; - - @override - String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'GithubAsset(url: $url, id: $id, nodeId: $nodeId, name: $name, label: $label, uploader: $uploader, contentType: $contentType, state: $state, size: $size, downloadCount: $downloadCount, createdAt: $createdAt, updatedAt: $updatedAt, browserDownloadUrl: $browserDownloadUrl)'; - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', 'GithubAsset')) - ..add(DiagnosticsProperty('url', url)) - ..add(DiagnosticsProperty('id', id)) - ..add(DiagnosticsProperty('nodeId', nodeId)) - ..add(DiagnosticsProperty('name', name)) - ..add(DiagnosticsProperty('label', label)) - ..add(DiagnosticsProperty('uploader', uploader)) - ..add(DiagnosticsProperty('contentType', contentType)) - ..add(DiagnosticsProperty('state', state)) - ..add(DiagnosticsProperty('size', size)) - ..add(DiagnosticsProperty('downloadCount', downloadCount)) - ..add(DiagnosticsProperty('createdAt', createdAt)) - ..add(DiagnosticsProperty('updatedAt', updatedAt)) - ..add(DiagnosticsProperty('browserDownloadUrl', browserDownloadUrl)); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$GithubAssetImpl && - (identical(other.url, url) || other.url == url) && - (identical(other.id, id) || other.id == id) && - (identical(other.nodeId, nodeId) || other.nodeId == nodeId) && - (identical(other.name, name) || other.name == name) && - (identical(other.label, label) || other.label == label) && - (identical(other.uploader, uploader) || - other.uploader == uploader) && - (identical(other.contentType, contentType) || - other.contentType == contentType) && - (identical(other.state, state) || other.state == state) && - (identical(other.size, size) || other.size == size) && - (identical(other.downloadCount, downloadCount) || - other.downloadCount == downloadCount) && - (identical(other.createdAt, createdAt) || - other.createdAt == createdAt) && - (identical(other.updatedAt, updatedAt) || - other.updatedAt == updatedAt) && - (identical(other.browserDownloadUrl, browserDownloadUrl) || - other.browserDownloadUrl == browserDownloadUrl)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, - url, - id, - nodeId, - name, - label, - uploader, - contentType, - state, - size, - downloadCount, - createdAt, - updatedAt, - browserDownloadUrl); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$GithubAssetImplCopyWith<_$GithubAssetImpl> get copyWith => - __$$GithubAssetImplCopyWithImpl<_$GithubAssetImpl>(this, _$identity); - - @override - Map toJson() { - return _$$GithubAssetImplToJson( - this, - ); - } -} - -abstract class _GithubAsset implements GithubAsset { - const factory _GithubAsset( - {@JsonKey(name: 'url') required final String url, - @JsonKey(name: 'id') required final int id, - @JsonKey(name: 'node_id') required final String nodeId, - @JsonKey(name: 'name') required final String name, - @JsonKey(name: 'label') final String? label, - @JsonKey(name: 'uploader') required final GithubUploader uploader, - @JsonKey(name: 'content_type') required final String contentType, - @JsonKey(name: 'state') required final String state, - @JsonKey(name: 'size') required final int size, - @JsonKey(name: 'download_count') required final int downloadCount, - @JsonKey(name: 'created_at') required final DateTime createdAt, - @JsonKey(name: 'updated_at') required final DateTime updatedAt, - @JsonKey(name: 'browser_download_url') - required final String browserDownloadUrl}) = _$GithubAssetImpl; - - factory _GithubAsset.fromJson(Map json) = - _$GithubAssetImpl.fromJson; - - @override - @JsonKey(name: 'url') - String get url; - @override - @JsonKey(name: 'id') - int get id; - @override - @JsonKey(name: 'node_id') - String get nodeId; - @override - @JsonKey(name: 'name') - String get name; - @override - @JsonKey(name: 'label') - String? get label; - @override - @JsonKey(name: 'uploader') - GithubUploader get uploader; - @override - @JsonKey(name: 'content_type') - String get contentType; - @override - @JsonKey(name: 'state') - String get state; - @override - @JsonKey(name: 'size') - int get size; - @override - @JsonKey(name: 'download_count') - int get downloadCount; - @override - @JsonKey(name: 'created_at') - DateTime get createdAt; - @override - @JsonKey(name: 'updated_at') - DateTime get updatedAt; - @override - @JsonKey(name: 'browser_download_url') - String get browserDownloadUrl; - @override - @JsonKey(ignore: true) - _$$GithubAssetImplCopyWith<_$GithubAssetImpl> get copyWith => - throw _privateConstructorUsedError; -} - -GithubUploader _$GithubUploaderFromJson(Map json) { - return _GithubUploader.fromJson(json); -} - -/// @nodoc -mixin _$GithubUploader { - @JsonKey(name: 'login') - String get login => throw _privateConstructorUsedError; - @JsonKey(name: 'id') - int get id => throw _privateConstructorUsedError; - @JsonKey(name: 'node_id') - String get nodeId => throw _privateConstructorUsedError; - @JsonKey(name: 'avatar_url') - String get avatarUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'gravatar_id') - String get gravatarId => throw _privateConstructorUsedError; - @JsonKey(name: 'url') - String get url => throw _privateConstructorUsedError; - @JsonKey(name: 'html_url') - String get htmlUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'followers_url') - String get followersUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'following_url') - String get followingUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'gists_url') - String get gistsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'starred_url') - String get starredUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'subscriptions_url') - String get subscriptionsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'organizations_url') - String get organizationsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'repos_url') - String get reposUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'events_url') - String get eventsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'received_events_url') - String get receivedEventsUrl => throw _privateConstructorUsedError; - @JsonKey(name: 'type') - String get type => throw _privateConstructorUsedError; - @JsonKey(name: 'site_admin') - bool get siteAdmin => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $GithubUploaderCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $GithubUploaderCopyWith<$Res> { - factory $GithubUploaderCopyWith( - GithubUploader value, $Res Function(GithubUploader) then) = - _$GithubUploaderCopyWithImpl<$Res, GithubUploader>; - @useResult - $Res call( - {@JsonKey(name: 'login') String login, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'avatar_url') String avatarUrl, - @JsonKey(name: 'gravatar_id') String gravatarId, - @JsonKey(name: 'url') String url, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'followers_url') String followersUrl, - @JsonKey(name: 'following_url') String followingUrl, - @JsonKey(name: 'gists_url') String gistsUrl, - @JsonKey(name: 'starred_url') String starredUrl, - @JsonKey(name: 'subscriptions_url') String subscriptionsUrl, - @JsonKey(name: 'organizations_url') String organizationsUrl, - @JsonKey(name: 'repos_url') String reposUrl, - @JsonKey(name: 'events_url') String eventsUrl, - @JsonKey(name: 'received_events_url') String receivedEventsUrl, - @JsonKey(name: 'type') String type, - @JsonKey(name: 'site_admin') bool siteAdmin}); -} - -/// @nodoc -class _$GithubUploaderCopyWithImpl<$Res, $Val extends GithubUploader> - implements $GithubUploaderCopyWith<$Res> { - _$GithubUploaderCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? login = null, - Object? id = null, - Object? nodeId = null, - Object? avatarUrl = null, - Object? gravatarId = null, - Object? url = null, - Object? htmlUrl = null, - Object? followersUrl = null, - Object? followingUrl = null, - Object? gistsUrl = null, - Object? starredUrl = null, - Object? subscriptionsUrl = null, - Object? organizationsUrl = null, - Object? reposUrl = null, - Object? eventsUrl = null, - Object? receivedEventsUrl = null, - Object? type = null, - Object? siteAdmin = null, - }) { - return _then(_value.copyWith( - login: null == login - ? _value.login - : login // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - avatarUrl: null == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String, - gravatarId: null == gravatarId - ? _value.gravatarId - : gravatarId // ignore: cast_nullable_to_non_nullable - as String, - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - followersUrl: null == followersUrl - ? _value.followersUrl - : followersUrl // ignore: cast_nullable_to_non_nullable - as String, - followingUrl: null == followingUrl - ? _value.followingUrl - : followingUrl // ignore: cast_nullable_to_non_nullable - as String, - gistsUrl: null == gistsUrl - ? _value.gistsUrl - : gistsUrl // ignore: cast_nullable_to_non_nullable - as String, - starredUrl: null == starredUrl - ? _value.starredUrl - : starredUrl // ignore: cast_nullable_to_non_nullable - as String, - subscriptionsUrl: null == subscriptionsUrl - ? _value.subscriptionsUrl - : subscriptionsUrl // ignore: cast_nullable_to_non_nullable - as String, - organizationsUrl: null == organizationsUrl - ? _value.organizationsUrl - : organizationsUrl // ignore: cast_nullable_to_non_nullable - as String, - reposUrl: null == reposUrl - ? _value.reposUrl - : reposUrl // ignore: cast_nullable_to_non_nullable - as String, - eventsUrl: null == eventsUrl - ? _value.eventsUrl - : eventsUrl // ignore: cast_nullable_to_non_nullable - as String, - receivedEventsUrl: null == receivedEventsUrl - ? _value.receivedEventsUrl - : receivedEventsUrl // ignore: cast_nullable_to_non_nullable - as String, - type: null == type - ? _value.type - : type // ignore: cast_nullable_to_non_nullable - as String, - siteAdmin: null == siteAdmin - ? _value.siteAdmin - : siteAdmin // ignore: cast_nullable_to_non_nullable - as bool, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$GithubUploaderImplCopyWith<$Res> - implements $GithubUploaderCopyWith<$Res> { - factory _$$GithubUploaderImplCopyWith(_$GithubUploaderImpl value, - $Res Function(_$GithubUploaderImpl) then) = - __$$GithubUploaderImplCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {@JsonKey(name: 'login') String login, - @JsonKey(name: 'id') int id, - @JsonKey(name: 'node_id') String nodeId, - @JsonKey(name: 'avatar_url') String avatarUrl, - @JsonKey(name: 'gravatar_id') String gravatarId, - @JsonKey(name: 'url') String url, - @JsonKey(name: 'html_url') String htmlUrl, - @JsonKey(name: 'followers_url') String followersUrl, - @JsonKey(name: 'following_url') String followingUrl, - @JsonKey(name: 'gists_url') String gistsUrl, - @JsonKey(name: 'starred_url') String starredUrl, - @JsonKey(name: 'subscriptions_url') String subscriptionsUrl, - @JsonKey(name: 'organizations_url') String organizationsUrl, - @JsonKey(name: 'repos_url') String reposUrl, - @JsonKey(name: 'events_url') String eventsUrl, - @JsonKey(name: 'received_events_url') String receivedEventsUrl, - @JsonKey(name: 'type') String type, - @JsonKey(name: 'site_admin') bool siteAdmin}); -} - -/// @nodoc -class __$$GithubUploaderImplCopyWithImpl<$Res> - extends _$GithubUploaderCopyWithImpl<$Res, _$GithubUploaderImpl> - implements _$$GithubUploaderImplCopyWith<$Res> { - __$$GithubUploaderImplCopyWithImpl( - _$GithubUploaderImpl _value, $Res Function(_$GithubUploaderImpl) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? login = null, - Object? id = null, - Object? nodeId = null, - Object? avatarUrl = null, - Object? gravatarId = null, - Object? url = null, - Object? htmlUrl = null, - Object? followersUrl = null, - Object? followingUrl = null, - Object? gistsUrl = null, - Object? starredUrl = null, - Object? subscriptionsUrl = null, - Object? organizationsUrl = null, - Object? reposUrl = null, - Object? eventsUrl = null, - Object? receivedEventsUrl = null, - Object? type = null, - Object? siteAdmin = null, - }) { - return _then(_$GithubUploaderImpl( - login: null == login - ? _value.login - : login // ignore: cast_nullable_to_non_nullable - as String, - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - nodeId: null == nodeId - ? _value.nodeId - : nodeId // ignore: cast_nullable_to_non_nullable - as String, - avatarUrl: null == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String, - gravatarId: null == gravatarId - ? _value.gravatarId - : gravatarId // ignore: cast_nullable_to_non_nullable - as String, - url: null == url - ? _value.url - : url // ignore: cast_nullable_to_non_nullable - as String, - htmlUrl: null == htmlUrl - ? _value.htmlUrl - : htmlUrl // ignore: cast_nullable_to_non_nullable - as String, - followersUrl: null == followersUrl - ? _value.followersUrl - : followersUrl // ignore: cast_nullable_to_non_nullable - as String, - followingUrl: null == followingUrl - ? _value.followingUrl - : followingUrl // ignore: cast_nullable_to_non_nullable - as String, - gistsUrl: null == gistsUrl - ? _value.gistsUrl - : gistsUrl // ignore: cast_nullable_to_non_nullable - as String, - starredUrl: null == starredUrl - ? _value.starredUrl - : starredUrl // ignore: cast_nullable_to_non_nullable - as String, - subscriptionsUrl: null == subscriptionsUrl - ? _value.subscriptionsUrl - : subscriptionsUrl // ignore: cast_nullable_to_non_nullable - as String, - organizationsUrl: null == organizationsUrl - ? _value.organizationsUrl - : organizationsUrl // ignore: cast_nullable_to_non_nullable - as String, - reposUrl: null == reposUrl - ? _value.reposUrl - : reposUrl // ignore: cast_nullable_to_non_nullable - as String, - eventsUrl: null == eventsUrl - ? _value.eventsUrl - : eventsUrl // ignore: cast_nullable_to_non_nullable - as String, - receivedEventsUrl: null == receivedEventsUrl - ? _value.receivedEventsUrl - : receivedEventsUrl // ignore: cast_nullable_to_non_nullable - as String, - type: null == type - ? _value.type - : type // ignore: cast_nullable_to_non_nullable - as String, - siteAdmin: null == siteAdmin - ? _value.siteAdmin - : siteAdmin // ignore: cast_nullable_to_non_nullable - as bool, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$GithubUploaderImpl - with DiagnosticableTreeMixin - implements _GithubUploader { - const _$GithubUploaderImpl( - {@JsonKey(name: 'login') required this.login, - @JsonKey(name: 'id') required this.id, - @JsonKey(name: 'node_id') required this.nodeId, - @JsonKey(name: 'avatar_url') required this.avatarUrl, - @JsonKey(name: 'gravatar_id') required this.gravatarId, - @JsonKey(name: 'url') required this.url, - @JsonKey(name: 'html_url') required this.htmlUrl, - @JsonKey(name: 'followers_url') required this.followersUrl, - @JsonKey(name: 'following_url') required this.followingUrl, - @JsonKey(name: 'gists_url') required this.gistsUrl, - @JsonKey(name: 'starred_url') required this.starredUrl, - @JsonKey(name: 'subscriptions_url') required this.subscriptionsUrl, - @JsonKey(name: 'organizations_url') required this.organizationsUrl, - @JsonKey(name: 'repos_url') required this.reposUrl, - @JsonKey(name: 'events_url') required this.eventsUrl, - @JsonKey(name: 'received_events_url') required this.receivedEventsUrl, - @JsonKey(name: 'type') required this.type, - @JsonKey(name: 'site_admin') required this.siteAdmin}); - - factory _$GithubUploaderImpl.fromJson(Map json) => - _$$GithubUploaderImplFromJson(json); - - @override - @JsonKey(name: 'login') - final String login; - @override - @JsonKey(name: 'id') - final int id; - @override - @JsonKey(name: 'node_id') - final String nodeId; - @override - @JsonKey(name: 'avatar_url') - final String avatarUrl; - @override - @JsonKey(name: 'gravatar_id') - final String gravatarId; - @override - @JsonKey(name: 'url') - final String url; - @override - @JsonKey(name: 'html_url') - final String htmlUrl; - @override - @JsonKey(name: 'followers_url') - final String followersUrl; - @override - @JsonKey(name: 'following_url') - final String followingUrl; - @override - @JsonKey(name: 'gists_url') - final String gistsUrl; - @override - @JsonKey(name: 'starred_url') - final String starredUrl; - @override - @JsonKey(name: 'subscriptions_url') - final String subscriptionsUrl; - @override - @JsonKey(name: 'organizations_url') - final String organizationsUrl; - @override - @JsonKey(name: 'repos_url') - final String reposUrl; - @override - @JsonKey(name: 'events_url') - final String eventsUrl; - @override - @JsonKey(name: 'received_events_url') - final String receivedEventsUrl; - @override - @JsonKey(name: 'type') - final String type; - @override - @JsonKey(name: 'site_admin') - final bool siteAdmin; - - @override - String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'GithubUploader(login: $login, id: $id, nodeId: $nodeId, avatarUrl: $avatarUrl, gravatarId: $gravatarId, url: $url, htmlUrl: $htmlUrl, followersUrl: $followersUrl, followingUrl: $followingUrl, gistsUrl: $gistsUrl, starredUrl: $starredUrl, subscriptionsUrl: $subscriptionsUrl, organizationsUrl: $organizationsUrl, reposUrl: $reposUrl, eventsUrl: $eventsUrl, receivedEventsUrl: $receivedEventsUrl, type: $type, siteAdmin: $siteAdmin)'; - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', 'GithubUploader')) - ..add(DiagnosticsProperty('login', login)) - ..add(DiagnosticsProperty('id', id)) - ..add(DiagnosticsProperty('nodeId', nodeId)) - ..add(DiagnosticsProperty('avatarUrl', avatarUrl)) - ..add(DiagnosticsProperty('gravatarId', gravatarId)) - ..add(DiagnosticsProperty('url', url)) - ..add(DiagnosticsProperty('htmlUrl', htmlUrl)) - ..add(DiagnosticsProperty('followersUrl', followersUrl)) - ..add(DiagnosticsProperty('followingUrl', followingUrl)) - ..add(DiagnosticsProperty('gistsUrl', gistsUrl)) - ..add(DiagnosticsProperty('starredUrl', starredUrl)) - ..add(DiagnosticsProperty('subscriptionsUrl', subscriptionsUrl)) - ..add(DiagnosticsProperty('organizationsUrl', organizationsUrl)) - ..add(DiagnosticsProperty('reposUrl', reposUrl)) - ..add(DiagnosticsProperty('eventsUrl', eventsUrl)) - ..add(DiagnosticsProperty('receivedEventsUrl', receivedEventsUrl)) - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('siteAdmin', siteAdmin)); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$GithubUploaderImpl && - (identical(other.login, login) || other.login == login) && - (identical(other.id, id) || other.id == id) && - (identical(other.nodeId, nodeId) || other.nodeId == nodeId) && - (identical(other.avatarUrl, avatarUrl) || - other.avatarUrl == avatarUrl) && - (identical(other.gravatarId, gravatarId) || - other.gravatarId == gravatarId) && - (identical(other.url, url) || other.url == url) && - (identical(other.htmlUrl, htmlUrl) || other.htmlUrl == htmlUrl) && - (identical(other.followersUrl, followersUrl) || - other.followersUrl == followersUrl) && - (identical(other.followingUrl, followingUrl) || - other.followingUrl == followingUrl) && - (identical(other.gistsUrl, gistsUrl) || - other.gistsUrl == gistsUrl) && - (identical(other.starredUrl, starredUrl) || - other.starredUrl == starredUrl) && - (identical(other.subscriptionsUrl, subscriptionsUrl) || - other.subscriptionsUrl == subscriptionsUrl) && - (identical(other.organizationsUrl, organizationsUrl) || - other.organizationsUrl == organizationsUrl) && - (identical(other.reposUrl, reposUrl) || - other.reposUrl == reposUrl) && - (identical(other.eventsUrl, eventsUrl) || - other.eventsUrl == eventsUrl) && - (identical(other.receivedEventsUrl, receivedEventsUrl) || - other.receivedEventsUrl == receivedEventsUrl) && - (identical(other.type, type) || other.type == type) && - (identical(other.siteAdmin, siteAdmin) || - other.siteAdmin == siteAdmin)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, - login, - id, - nodeId, - avatarUrl, - gravatarId, - url, - htmlUrl, - followersUrl, - followingUrl, - gistsUrl, - starredUrl, - subscriptionsUrl, - organizationsUrl, - reposUrl, - eventsUrl, - receivedEventsUrl, - type, - siteAdmin); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$GithubUploaderImplCopyWith<_$GithubUploaderImpl> get copyWith => - __$$GithubUploaderImplCopyWithImpl<_$GithubUploaderImpl>( - this, _$identity); - - @override - Map toJson() { - return _$$GithubUploaderImplToJson( - this, - ); - } -} - -abstract class _GithubUploader implements GithubUploader { - const factory _GithubUploader( - {@JsonKey(name: 'login') required final String login, - @JsonKey(name: 'id') required final int id, - @JsonKey(name: 'node_id') required final String nodeId, - @JsonKey(name: 'avatar_url') required final String avatarUrl, - @JsonKey(name: 'gravatar_id') required final String gravatarId, - @JsonKey(name: 'url') required final String url, - @JsonKey(name: 'html_url') required final String htmlUrl, - @JsonKey(name: 'followers_url') required final String followersUrl, - @JsonKey(name: 'following_url') required final String followingUrl, - @JsonKey(name: 'gists_url') required final String gistsUrl, - @JsonKey(name: 'starred_url') required final String starredUrl, - @JsonKey(name: 'subscriptions_url') - required final String subscriptionsUrl, - @JsonKey(name: 'organizations_url') - required final String organizationsUrl, - @JsonKey(name: 'repos_url') required final String reposUrl, - @JsonKey(name: 'events_url') required final String eventsUrl, - @JsonKey(name: 'received_events_url') - required final String receivedEventsUrl, - @JsonKey(name: 'type') required final String type, - @JsonKey(name: 'site_admin') required final bool siteAdmin}) = - _$GithubUploaderImpl; - - factory _GithubUploader.fromJson(Map json) = - _$GithubUploaderImpl.fromJson; - - @override - @JsonKey(name: 'login') - String get login; - @override - @JsonKey(name: 'id') - int get id; - @override - @JsonKey(name: 'node_id') - String get nodeId; - @override - @JsonKey(name: 'avatar_url') - String get avatarUrl; - @override - @JsonKey(name: 'gravatar_id') - String get gravatarId; - @override - @JsonKey(name: 'url') - String get url; - @override - @JsonKey(name: 'html_url') - String get htmlUrl; - @override - @JsonKey(name: 'followers_url') - String get followersUrl; - @override - @JsonKey(name: 'following_url') - String get followingUrl; - @override - @JsonKey(name: 'gists_url') - String get gistsUrl; - @override - @JsonKey(name: 'starred_url') - String get starredUrl; - @override - @JsonKey(name: 'subscriptions_url') - String get subscriptionsUrl; - @override - @JsonKey(name: 'organizations_url') - String get organizationsUrl; - @override - @JsonKey(name: 'repos_url') - String get reposUrl; - @override - @JsonKey(name: 'events_url') - String get eventsUrl; - @override - @JsonKey(name: 'received_events_url') - String get receivedEventsUrl; - @override - @JsonKey(name: 'type') - String get type; - @override - @JsonKey(name: 'site_admin') - bool get siteAdmin; - @override - @JsonKey(ignore: true) - _$$GithubUploaderImplCopyWith<_$GithubUploaderImpl> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/src/freezed/freezed.g.dart b/lib/src/freezed/freezed.g.dart deleted file mode 100644 index 9212364d..00000000 --- a/lib/src/freezed/freezed.g.dart +++ /dev/null @@ -1,177 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'freezed.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_$GithubReleaseImpl _$$GithubReleaseImplFromJson(Map json) => - _$GithubReleaseImpl( - url: json['url'] as String, - assetsUrl: json['assets_url'] as String, - uploadUrl: json['upload_url'] as String, - htmlUrl: json['html_url'] as String, - id: (json['id'] as num).toInt(), - assets: (json['assets'] as List) - .map((e) => GithubAsset.fromJson(e as Map)) - .toList(), - author: GithubAuthor.fromJson(json['author'] as Map), - nodeId: json['node_id'] as String, - tagName: json['tag_name'] as String, - targetCommitish: json['target_commitish'] as String, - name: json['name'] as String, - draft: json['draft'] as bool, - prerelease: json['prerelease'] as bool, - createdAt: DateTime.parse(json['created_at'] as String), - publishedAt: DateTime.parse(json['published_at'] as String), - tarballUrl: json['tarball_url'] as String, - zipballUrl: json['zipball_url'] as String, - body: json['body'] as String, - ); - -Map _$$GithubReleaseImplToJson(_$GithubReleaseImpl instance) => - { - 'url': instance.url, - 'assets_url': instance.assetsUrl, - 'upload_url': instance.uploadUrl, - 'html_url': instance.htmlUrl, - 'id': instance.id, - 'assets': instance.assets, - 'author': instance.author, - 'node_id': instance.nodeId, - 'tag_name': instance.tagName, - 'target_commitish': instance.targetCommitish, - 'name': instance.name, - 'draft': instance.draft, - 'prerelease': instance.prerelease, - 'created_at': instance.createdAt.toIso8601String(), - 'published_at': instance.publishedAt.toIso8601String(), - 'tarball_url': instance.tarballUrl, - 'zipball_url': instance.zipballUrl, - 'body': instance.body, - }; - -_$GithubAuthorImpl _$$GithubAuthorImplFromJson(Map json) => - _$GithubAuthorImpl( - login: json['login'] as String, - id: (json['id'] as num).toInt(), - nodeId: json['node_id'] as String, - avatarUrl: json['avatar_url'] as String, - gravatarId: json['gravatar_id'] as String, - url: json['url'] as String, - htmlUrl: json['html_url'] as String, - followersUrl: json['followers_url'] as String, - followingUrl: json['following_url'] as String, - gistsUrl: json['gists_url'] as String, - starredUrl: json['starred_url'] as String, - subscriptionsUrl: json['subscriptions_url'] as String, - organizationsUrl: json['organizations_url'] as String, - reposUrl: json['repos_url'] as String, - eventsUrl: json['events_url'] as String, - receivedEventsUrl: json['received_events_url'] as String, - type: json['type'] as String, - siteAdmin: json['site_admin'] as bool, - ); - -Map _$$GithubAuthorImplToJson(_$GithubAuthorImpl instance) => - { - 'login': instance.login, - 'id': instance.id, - 'node_id': instance.nodeId, - 'avatar_url': instance.avatarUrl, - 'gravatar_id': instance.gravatarId, - 'url': instance.url, - 'html_url': instance.htmlUrl, - 'followers_url': instance.followersUrl, - 'following_url': instance.followingUrl, - 'gists_url': instance.gistsUrl, - 'starred_url': instance.starredUrl, - 'subscriptions_url': instance.subscriptionsUrl, - 'organizations_url': instance.organizationsUrl, - 'repos_url': instance.reposUrl, - 'events_url': instance.eventsUrl, - 'received_events_url': instance.receivedEventsUrl, - 'type': instance.type, - 'site_admin': instance.siteAdmin, - }; - -_$GithubAssetImpl _$$GithubAssetImplFromJson(Map json) => - _$GithubAssetImpl( - url: json['url'] as String, - id: (json['id'] as num).toInt(), - nodeId: json['node_id'] as String, - name: json['name'] as String, - label: json['label'] as String?, - uploader: - GithubUploader.fromJson(json['uploader'] as Map), - contentType: json['content_type'] as String, - state: json['state'] as String, - size: (json['size'] as num).toInt(), - downloadCount: (json['download_count'] as num).toInt(), - createdAt: DateTime.parse(json['created_at'] as String), - updatedAt: DateTime.parse(json['updated_at'] as String), - browserDownloadUrl: json['browser_download_url'] as String, - ); - -Map _$$GithubAssetImplToJson(_$GithubAssetImpl instance) => - { - 'url': instance.url, - 'id': instance.id, - 'node_id': instance.nodeId, - 'name': instance.name, - 'label': instance.label, - 'uploader': instance.uploader, - 'content_type': instance.contentType, - 'state': instance.state, - 'size': instance.size, - 'download_count': instance.downloadCount, - 'created_at': instance.createdAt.toIso8601String(), - 'updated_at': instance.updatedAt.toIso8601String(), - 'browser_download_url': instance.browserDownloadUrl, - }; - -_$GithubUploaderImpl _$$GithubUploaderImplFromJson(Map json) => - _$GithubUploaderImpl( - login: json['login'] as String, - id: (json['id'] as num).toInt(), - nodeId: json['node_id'] as String, - avatarUrl: json['avatar_url'] as String, - gravatarId: json['gravatar_id'] as String, - url: json['url'] as String, - htmlUrl: json['html_url'] as String, - followersUrl: json['followers_url'] as String, - followingUrl: json['following_url'] as String, - gistsUrl: json['gists_url'] as String, - starredUrl: json['starred_url'] as String, - subscriptionsUrl: json['subscriptions_url'] as String, - organizationsUrl: json['organizations_url'] as String, - reposUrl: json['repos_url'] as String, - eventsUrl: json['events_url'] as String, - receivedEventsUrl: json['received_events_url'] as String, - type: json['type'] as String, - siteAdmin: json['site_admin'] as bool, - ); - -Map _$$GithubUploaderImplToJson( - _$GithubUploaderImpl instance) => - { - 'login': instance.login, - 'id': instance.id, - 'node_id': instance.nodeId, - 'avatar_url': instance.avatarUrl, - 'gravatar_id': instance.gravatarId, - 'url': instance.url, - 'html_url': instance.htmlUrl, - 'followers_url': instance.followersUrl, - 'following_url': instance.followingUrl, - 'gists_url': instance.gistsUrl, - 'starred_url': instance.starredUrl, - 'subscriptions_url': instance.subscriptionsUrl, - 'organizations_url': instance.organizationsUrl, - 'repos_url': instance.reposUrl, - 'events_url': instance.eventsUrl, - 'received_events_url': instance.receivedEventsUrl, - 'type': instance.type, - 'site_admin': instance.siteAdmin, - }; diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 92643f6b..f291a826 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -1,42 +1,246 @@ { "@@locale": "cs", + "about": "O aplikaci", + "aboutCheckForUpdates": "Zkontrolovat aktualizace", + "aboutCopyRight": "© 2023 - {time} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3", + "@aboutCopyRight": { + "placeholders": { + "time": { + "type": "DateTime", + "format": "y" + } + } + }, + "aboutLatestVersion": "Aktuálně jste na nejnovější verzi aplikace 👍", + "aboutSourceCode": "Zdrojový kód", + "aboutVersionSubtitle": "{arg, select, true{Debug} other{Stable}} {version}", + "@aboutVersionSubtitle": { + "description": "aboutVersionSubtitle", + "placeholders": { + "arg": { + "type": "String", + "example": "true" + }, + "version": { + "type": "String" + } + } + }, + "account": "Účet", "accountStatus": "Stav účtu", "accountcreationTime": "Čas vytvoření účtu: {date}", + "addAccount": "Přidat účet", + "allergens": "Alergeny", + "allowPermission": "Udělit oprávnění", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", "appName": "Autojídelna", + "burzaAlertDialogContent": "Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.", "buttonPushed": "Tlačítko jste stiskli tolikrát:", + "cancel": "Zrušit", + "category": "Kategorie", + "changeAccount": "Změnit účet", "connectedToANetwork": "Připojeno k síti", "connectedToTheInternet": "Připojeno k internetu", + "convenience": "Pohodlí", "counting": "Počítání", "crashlytics": "Crashlytics", "crashlyticsPage": "Stránka Crashlytics", "crashlyticsTestCrash": "Testovací pád Crashlytics yohooo!", "createAccount": "Vytvořit účet s e-mailem a heslem", - "debug": " - debug", + "credit": "Kredit: {ammount} Kč", + "@credit": { + "placeholders": { + "ammount": { + "type": "double", + "format": "decimalPattern" + } + } + }, + "currency": "Kč", + "darkThemeMode": "Tmavý", + "dataCollectionAgreement": "Používáním aplikace souhlasíte se zasíláním anonymních dat. ", + "dateFormat": "Formát dat", + "debug": "Debug", "deleteAccount": "Smazat účet", "deleteAccountConfirm": "Smazat účet", "deleteAccountDialog": "Opravdu chcete smazat svůj účet?", "demoPageTitle": "Demo stránka", "disconnectedFromANetwork": "Odpojeno od sítě", "disconnectedFromTheInternet": "Odpojeno od internetu", + "dochazejiciKreditChannelDescription": "Oznámení o tom, zda vám dochází kredit týden dopředu pro {username}", + "@dochazejiciKreditChannelDescription": { + "placeholders": { + "username": { + "type": "String" + } + } + }, + "dochazejiciKreditChannelName": "Docházející kredit", + "dontShowAgain": "Příště nezobrazovat", + "drinks": "Pití", "email": "E-mail", "enterAValidEmailAddress": "Zadejte platnou e-mailovou adresu", "enterYourEmail": "Zadejte svůj e-mail", "enterYourPassword": "Zadejte své heslo", + "errorsBadConnection": "Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později", + "errorsBadLogin": "Nesprávné přihlašovací údaje", + "errorsBadPassword": "Špatné heslo nebo uživatelské jméno", + "errorsBadUrl": "Nesprávné Url", + "errorsChangelog": "Nepodařilo se získat změny :/", + "errorsChybaPriDavaniNaBurzu": "Nastala chyba při dávání jídla na burzu", + "errorsChybaPriRuseni": "Nastala chyba při rušení objednávky", + "errorsDownloadingApp": "Aktualizace aplikace selhala", + "errorsDownloadingAppDetail": "Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.", + "errorsJidloNeniNaBurze": "Jídlo není na burze", + "errorsLoad": "Selhalo načítání jídelníčku", + "errorsLoadingData": "Nastala chyba při načítání dat", + "errorsLoginFailed": "Přihlášení se nezdařilo", + "errorsLoginFailedDetail": "Při přihlašování došlo k chybě: {error}", + "@errorsLoginFailedDetail": { + "placeholders": { + "error": { + "type": "String" + } + } + }, + "errorsNelzeObjednat": "Oběd nelze objednat", + "errorsNelzeObjednatKredit": "Oběd nelze objednat - Nedostatečný kredit.", + "errorsNoInternet": "Nemáte připojení k internetu", + "errorsObedNelzeZrusit": "Oběd nelze zrušit. Platnost objednávky vypršela.", + "errorsObjednavaniJidla": "Nastala chyba při objednávání jídla", + "errorsUndefined": "Nastala Chyba", + "errorsUpdatingData": "Nastala chyba při aktualizaci dat", + "gettingDataNotifications": "Získávám data pro oznámení", "goBack": "Jít zpět", "goToSettings": "Jít na nastavení", + "jidloChannelDescription": "Oznámení každý den o tom jaké je dnes jídlo pro {username}", + "@jidloChannelDescription": { + "placeholders": { + "username": { + "type": "String" + } + } + }, + "jidloChannelName": "Dnešní jídlo", "language": "Jazyk", "languageCzech": "Čeština", "languageEnglish": "Angličtina", "languageName": "Čeština", "lastSignInTime": "Čas posledního přihlášení: {date}", + "licenses": "Licence", + "lightThemeMode": "Světlý", + "listUi": "List UI", "localization": "Lokalizace", + "location": "Výdejna", + "locationsUnknown": "Neznámá výdejna", "loggedIn": "Přihlášen: {bool}", "login": "přihlásit se", + "loginButton": "Přihlásit se", + "loginPasswordFieldHint": "Zadejte prosím své heslo", + "loginPasswordFieldLabel": "Heslo", + "loginUrlFieldHint": "Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz", + "loginUrlFieldLabel": "Url stránky icanteen - např. jidelna.trebesin.cz", + "loginUserFieldHint": "Zadejte prosím své uživatelské jméno", + "loginUserFieldLabel": "Uživatelské jméno", + "logoutConfirm": "Odhlásit se", + "logoutUSure": "Opravdu se chcete odhlásit?", + "mainCourse": "Hlavní chod", + "menu": "Jídelníček", + "more": "Více", + "moreInfo": "Více informací.", + "name": "Jméno", + "nedostatekKreditu": "Nedostatek kreditu", + "neededPermission": "Potřebné oprávnění", + "neededPermissionDescription_1": "Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.", + "neededPermissionDescription_2": "Ta může vypadat takto:", + "neededPermissionDescription_3": "Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.", + "nelzeObjednat": "Nelze objednat", + "nelzeZrusit": "Nelze zrušit", + "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", + "notificationDochaziVamKredit": "Dochází vám kredit!", + "notificationKreditPro": "Kredit pro {first} {last}: {ammount} Kč", + "@notificationKreditPro": { + "placeholders": { + "first": { + "type": "String" + }, + "last": { + "type": "String" + }, + "ammount": { + "type": "String" + } + } + }, + "notificationObjednejteSi": "Objednejte si na příští týden", + "notificationObjednejteSiDetail": "Uživatel {fist} {last} si stále ještě neobjenal na příští týden", + "@notificationObjednejteSiDetail": { + "placeholders": { + "first": { + "type": "String" + }, + "last": { + "type": "String" + } + } + }, + "notificationZtlumit": "Ztlumit na týden", + "notifications": "Oznámení", + "notificationsFor": "Oznámení pro {username}", + "@notificationsFor": { + "placeholders": { + "username": { + "type": "String" + } + } + }, + "objednanoChannelDescription": "Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro {username}", + "@objednanoChannelDescription": { + "placeholders": { + "username": { + "type": "String" + } + } + }, + "objednanoChannelName": "Objednáno?", + "objednat": "Objednat", + "objednatAction": "Objednat náhodně", + "objednatZBurzy": "Objednat z burzy", + "odebratZBurzy": "Odebrat z burzy", + "ok": "OK", + "orders": "Objednávky", + "ordersWithAutojidelna": "Objednávky s Autojídelnou: {ammount}", + "@ordersWithAutojidelna": { + "placeholders": { + "ammount": { + "type": "int" + } + } + }, + "other": "Ostatní", + "otherDescription": "Ostatní oznámení, např. chybové hlášky", "password": "Heslo", "passwordMustBeAtLeast6CharactersLong": "Heslo musí mít alespoň 6 znaků", "patch": "patch", + "paymentAccountNumber": "Číslo účtu", + "paymentInfo": "Platební Údaje", + "personalInfo": "Osobní Údaje", + "pickLocation": "Vyberte výdejnu ", + "popupChangelogNotAvailable": "Changelog není k dispozici", + "popupNewUpdateInfo": "Nová verze přináší: ", + "popupNewVersionAvailable": "Nová verze aplikace - {version}", + "@popupNewVersionAvailable": { + "placeholders": { + "version": { + "type": "String" + } + } + }, + "popupNotNow": "Teď ne", + "popupShowOnGithub": "Zobrazit na Githubu", + "popupUpdate": "Aktualizovat", + "privacyPolicy": "Zásady ochrany osobních údajů", "providerId": "ID poskytovatele: {id}", "remoteConfig": "Vzdálená konfigurace", "requestNotificationPermission": "Požádat o povolení notifikací", @@ -61,16 +265,90 @@ "secret": "tajemství", "secretPage": "Tajná stránka", "settings": "Nastavení", + "settingsAmoled": "AMOLED mód", + "settingsAmoledSub": "Přidej se k temné straně síly!", + "settingsAnotherOptions": "Další možnosti v nastavení systému...", + "settingsAppearence": "Vzhled", + "settingsCalendarBigMarkers": "Velké ukazatele v kalendáři", + "settingsDataCollection": "Shromažďování údajů", + "settingsDataCollectionDescription_1": "Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve ", + "settingsDataCollectionDescription_2": "Zdrojovém kódu", + "settingsDataCollectionDescription_3": " nebo v ", + "settingsDataCollectionDescription_4": "Zásadách ochrany osobních údajů.", + "settingsDebugForceNotifications": "Force send notifications", + "settingsDebugNotifications": "Send Notifications", + "settingsDebugOptions": "Debug Options", + "settingsDisplay": "Zobrazení", + "settingsNemateObjednano": "Nemáte objednáno na příští týden", + "settingsNotificationFor": "Oznámení pro {username}", + "@settingsNotificationFor": { + "placeholders": { + "username": { + "type": "String" + } + } + }, + "settingsNotificationTime": "Čas oznámení: ", + "settingsRelativeTimestamps": "Relativní časové značky", + "settingsRelativeTimestampsSub": "„Dnes“ místo „{date}“", + "@settingsRelativeTimestampsSub": { + "placeholders": { + "date": { + "type": "String" + } + } + }, + "settingsSkipWeekends": "Přeskakovat víkendy", + "settingsStopDataCollection": "Zastavit sledování analytických služeb", + "settingsTheme": "Schéma", + "settingsTitleCredit": "Nízký credit", + "settingsTitleTodaysFood": "Dnešní jídlo", + "shareApp": "Sdílet aplikaci", + "shareDescription": "Autojídelna (aplikace na objednávání jídla)", "showLocale": "Zobrazit lokalizaci", + "sideDish": "Přílohy", "signInAnonymously": "Přihlásit se anonymně", "signInWithApple": "Přihlásit se pomocí Apple", "signInWithEmailAndPassword": "Přihlásit se pomocí e-mailu a hesla", "signInWithGoogle": "Přihlásit se pomocí Google", "signOut": "Odhlásit se", + "soup": "Polévka", + "specificSymbol": "Specifický symbol", + "stable": "Stable", + "statistics": "Statistiky", + "switchAccountPanelTitle": "Účty", + "systemThemeMode": "Systém", + "tabletUi": "Tablet UI", + "tabletUiOptions": "{arg, select, other{error} auto{Automaticky} always{Vždy} landscape{Na šířku} never{Nikdy}}", + "@tabletUiOptions": { + "description": "tabletUiOptions", + "placeholders": { + "arg": { + "type": "String", + "example": "always" + } + } + }, + "toastExit": "Zmáčkněte tlačítko zpět pro ukončení aplikace", + "tryAgain": "Zkusit znovu", "typeCrash": "Napište \"crash\" pro pád aplikace", + "updateSnackbarDownloaded": "Aktualizace byla stažena, instalování", + "updateSnackbarDownloading": "Nová Aktualizace se stahuje - {value}%", + "@updateSnackbarDownloading": { + "placeholders": { + "value": { + "type": "int" + } + } + }, + "updateSnackbarError": "Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu", + "updateSnackbarWaiting": "Aktualizace - Čeká se na oprávnění", "userDisplayName": "Zobrazované jméno uživatele: {name}", "userEmail": "E-mail uživatele: {email}", "userEmailVerified": "E-mail uživatele ověřen: {bool}", "userId": "ID uživatele: {id}", - "verifyEmail": "Ověřit e-mail" + "variableSymbol": "Variabilní symbol", + "verifyEmail": "Ověřit e-mail", + "version": "Verze", + "vlozitNaBurzu": "Vložit na burzu" } \ No newline at end of file diff --git a/lib/src/lang/app_en.arb b/lib/src/lang/app_en.arb deleted file mode 100644 index 820cc044..00000000 --- a/lib/src/lang/app_en.arb +++ /dev/null @@ -1,148 +0,0 @@ -{ - "@@locale": "en", - "accountStatus": "Account Status", - "accountcreationTime": "Account Creation Time: {date}", - "@accountcreationTime": { - "placeholders": { - "date": { - "type": "DateTime", - "format": "yMMMMEEEEd" - } - } - }, - "appDescription": "Application for ordering from the Icanteen system. The aim of this application is to simplify, speed up (or even automate) the ordering of lunches.", - "appName": "Autojídelna", - "buttonPushed": "You have pushed the button this many times:", - "connectedToANetwork": "Connected to a network", - "connectedToTheInternet": "Connected to the internet", - "counting": "Counting", - "crashlytics": "Crashlytics", - "crashlyticsPage": "Crashlytics Page", - "crashlyticsTestCrash": "Crashlytics test crash!", - "createAccount": "Create account with email and password", - "debug": " - debug", - "deleteAccount": "Delete account", - "deleteAccountConfirm": "Delete account", - "deleteAccountDialog": "Are you sure you want to delete your account?", - "demoPageTitle": "Demo Page", - "disconnectedFromANetwork": "Disconnected from a network", - "disconnectedFromTheInternet": "Disconnected from the internet", - "email": "Email", - "enterAValidEmailAddress": "Please enter a valid email address", - "enterYourEmail": "Please enter your email", - "enterYourPassword": "Please enter your password", - "goBack": "Go back", - "goToSettings": "Go to settings", - "language": "Language", - "languageCzech": "Czech", - "languageEnglish": "English", - "languageName": "English", - "lastSignInTime": "Last Sign In Time: {date}", - "@lastSignInTime": { - "placeholders": { - "date": { - "type": "DateTime", - "format": "yMMMMEEEEd" - } - } - }, - "localization": "Localizations", - "loggedIn": "Logged in: {bool}", - "@loggedIn": { - "placeholders": { - "bool": { - "type": "String", - "example": "false" - } - } - }, - "login": "Login", - "noThankYou": "No, thank you", - "password": "Password", - "passwordMustBeAtLeast6CharactersLong": "Password must be at least 6 characters long", - "patch": "patch", - "providerId": "Provider ID: {id}", - "@providerId": { - "placeholders": { - "id": { - "type": "String", - "example": "google.com" - } - } - }, - "remoteConfig": "Remote Config", - "requestNotificationPermission": "Request Notification Permission", - "resetPassword": "Reset password", - "routingGoToDetailDetail": "Go to Detail Detail", - "routingGoToDetailPage": "Go to Detail Page", - "routingGoToParamDetailPage": "Go to Param Detail Page", - "routingParamDetailPageDetail": "Routing Param Detail Page", - "routingParamDetailPageDetail1": "This is a routing param detail page.", - "routingParamDetailPageDetail2": "It is used to test routing with parameters.", - "routingParamDetailPageDetail3": "Film ID: {filmId}", - "@routingParamDetailPageDetail3": { - "placeholders": { - "filmId": { - "type": "String", - "example": "100" - } - } - }, - "routingParamFilmId": "Path param Film ID", - "routingParamPage": "Routing Param Page", - "routingParamPageDetail": "This is a routing param page.", - "routingParamPageDetail2": "It is used to test routing with parameters.", - "routingParamQueryFilmId": "Query param Film ID", - "routingTestDetailDetail": "Routing Test Detail Detail", - "routingTestDetailDetailText": "This is a routing test detail detail page.", - "routingTestPage": "Settings", - "routingTestPageDetail": "This is a routing test page.", - "routingTestPageDetail1": "It is used to test routing.", - "secret": "secret", - "secretPage": "Secret Page", - "settings": "Settings", - "showLocale": "Show locale", - "signInAnonymously": "Sign in Anonymously", - "signInWithApple": "Sign in with Apple", - "signInWithEmailAndPassword": "Sign in with email and password", - "signInWithGoogle": "Sign in with Google", - "signOut": "Sign out", - "typeCrash": "Type \"crash\" to crash the app", - "userDisplayName": "User Display Name: {name}", - "@userDisplayName": { - "placeholders": { - "name": { - "type": "String", - "example": "ALena Novotna" - } - } - }, - "userEmail": "User Email: {email}", - "@userEmail": { - "placeholders": { - "email": { - "type": "String", - "example": "this@example.com" - } - } - }, - "userEmailVerified": "User Email Verified: {bool}", - "@userEmailVerified": { - "placeholders": { - "bool": { - "type": "String", - "example": "false" - } - } - }, - "userId": "User ID: {id}", - "@userId": { - "placeholders": { - "id": { - "type": "String", - "example": "MNJNS3q134213rdasfn" - } - } - }, - "verifyEmail": "Verify email" -} \ No newline at end of file diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 5e165c7a..cd0bcd38 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -6,7 +6,6 @@ import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:intl/intl.dart' as intl; import 'texts_cs.dart'; -import 'texts_en.dart'; /// Callers can lookup localized strings with an instance of Texts /// returned by `Texts.of(context)`. @@ -90,448 +89,1333 @@ abstract class Texts { ]; /// A list of this localizations delegate's supported locales. - static const List supportedLocales = [ - Locale('cs'), - Locale('en') - ]; + static const List supportedLocales = [Locale('cs')]; + + /// No description provided for @about. + /// + /// In cs, this message translates to: + /// **'O aplikaci'** + String get about; + + /// No description provided for @aboutCheckForUpdates. + /// + /// In cs, this message translates to: + /// **'Zkontrolovat aktualizace'** + String get aboutCheckForUpdates; + + /// No description provided for @aboutCopyRight. + /// + /// In cs, this message translates to: + /// **'© 2023 - {time} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'** + String aboutCopyRight(DateTime time); + + /// No description provided for @aboutLatestVersion. + /// + /// In cs, this message translates to: + /// **'Aktuálně jste na nejnovější verzi aplikace 👍'** + String get aboutLatestVersion; + + /// No description provided for @aboutSourceCode. + /// + /// In cs, this message translates to: + /// **'Zdrojový kód'** + String get aboutSourceCode; + + /// aboutVersionSubtitle + /// + /// In cs, this message translates to: + /// **'{arg, select, true{Debug} other{Stable}} {version}'** + String aboutVersionSubtitle(String arg, String version); + + /// No description provided for @account. + /// + /// In cs, this message translates to: + /// **'Účet'** + String get account; /// No description provided for @accountStatus. /// - /// In en, this message translates to: - /// **'Account Status'** + /// In cs, this message translates to: + /// **'Stav účtu'** String get accountStatus; /// No description provided for @accountcreationTime. /// - /// In en, this message translates to: - /// **'Account Creation Time: {date}'** - String accountcreationTime(DateTime date); + /// In cs, this message translates to: + /// **'Čas vytvoření účtu: {date}'** + String accountcreationTime(Object date); + + /// No description provided for @addAccount. + /// + /// In cs, this message translates to: + /// **'Přidat účet'** + String get addAccount; + + /// No description provided for @allergens. + /// + /// In cs, this message translates to: + /// **'Alergeny'** + String get allergens; + + /// No description provided for @allowPermission. + /// + /// In cs, this message translates to: + /// **'Udělit oprávnění'** + String get allowPermission; /// No description provided for @appDescription. /// - /// In en, this message translates to: - /// **'Application for ordering from the Icanteen system. The aim of this application is to simplify, speed up (or even automate) the ordering of lunches.'** + /// In cs, this message translates to: + /// **'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'** String get appDescription; /// No description provided for @appName. /// - /// In en, this message translates to: + /// In cs, this message translates to: /// **'Autojídelna'** String get appName; + /// No description provided for @burzaAlertDialogContent. + /// + /// In cs, this message translates to: + /// **'Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.'** + String get burzaAlertDialogContent; + /// No description provided for @buttonPushed. /// - /// In en, this message translates to: - /// **'You have pushed the button this many times:'** + /// In cs, this message translates to: + /// **'Tlačítko jste stiskli tolikrát:'** String get buttonPushed; + /// No description provided for @cancel. + /// + /// In cs, this message translates to: + /// **'Zrušit'** + String get cancel; + + /// No description provided for @category. + /// + /// In cs, this message translates to: + /// **'Kategorie'** + String get category; + + /// No description provided for @changeAccount. + /// + /// In cs, this message translates to: + /// **'Změnit účet'** + String get changeAccount; + /// No description provided for @connectedToANetwork. /// - /// In en, this message translates to: - /// **'Connected to a network'** + /// In cs, this message translates to: + /// **'Připojeno k síti'** String get connectedToANetwork; /// No description provided for @connectedToTheInternet. /// - /// In en, this message translates to: - /// **'Connected to the internet'** + /// In cs, this message translates to: + /// **'Připojeno k internetu'** String get connectedToTheInternet; + /// No description provided for @convenience. + /// + /// In cs, this message translates to: + /// **'Pohodlí'** + String get convenience; + /// No description provided for @counting. /// - /// In en, this message translates to: - /// **'Counting'** + /// In cs, this message translates to: + /// **'Počítání'** String get counting; /// No description provided for @crashlytics. /// - /// In en, this message translates to: + /// In cs, this message translates to: /// **'Crashlytics'** String get crashlytics; /// No description provided for @crashlyticsPage. /// - /// In en, this message translates to: - /// **'Crashlytics Page'** + /// In cs, this message translates to: + /// **'Stránka Crashlytics'** String get crashlyticsPage; /// No description provided for @crashlyticsTestCrash. /// - /// In en, this message translates to: - /// **'Crashlytics test crash!'** + /// In cs, this message translates to: + /// **'Testovací pád Crashlytics yohooo!'** String get crashlyticsTestCrash; /// No description provided for @createAccount. /// - /// In en, this message translates to: - /// **'Create account with email and password'** + /// In cs, this message translates to: + /// **'Vytvořit účet s e-mailem a heslem'** String get createAccount; + /// No description provided for @credit. + /// + /// In cs, this message translates to: + /// **'Kredit: {ammount} Kč'** + String credit(double ammount); + + /// No description provided for @currency. + /// + /// In cs, this message translates to: + /// **'Kč'** + String get currency; + + /// No description provided for @darkThemeMode. + /// + /// In cs, this message translates to: + /// **'Tmavý'** + String get darkThemeMode; + + /// No description provided for @dataCollectionAgreement. + /// + /// In cs, this message translates to: + /// **'Používáním aplikace souhlasíte se zasíláním anonymních dat. '** + String get dataCollectionAgreement; + + /// No description provided for @dateFormat. + /// + /// In cs, this message translates to: + /// **'Formát dat'** + String get dateFormat; + /// No description provided for @debug. /// - /// In en, this message translates to: - /// **' - debug'** + /// In cs, this message translates to: + /// **'Debug'** String get debug; /// No description provided for @deleteAccount. /// - /// In en, this message translates to: - /// **'Delete account'** + /// In cs, this message translates to: + /// **'Smazat účet'** String get deleteAccount; /// No description provided for @deleteAccountConfirm. /// - /// In en, this message translates to: - /// **'Delete account'** + /// In cs, this message translates to: + /// **'Smazat účet'** String get deleteAccountConfirm; /// No description provided for @deleteAccountDialog. /// - /// In en, this message translates to: - /// **'Are you sure you want to delete your account?'** + /// In cs, this message translates to: + /// **'Opravdu chcete smazat svůj účet?'** String get deleteAccountDialog; /// No description provided for @demoPageTitle. /// - /// In en, this message translates to: - /// **'Demo Page'** + /// In cs, this message translates to: + /// **'Demo stránka'** String get demoPageTitle; /// No description provided for @disconnectedFromANetwork. /// - /// In en, this message translates to: - /// **'Disconnected from a network'** + /// In cs, this message translates to: + /// **'Odpojeno od sítě'** String get disconnectedFromANetwork; /// No description provided for @disconnectedFromTheInternet. /// - /// In en, this message translates to: - /// **'Disconnected from the internet'** + /// In cs, this message translates to: + /// **'Odpojeno od internetu'** String get disconnectedFromTheInternet; + /// No description provided for @dochazejiciKreditChannelDescription. + /// + /// In cs, this message translates to: + /// **'Oznámení o tom, zda vám dochází kredit týden dopředu pro {username}'** + String dochazejiciKreditChannelDescription(String username); + + /// No description provided for @dochazejiciKreditChannelName. + /// + /// In cs, this message translates to: + /// **'Docházející kredit'** + String get dochazejiciKreditChannelName; + + /// No description provided for @dontShowAgain. + /// + /// In cs, this message translates to: + /// **'Příště nezobrazovat'** + String get dontShowAgain; + + /// No description provided for @drinks. + /// + /// In cs, this message translates to: + /// **'Pití'** + String get drinks; + /// No description provided for @email. /// - /// In en, this message translates to: - /// **'Email'** + /// In cs, this message translates to: + /// **'E-mail'** String get email; /// No description provided for @enterAValidEmailAddress. /// - /// In en, this message translates to: - /// **'Please enter a valid email address'** + /// In cs, this message translates to: + /// **'Zadejte platnou e-mailovou adresu'** String get enterAValidEmailAddress; /// No description provided for @enterYourEmail. /// - /// In en, this message translates to: - /// **'Please enter your email'** + /// In cs, this message translates to: + /// **'Zadejte svůj e-mail'** String get enterYourEmail; /// No description provided for @enterYourPassword. /// - /// In en, this message translates to: - /// **'Please enter your password'** + /// In cs, this message translates to: + /// **'Zadejte své heslo'** String get enterYourPassword; + /// No description provided for @errorsBadConnection. + /// + /// In cs, this message translates to: + /// **'Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později'** + String get errorsBadConnection; + + /// No description provided for @errorsBadLogin. + /// + /// In cs, this message translates to: + /// **'Nesprávné přihlašovací údaje'** + String get errorsBadLogin; + + /// No description provided for @errorsBadPassword. + /// + /// In cs, this message translates to: + /// **'Špatné heslo nebo uživatelské jméno'** + String get errorsBadPassword; + + /// No description provided for @errorsBadUrl. + /// + /// In cs, this message translates to: + /// **'Nesprávné Url'** + String get errorsBadUrl; + + /// No description provided for @errorsChangelog. + /// + /// In cs, this message translates to: + /// **'Nepodařilo se získat změny :/'** + String get errorsChangelog; + + /// No description provided for @errorsChybaPriDavaniNaBurzu. + /// + /// In cs, this message translates to: + /// **'Nastala chyba při dávání jídla na burzu'** + String get errorsChybaPriDavaniNaBurzu; + + /// No description provided for @errorsChybaPriRuseni. + /// + /// In cs, this message translates to: + /// **'Nastala chyba při rušení objednávky'** + String get errorsChybaPriRuseni; + + /// No description provided for @errorsDownloadingApp. + /// + /// In cs, this message translates to: + /// **'Aktualizace aplikace selhala'** + String get errorsDownloadingApp; + + /// No description provided for @errorsDownloadingAppDetail. + /// + /// In cs, this message translates to: + /// **'Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.'** + String get errorsDownloadingAppDetail; + + /// No description provided for @errorsJidloNeniNaBurze. + /// + /// In cs, this message translates to: + /// **'Jídlo není na burze'** + String get errorsJidloNeniNaBurze; + + /// No description provided for @errorsLoad. + /// + /// In cs, this message translates to: + /// **'Selhalo načítání jídelníčku'** + String get errorsLoad; + + /// No description provided for @errorsLoadingData. + /// + /// In cs, this message translates to: + /// **'Nastala chyba při načítání dat'** + String get errorsLoadingData; + + /// No description provided for @errorsLoginFailed. + /// + /// In cs, this message translates to: + /// **'Přihlášení se nezdařilo'** + String get errorsLoginFailed; + + /// No description provided for @errorsLoginFailedDetail. + /// + /// In cs, this message translates to: + /// **'Při přihlašování došlo k chybě: {error}'** + String errorsLoginFailedDetail(String error); + + /// No description provided for @errorsNelzeObjednat. + /// + /// In cs, this message translates to: + /// **'Oběd nelze objednat'** + String get errorsNelzeObjednat; + + /// No description provided for @errorsNelzeObjednatKredit. + /// + /// In cs, this message translates to: + /// **'Oběd nelze objednat - Nedostatečný kredit.'** + String get errorsNelzeObjednatKredit; + + /// No description provided for @errorsNoInternet. + /// + /// In cs, this message translates to: + /// **'Nemáte připojení k internetu'** + String get errorsNoInternet; + + /// No description provided for @errorsObedNelzeZrusit. + /// + /// In cs, this message translates to: + /// **'Oběd nelze zrušit. Platnost objednávky vypršela.'** + String get errorsObedNelzeZrusit; + + /// No description provided for @errorsObjednavaniJidla. + /// + /// In cs, this message translates to: + /// **'Nastala chyba při objednávání jídla'** + String get errorsObjednavaniJidla; + + /// No description provided for @errorsUndefined. + /// + /// In cs, this message translates to: + /// **'Nastala Chyba'** + String get errorsUndefined; + + /// No description provided for @errorsUpdatingData. + /// + /// In cs, this message translates to: + /// **'Nastala chyba při aktualizaci dat'** + String get errorsUpdatingData; + + /// No description provided for @gettingDataNotifications. + /// + /// In cs, this message translates to: + /// **'Získávám data pro oznámení'** + String get gettingDataNotifications; + /// No description provided for @goBack. /// - /// In en, this message translates to: - /// **'Go back'** + /// In cs, this message translates to: + /// **'Jít zpět'** String get goBack; /// No description provided for @goToSettings. /// - /// In en, this message translates to: - /// **'Go to settings'** + /// In cs, this message translates to: + /// **'Jít na nastavení'** String get goToSettings; + /// No description provided for @jidloChannelDescription. + /// + /// In cs, this message translates to: + /// **'Oznámení každý den o tom jaké je dnes jídlo pro {username}'** + String jidloChannelDescription(String username); + + /// No description provided for @jidloChannelName. + /// + /// In cs, this message translates to: + /// **'Dnešní jídlo'** + String get jidloChannelName; + /// No description provided for @language. /// - /// In en, this message translates to: - /// **'Language'** + /// In cs, this message translates to: + /// **'Jazyk'** String get language; /// No description provided for @languageCzech. /// - /// In en, this message translates to: - /// **'Czech'** + /// In cs, this message translates to: + /// **'Čeština'** String get languageCzech; /// No description provided for @languageEnglish. /// - /// In en, this message translates to: - /// **'English'** + /// In cs, this message translates to: + /// **'Angličtina'** String get languageEnglish; /// No description provided for @languageName. /// - /// In en, this message translates to: - /// **'English'** + /// In cs, this message translates to: + /// **'Čeština'** String get languageName; /// No description provided for @lastSignInTime. /// - /// In en, this message translates to: - /// **'Last Sign In Time: {date}'** - String lastSignInTime(DateTime date); + /// In cs, this message translates to: + /// **'Čas posledního přihlášení: {date}'** + String lastSignInTime(Object date); + + /// No description provided for @licenses. + /// + /// In cs, this message translates to: + /// **'Licence'** + String get licenses; + + /// No description provided for @lightThemeMode. + /// + /// In cs, this message translates to: + /// **'Světlý'** + String get lightThemeMode; + + /// No description provided for @listUi. + /// + /// In cs, this message translates to: + /// **'List UI'** + String get listUi; /// No description provided for @localization. /// - /// In en, this message translates to: - /// **'Localizations'** + /// In cs, this message translates to: + /// **'Lokalizace'** String get localization; + /// No description provided for @location. + /// + /// In cs, this message translates to: + /// **'Výdejna'** + String get location; + + /// No description provided for @locationsUnknown. + /// + /// In cs, this message translates to: + /// **'Neznámá výdejna'** + String get locationsUnknown; + /// No description provided for @loggedIn. /// - /// In en, this message translates to: - /// **'Logged in: {bool}'** - String loggedIn(String bool); + /// In cs, this message translates to: + /// **'Přihlášen: {bool}'** + String loggedIn(Object bool); /// No description provided for @login. /// - /// In en, this message translates to: - /// **'Login'** + /// In cs, this message translates to: + /// **'přihlásit se'** String get login; + /// No description provided for @loginButton. + /// + /// In cs, this message translates to: + /// **'Přihlásit se'** + String get loginButton; + + /// No description provided for @loginPasswordFieldHint. + /// + /// In cs, this message translates to: + /// **'Zadejte prosím své heslo'** + String get loginPasswordFieldHint; + + /// No description provided for @loginPasswordFieldLabel. + /// + /// In cs, this message translates to: + /// **'Heslo'** + String get loginPasswordFieldLabel; + + /// No description provided for @loginUrlFieldHint. + /// + /// In cs, this message translates to: + /// **'Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz'** + String get loginUrlFieldHint; + + /// No description provided for @loginUrlFieldLabel. + /// + /// In cs, this message translates to: + /// **'Url stránky icanteen - např. jidelna.trebesin.cz'** + String get loginUrlFieldLabel; + + /// No description provided for @loginUserFieldHint. + /// + /// In cs, this message translates to: + /// **'Zadejte prosím své uživatelské jméno'** + String get loginUserFieldHint; + + /// No description provided for @loginUserFieldLabel. + /// + /// In cs, this message translates to: + /// **'Uživatelské jméno'** + String get loginUserFieldLabel; + + /// No description provided for @logoutConfirm. + /// + /// In cs, this message translates to: + /// **'Odhlásit se'** + String get logoutConfirm; + + /// No description provided for @logoutUSure. + /// + /// In cs, this message translates to: + /// **'Opravdu se chcete odhlásit?'** + String get logoutUSure; + + /// No description provided for @mainCourse. + /// + /// In cs, this message translates to: + /// **'Hlavní chod'** + String get mainCourse; + + /// No description provided for @menu. + /// + /// In cs, this message translates to: + /// **'Jídelníček'** + String get menu; + + /// No description provided for @more. + /// + /// In cs, this message translates to: + /// **'Více'** + String get more; + + /// No description provided for @moreInfo. + /// + /// In cs, this message translates to: + /// **'Více informací.'** + String get moreInfo; + + /// No description provided for @name. + /// + /// In cs, this message translates to: + /// **'Jméno'** + String get name; + + /// No description provided for @nedostatekKreditu. + /// + /// In cs, this message translates to: + /// **'Nedostatek kreditu'** + String get nedostatekKreditu; + + /// No description provided for @neededPermission. + /// + /// In cs, this message translates to: + /// **'Potřebné oprávnění'** + String get neededPermission; + + /// No description provided for @neededPermissionDescription_1. + /// + /// In cs, this message translates to: + /// **'Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.'** + String get neededPermissionDescription_1; + + /// No description provided for @neededPermissionDescription_2. + /// + /// In cs, this message translates to: + /// **'Ta může vypadat takto:'** + String get neededPermissionDescription_2; + + /// No description provided for @neededPermissionDescription_3. + /// + /// In cs, this message translates to: + /// **'Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.'** + String get neededPermissionDescription_3; + + /// No description provided for @nelzeObjednat. + /// + /// In cs, this message translates to: + /// **'Nelze objednat'** + String get nelzeObjednat; + + /// No description provided for @nelzeZrusit. + /// + /// In cs, this message translates to: + /// **'Nelze zrušit'** + String get nelzeZrusit; + + /// No description provided for @noFood. + /// + /// In cs, this message translates to: + /// **'Žádná jídla pro tento den.'** + String get noFood; + /// No description provided for @noThankYou. /// - /// In en, this message translates to: - /// **'No, thank you'** + /// In cs, this message translates to: + /// **'Ne, děkuji'** String get noThankYou; + /// No description provided for @notificationDochaziVamKredit. + /// + /// In cs, this message translates to: + /// **'Dochází vám kredit!'** + String get notificationDochaziVamKredit; + + /// No description provided for @notificationKreditPro. + /// + /// In cs, this message translates to: + /// **'Kredit pro {first} {last}: {ammount} Kč'** + String notificationKreditPro(String first, String last, String ammount); + + /// No description provided for @notificationObjednejteSi. + /// + /// In cs, this message translates to: + /// **'Objednejte si na příští týden'** + String get notificationObjednejteSi; + + /// No description provided for @notificationObjednejteSiDetail. + /// + /// In cs, this message translates to: + /// **'Uživatel {fist} {last} si stále ještě neobjenal na příští týden'** + String notificationObjednejteSiDetail(String first, String last, Object fist); + + /// No description provided for @notificationZtlumit. + /// + /// In cs, this message translates to: + /// **'Ztlumit na týden'** + String get notificationZtlumit; + + /// No description provided for @notifications. + /// + /// In cs, this message translates to: + /// **'Oznámení'** + String get notifications; + + /// No description provided for @notificationsFor. + /// + /// In cs, this message translates to: + /// **'Oznámení pro {username}'** + String notificationsFor(String username); + + /// No description provided for @objednanoChannelDescription. + /// + /// In cs, this message translates to: + /// **'Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro {username}'** + String objednanoChannelDescription(String username); + + /// No description provided for @objednanoChannelName. + /// + /// In cs, this message translates to: + /// **'Objednáno?'** + String get objednanoChannelName; + + /// No description provided for @objednat. + /// + /// In cs, this message translates to: + /// **'Objednat'** + String get objednat; + + /// No description provided for @objednatAction. + /// + /// In cs, this message translates to: + /// **'Objednat náhodně'** + String get objednatAction; + + /// No description provided for @objednatZBurzy. + /// + /// In cs, this message translates to: + /// **'Objednat z burzy'** + String get objednatZBurzy; + + /// No description provided for @odebratZBurzy. + /// + /// In cs, this message translates to: + /// **'Odebrat z burzy'** + String get odebratZBurzy; + + /// No description provided for @ok. + /// + /// In cs, this message translates to: + /// **'OK'** + String get ok; + + /// No description provided for @orders. + /// + /// In cs, this message translates to: + /// **'Objednávky'** + String get orders; + + /// No description provided for @ordersWithAutojidelna. + /// + /// In cs, this message translates to: + /// **'Objednávky s Autojídelnou: {ammount}'** + String ordersWithAutojidelna(int ammount); + + /// No description provided for @other. + /// + /// In cs, this message translates to: + /// **'Ostatní'** + String get other; + + /// No description provided for @otherDescription. + /// + /// In cs, this message translates to: + /// **'Ostatní oznámení, např. chybové hlášky'** + String get otherDescription; + /// No description provided for @password. /// - /// In en, this message translates to: - /// **'Password'** + /// In cs, this message translates to: + /// **'Heslo'** String get password; /// No description provided for @passwordMustBeAtLeast6CharactersLong. /// - /// In en, this message translates to: - /// **'Password must be at least 6 characters long'** + /// In cs, this message translates to: + /// **'Heslo musí mít alespoň 6 znaků'** String get passwordMustBeAtLeast6CharactersLong; /// No description provided for @patch. /// - /// In en, this message translates to: + /// In cs, this message translates to: /// **'patch'** String get patch; + /// No description provided for @paymentAccountNumber. + /// + /// In cs, this message translates to: + /// **'Číslo účtu'** + String get paymentAccountNumber; + + /// No description provided for @paymentInfo. + /// + /// In cs, this message translates to: + /// **'Platební Údaje'** + String get paymentInfo; + + /// No description provided for @personalInfo. + /// + /// In cs, this message translates to: + /// **'Osobní Údaje'** + String get personalInfo; + + /// No description provided for @pickLocation. + /// + /// In cs, this message translates to: + /// **'Vyberte výdejnu '** + String get pickLocation; + + /// No description provided for @popupChangelogNotAvailable. + /// + /// In cs, this message translates to: + /// **'Changelog není k dispozici'** + String get popupChangelogNotAvailable; + + /// No description provided for @popupNewUpdateInfo. + /// + /// In cs, this message translates to: + /// **'Nová verze přináší: '** + String get popupNewUpdateInfo; + + /// No description provided for @popupNewVersionAvailable. + /// + /// In cs, this message translates to: + /// **'Nová verze aplikace - {version}'** + String popupNewVersionAvailable(String version); + + /// No description provided for @popupNotNow. + /// + /// In cs, this message translates to: + /// **'Teď ne'** + String get popupNotNow; + + /// No description provided for @popupShowOnGithub. + /// + /// In cs, this message translates to: + /// **'Zobrazit na Githubu'** + String get popupShowOnGithub; + + /// No description provided for @popupUpdate. + /// + /// In cs, this message translates to: + /// **'Aktualizovat'** + String get popupUpdate; + + /// No description provided for @privacyPolicy. + /// + /// In cs, this message translates to: + /// **'Zásady ochrany osobních údajů'** + String get privacyPolicy; + /// No description provided for @providerId. /// - /// In en, this message translates to: - /// **'Provider ID: {id}'** - String providerId(String id); + /// In cs, this message translates to: + /// **'ID poskytovatele: {id}'** + String providerId(Object id); /// No description provided for @remoteConfig. /// - /// In en, this message translates to: - /// **'Remote Config'** + /// In cs, this message translates to: + /// **'Vzdálená konfigurace'** String get remoteConfig; /// No description provided for @requestNotificationPermission. /// - /// In en, this message translates to: - /// **'Request Notification Permission'** + /// In cs, this message translates to: + /// **'Požádat o povolení notifikací'** String get requestNotificationPermission; /// No description provided for @resetPassword. /// - /// In en, this message translates to: - /// **'Reset password'** + /// In cs, this message translates to: + /// **'Obnovit heslo'** String get resetPassword; /// No description provided for @routingGoToDetailDetail. /// - /// In en, this message translates to: - /// **'Go to Detail Detail'** + /// In cs, this message translates to: + /// **'Jít na podrobnosti podrobností'** String get routingGoToDetailDetail; /// No description provided for @routingGoToDetailPage. /// - /// In en, this message translates to: - /// **'Go to Detail Page'** + /// In cs, this message translates to: + /// **'Jít na podrobnosti stránky'** String get routingGoToDetailPage; /// No description provided for @routingGoToParamDetailPage. /// - /// In en, this message translates to: - /// **'Go to Param Detail Page'** + /// In cs, this message translates to: + /// **'Jít na podrobnosti stránky s parametry'** String get routingGoToParamDetailPage; /// No description provided for @routingParamDetailPageDetail. /// - /// In en, this message translates to: - /// **'Routing Param Detail Page'** + /// In cs, this message translates to: + /// **'Stránka s podrobnostmi o parametrech směrování'** String get routingParamDetailPageDetail; /// No description provided for @routingParamDetailPageDetail1. /// - /// In en, this message translates to: - /// **'This is a routing param detail page.'** + /// In cs, this message translates to: + /// **'Toto je stránka s podrobnostmi o parametrech směrování.'** String get routingParamDetailPageDetail1; /// No description provided for @routingParamDetailPageDetail2. /// - /// In en, this message translates to: - /// **'It is used to test routing with parameters.'** + /// In cs, this message translates to: + /// **'Slouží k testování směrování s parametry.'** String get routingParamDetailPageDetail2; /// No description provided for @routingParamDetailPageDetail3. /// - /// In en, this message translates to: + /// In cs, this message translates to: /// **'Film ID: {filmId}'** - String routingParamDetailPageDetail3(String filmId); + String routingParamDetailPageDetail3(Object filmId); /// No description provided for @routingParamFilmId. /// - /// In en, this message translates to: - /// **'Path param Film ID'** + /// In cs, this message translates to: + /// **'Cesta param Film ID'** String get routingParamFilmId; /// No description provided for @routingParamPage. /// - /// In en, this message translates to: - /// **'Routing Param Page'** + /// In cs, this message translates to: + /// **'Stránka s parametry směrování'** String get routingParamPage; /// No description provided for @routingParamPageDetail. /// - /// In en, this message translates to: - /// **'This is a routing param page.'** + /// In cs, this message translates to: + /// **'Toto je stránka s parametry směrování.'** String get routingParamPageDetail; /// No description provided for @routingParamPageDetail2. /// - /// In en, this message translates to: - /// **'It is used to test routing with parameters.'** + /// In cs, this message translates to: + /// **'Slouží k testování směrování s parametry.'** String get routingParamPageDetail2; /// No description provided for @routingParamQueryFilmId. /// - /// In en, this message translates to: - /// **'Query param Film ID'** + /// In cs, this message translates to: + /// **'Dotaz param Film ID'** String get routingParamQueryFilmId; /// No description provided for @routingTestDetailDetail. /// - /// In en, this message translates to: - /// **'Routing Test Detail Detail'** + /// In cs, this message translates to: + /// **'Podrobnosti o testování směrování'** String get routingTestDetailDetail; /// No description provided for @routingTestDetailDetailText. /// - /// In en, this message translates to: - /// **'This is a routing test detail detail page.'** + /// In cs, this message translates to: + /// **'Toto je podostránka s podrobnostmi o testování směrování.'** String get routingTestDetailDetailText; /// No description provided for @routingTestPage. /// - /// In en, this message translates to: - /// **'Settings'** + /// In cs, this message translates to: + /// **'Nastavení'** String get routingTestPage; /// No description provided for @routingTestPageDetail. /// - /// In en, this message translates to: - /// **'This is a routing test page.'** + /// In cs, this message translates to: + /// **'Toto je stránka s testováním směrování.'** String get routingTestPageDetail; /// No description provided for @routingTestPageDetail1. /// - /// In en, this message translates to: - /// **'It is used to test routing.'** + /// In cs, this message translates to: + /// **'Slouží k testování směrování.'** String get routingTestPageDetail1; /// No description provided for @secret. /// - /// In en, this message translates to: - /// **'secret'** + /// In cs, this message translates to: + /// **'tajemství'** String get secret; /// No description provided for @secretPage. /// - /// In en, this message translates to: - /// **'Secret Page'** + /// In cs, this message translates to: + /// **'Tajná stránka'** String get secretPage; /// No description provided for @settings. /// - /// In en, this message translates to: - /// **'Settings'** + /// In cs, this message translates to: + /// **'Nastavení'** String get settings; + /// No description provided for @settingsAmoled. + /// + /// In cs, this message translates to: + /// **'AMOLED mód'** + String get settingsAmoled; + + /// No description provided for @settingsAmoledSub. + /// + /// In cs, this message translates to: + /// **'Přidej se k temné straně síly!'** + String get settingsAmoledSub; + + /// No description provided for @settingsAnotherOptions. + /// + /// In cs, this message translates to: + /// **'Další možnosti v nastavení systému...'** + String get settingsAnotherOptions; + + /// No description provided for @settingsAppearence. + /// + /// In cs, this message translates to: + /// **'Vzhled'** + String get settingsAppearence; + + /// No description provided for @settingsCalendarBigMarkers. + /// + /// In cs, this message translates to: + /// **'Velké ukazatele v kalendáři'** + String get settingsCalendarBigMarkers; + + /// No description provided for @settingsDataCollection. + /// + /// In cs, this message translates to: + /// **'Shromažďování údajů'** + String get settingsDataCollection; + + /// No description provided for @settingsDataCollectionDescription_1. + /// + /// In cs, this message translates to: + /// **'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '** + String get settingsDataCollectionDescription_1; + + /// No description provided for @settingsDataCollectionDescription_2. + /// + /// In cs, this message translates to: + /// **'Zdrojovém kódu'** + String get settingsDataCollectionDescription_2; + + /// No description provided for @settingsDataCollectionDescription_3. + /// + /// In cs, this message translates to: + /// **' nebo v '** + String get settingsDataCollectionDescription_3; + + /// No description provided for @settingsDataCollectionDescription_4. + /// + /// In cs, this message translates to: + /// **'Zásadách ochrany osobních údajů.'** + String get settingsDataCollectionDescription_4; + + /// No description provided for @settingsDebugForceNotifications. + /// + /// In cs, this message translates to: + /// **'Force send notifications'** + String get settingsDebugForceNotifications; + + /// No description provided for @settingsDebugNotifications. + /// + /// In cs, this message translates to: + /// **'Send Notifications'** + String get settingsDebugNotifications; + + /// No description provided for @settingsDebugOptions. + /// + /// In cs, this message translates to: + /// **'Debug Options'** + String get settingsDebugOptions; + + /// No description provided for @settingsDisplay. + /// + /// In cs, this message translates to: + /// **'Zobrazení'** + String get settingsDisplay; + + /// No description provided for @settingsNemateObjednano. + /// + /// In cs, this message translates to: + /// **'Nemáte objednáno na příští týden'** + String get settingsNemateObjednano; + + /// No description provided for @settingsNotificationFor. + /// + /// In cs, this message translates to: + /// **'Oznámení pro {username}'** + String settingsNotificationFor(String username); + + /// No description provided for @settingsNotificationTime. + /// + /// In cs, this message translates to: + /// **'Čas oznámení: '** + String get settingsNotificationTime; + + /// No description provided for @settingsRelativeTimestamps. + /// + /// In cs, this message translates to: + /// **'Relativní časové značky'** + String get settingsRelativeTimestamps; + + /// No description provided for @settingsRelativeTimestampsSub. + /// + /// In cs, this message translates to: + /// **'„Dnes“ místo „{date}“'** + String settingsRelativeTimestampsSub(String date); + + /// No description provided for @settingsSkipWeekends. + /// + /// In cs, this message translates to: + /// **'Přeskakovat víkendy'** + String get settingsSkipWeekends; + + /// No description provided for @settingsStopDataCollection. + /// + /// In cs, this message translates to: + /// **'Zastavit sledování analytických služeb'** + String get settingsStopDataCollection; + + /// No description provided for @settingsTheme. + /// + /// In cs, this message translates to: + /// **'Schéma'** + String get settingsTheme; + + /// No description provided for @settingsTitleCredit. + /// + /// In cs, this message translates to: + /// **'Nízký credit'** + String get settingsTitleCredit; + + /// No description provided for @settingsTitleTodaysFood. + /// + /// In cs, this message translates to: + /// **'Dnešní jídlo'** + String get settingsTitleTodaysFood; + + /// No description provided for @shareApp. + /// + /// In cs, this message translates to: + /// **'Sdílet aplikaci'** + String get shareApp; + + /// No description provided for @shareDescription. + /// + /// In cs, this message translates to: + /// **'Autojídelna (aplikace na objednávání jídla)'** + String get shareDescription; + /// No description provided for @showLocale. /// - /// In en, this message translates to: - /// **'Show locale'** + /// In cs, this message translates to: + /// **'Zobrazit lokalizaci'** String get showLocale; + /// No description provided for @sideDish. + /// + /// In cs, this message translates to: + /// **'Přílohy'** + String get sideDish; + /// No description provided for @signInAnonymously. /// - /// In en, this message translates to: - /// **'Sign in Anonymously'** + /// In cs, this message translates to: + /// **'Přihlásit se anonymně'** String get signInAnonymously; /// No description provided for @signInWithApple. /// - /// In en, this message translates to: - /// **'Sign in with Apple'** + /// In cs, this message translates to: + /// **'Přihlásit se pomocí Apple'** String get signInWithApple; /// No description provided for @signInWithEmailAndPassword. /// - /// In en, this message translates to: - /// **'Sign in with email and password'** + /// In cs, this message translates to: + /// **'Přihlásit se pomocí e-mailu a hesla'** String get signInWithEmailAndPassword; /// No description provided for @signInWithGoogle. /// - /// In en, this message translates to: - /// **'Sign in with Google'** + /// In cs, this message translates to: + /// **'Přihlásit se pomocí Google'** String get signInWithGoogle; /// No description provided for @signOut. /// - /// In en, this message translates to: - /// **'Sign out'** + /// In cs, this message translates to: + /// **'Odhlásit se'** String get signOut; + /// No description provided for @soup. + /// + /// In cs, this message translates to: + /// **'Polévka'** + String get soup; + + /// No description provided for @specificSymbol. + /// + /// In cs, this message translates to: + /// **'Specifický symbol'** + String get specificSymbol; + + /// No description provided for @stable. + /// + /// In cs, this message translates to: + /// **'Stable'** + String get stable; + + /// No description provided for @statistics. + /// + /// In cs, this message translates to: + /// **'Statistiky'** + String get statistics; + + /// No description provided for @switchAccountPanelTitle. + /// + /// In cs, this message translates to: + /// **'Účty'** + String get switchAccountPanelTitle; + + /// No description provided for @systemThemeMode. + /// + /// In cs, this message translates to: + /// **'Systém'** + String get systemThemeMode; + + /// No description provided for @tabletUi. + /// + /// In cs, this message translates to: + /// **'Tablet UI'** + String get tabletUi; + + /// tabletUiOptions + /// + /// In cs, this message translates to: + /// **'{arg, select, other{error} auto{Automaticky} always{Vždy} landscape{Na šířku} never{Nikdy}}'** + String tabletUiOptions(String arg); + + /// No description provided for @toastExit. + /// + /// In cs, this message translates to: + /// **'Zmáčkněte tlačítko zpět pro ukončení aplikace'** + String get toastExit; + + /// No description provided for @tryAgain. + /// + /// In cs, this message translates to: + /// **'Zkusit znovu'** + String get tryAgain; + /// No description provided for @typeCrash. /// - /// In en, this message translates to: - /// **'Type \"crash\" to crash the app'** + /// In cs, this message translates to: + /// **'Napište \"crash\" pro pád aplikace'** String get typeCrash; + /// No description provided for @updateSnackbarDownloaded. + /// + /// In cs, this message translates to: + /// **'Aktualizace byla stažena, instalování'** + String get updateSnackbarDownloaded; + + /// No description provided for @updateSnackbarDownloading. + /// + /// In cs, this message translates to: + /// **'Nová Aktualizace se stahuje - {value}%'** + String updateSnackbarDownloading(int value); + + /// No description provided for @updateSnackbarError. + /// + /// In cs, this message translates to: + /// **'Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu'** + String get updateSnackbarError; + + /// No description provided for @updateSnackbarWaiting. + /// + /// In cs, this message translates to: + /// **'Aktualizace - Čeká se na oprávnění'** + String get updateSnackbarWaiting; + /// No description provided for @userDisplayName. /// - /// In en, this message translates to: - /// **'User Display Name: {name}'** - String userDisplayName(String name); + /// In cs, this message translates to: + /// **'Zobrazované jméno uživatele: {name}'** + String userDisplayName(Object name); /// No description provided for @userEmail. /// - /// In en, this message translates to: - /// **'User Email: {email}'** - String userEmail(String email); + /// In cs, this message translates to: + /// **'E-mail uživatele: {email}'** + String userEmail(Object email); /// No description provided for @userEmailVerified. /// - /// In en, this message translates to: - /// **'User Email Verified: {bool}'** - String userEmailVerified(String bool); + /// In cs, this message translates to: + /// **'E-mail uživatele ověřen: {bool}'** + String userEmailVerified(Object bool); /// No description provided for @userId. /// - /// In en, this message translates to: - /// **'User ID: {id}'** - String userId(String id); + /// In cs, this message translates to: + /// **'ID uživatele: {id}'** + String userId(Object id); + + /// No description provided for @variableSymbol. + /// + /// In cs, this message translates to: + /// **'Variabilní symbol'** + String get variableSymbol; /// No description provided for @verifyEmail. /// - /// In en, this message translates to: - /// **'Verify email'** + /// In cs, this message translates to: + /// **'Ověřit e-mail'** String get verifyEmail; + + /// No description provided for @version. + /// + /// In cs, this message translates to: + /// **'Verze'** + String get version; + + /// No description provided for @vlozitNaBurzu. + /// + /// In cs, this message translates to: + /// **'Vložit na burzu'** + String get vlozitNaBurzu; } class _TextsDelegate extends LocalizationsDelegate { @@ -544,7 +1428,7 @@ class _TextsDelegate extends LocalizationsDelegate { @override bool isSupported(Locale locale) => - ['cs', 'en'].contains(locale.languageCode); + ['cs'].contains(locale.languageCode); @override bool shouldReload(_TextsDelegate old) => false; @@ -555,8 +1439,6 @@ Texts lookupTexts(Locale locale) { switch (locale.languageCode) { case 'cs': return TextsCs(); - case 'en': - return TextsEn(); } throw FlutterError( diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 8c827845..9a9e684f 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -7,17 +7,58 @@ class TextsCs extends Texts { TextsCs([String locale = 'cs']) : super(locale); @override - String get accountStatus => 'Stav účtu'; + String get about => 'O aplikaci'; + + @override + String get aboutCheckForUpdates => 'Zkontrolovat aktualizace'; + + @override + String aboutCopyRight(DateTime time) { + final intl.DateFormat timeDateFormat = intl.DateFormat.y(localeName); + final String timeString = timeDateFormat.format(time); + + return '© 2023 - $timeString Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'; + } + + @override + String get aboutLatestVersion => + 'Aktuálně jste na nejnovější verzi aplikace 👍'; + + @override + String get aboutSourceCode => 'Zdrojový kód'; + + @override + String aboutVersionSubtitle(String arg, String version) { + String _temp0 = intl.Intl.selectLogic( + arg, + { + 'true': 'Debug', + 'other': 'Stable', + }, + ); + return '$_temp0 $version'; + } + + @override + String get account => 'Účet'; @override - String accountcreationTime(DateTime date) { - final intl.DateFormat dateDateFormat = - intl.DateFormat.yMMMMEEEEd(localeName); - final String dateString = dateDateFormat.format(date); + String get accountStatus => 'Stav účtu'; - return 'Čas vytvoření účtu: $dateString'; + @override + String accountcreationTime(Object date) { + return 'Čas vytvoření účtu: $date'; } + @override + String get addAccount => 'Přidat účet'; + + @override + String get allergens => 'Alergeny'; + + @override + String get allowPermission => 'Udělit oprávnění'; + @override String get appDescription => 'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'; @@ -25,15 +66,31 @@ class TextsCs extends Texts { @override String get appName => 'Autojídelna'; + @override + String get burzaAlertDialogContent => + 'Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.'; + @override String get buttonPushed => 'Tlačítko jste stiskli tolikrát:'; + @override + String get cancel => 'Zrušit'; + + @override + String get category => 'Kategorie'; + + @override + String get changeAccount => 'Změnit účet'; + @override String get connectedToANetwork => 'Připojeno k síti'; @override String get connectedToTheInternet => 'Připojeno k internetu'; + @override + String get convenience => 'Pohodlí'; + @override String get counting => 'Počítání'; @@ -50,7 +107,29 @@ class TextsCs extends Texts { String get createAccount => 'Vytvořit účet s e-mailem a heslem'; @override - String get debug => ' - debug'; + String credit(double ammount) { + final intl.NumberFormat ammountNumberFormat = + intl.NumberFormat.decimalPattern(localeName); + final String ammountString = ammountNumberFormat.format(ammount); + + return 'Kredit: $ammountString Kč'; + } + + @override + String get currency => 'Kč'; + + @override + String get darkThemeMode => 'Tmavý'; + + @override + String get dataCollectionAgreement => + 'Používáním aplikace souhlasíte se zasíláním anonymních dat. '; + + @override + String get dateFormat => 'Formát dat'; + + @override + String get debug => 'Debug'; @override String get deleteAccount => 'Smazat účet'; @@ -70,6 +149,20 @@ class TextsCs extends Texts { @override String get disconnectedFromTheInternet => 'Odpojeno od internetu'; + @override + String dochazejiciKreditChannelDescription(String username) { + return 'Oznámení o tom, zda vám dochází kredit týden dopředu pro $username'; + } + + @override + String get dochazejiciKreditChannelName => 'Docházející kredit'; + + @override + String get dontShowAgain => 'Příště nezobrazovat'; + + @override + String get drinks => 'Pití'; + @override String get email => 'E-mail'; @@ -82,12 +175,93 @@ class TextsCs extends Texts { @override String get enterYourPassword => 'Zadejte své heslo'; + @override + String get errorsBadConnection => + 'Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později'; + + @override + String get errorsBadLogin => 'Nesprávné přihlašovací údaje'; + + @override + String get errorsBadPassword => 'Špatné heslo nebo uživatelské jméno'; + + @override + String get errorsBadUrl => 'Nesprávné Url'; + + @override + String get errorsChangelog => 'Nepodařilo se získat změny :/'; + + @override + String get errorsChybaPriDavaniNaBurzu => + 'Nastala chyba při dávání jídla na burzu'; + + @override + String get errorsChybaPriRuseni => 'Nastala chyba při rušení objednávky'; + + @override + String get errorsDownloadingApp => 'Aktualizace aplikace selhala'; + + @override + String get errorsDownloadingAppDetail => + 'Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.'; + + @override + String get errorsJidloNeniNaBurze => 'Jídlo není na burze'; + + @override + String get errorsLoad => 'Selhalo načítání jídelníčku'; + + @override + String get errorsLoadingData => 'Nastala chyba při načítání dat'; + + @override + String get errorsLoginFailed => 'Přihlášení se nezdařilo'; + + @override + String errorsLoginFailedDetail(String error) { + return 'Při přihlašování došlo k chybě: $error'; + } + + @override + String get errorsNelzeObjednat => 'Oběd nelze objednat'; + + @override + String get errorsNelzeObjednatKredit => + 'Oběd nelze objednat - Nedostatečný kredit.'; + + @override + String get errorsNoInternet => 'Nemáte připojení k internetu'; + + @override + String get errorsObedNelzeZrusit => + 'Oběd nelze zrušit. Platnost objednávky vypršela.'; + + @override + String get errorsObjednavaniJidla => 'Nastala chyba při objednávání jídla'; + + @override + String get errorsUndefined => 'Nastala Chyba'; + + @override + String get errorsUpdatingData => 'Nastala chyba při aktualizaci dat'; + + @override + String get gettingDataNotifications => 'Získávám data pro oznámení'; + @override String get goBack => 'Jít zpět'; @override String get goToSettings => 'Jít na nastavení'; + @override + String jidloChannelDescription(String username) { + return 'Oznámení každý den o tom jaké je dnes jídlo pro $username'; + } + + @override + String get jidloChannelName => 'Dnešní jídlo'; + @override String get language => 'Jazyk'; @@ -101,28 +275,174 @@ class TextsCs extends Texts { String get languageName => 'Čeština'; @override - String lastSignInTime(DateTime date) { - final intl.DateFormat dateDateFormat = - intl.DateFormat.yMMMMEEEEd(localeName); - final String dateString = dateDateFormat.format(date); - - return 'Čas posledního přihlášení: $dateString'; + String lastSignInTime(Object date) { + return 'Čas posledního přihlášení: $date'; } + @override + String get licenses => 'Licence'; + + @override + String get lightThemeMode => 'Světlý'; + + @override + String get listUi => 'List UI'; + @override String get localization => 'Lokalizace'; @override - String loggedIn(String bool) { + String get location => 'Výdejna'; + + @override + String get locationsUnknown => 'Neznámá výdejna'; + + @override + String loggedIn(Object bool) { return 'Přihlášen: $bool'; } @override String get login => 'přihlásit se'; + @override + String get loginButton => 'Přihlásit se'; + + @override + String get loginPasswordFieldHint => 'Zadejte prosím své heslo'; + + @override + String get loginPasswordFieldLabel => 'Heslo'; + + @override + String get loginUrlFieldHint => + 'Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz'; + + @override + String get loginUrlFieldLabel => + 'Url stránky icanteen - např. jidelna.trebesin.cz'; + + @override + String get loginUserFieldHint => 'Zadejte prosím své uživatelské jméno'; + + @override + String get loginUserFieldLabel => 'Uživatelské jméno'; + + @override + String get logoutConfirm => 'Odhlásit se'; + + @override + String get logoutUSure => 'Opravdu se chcete odhlásit?'; + + @override + String get mainCourse => 'Hlavní chod'; + + @override + String get menu => 'Jídelníček'; + + @override + String get more => 'Více'; + + @override + String get moreInfo => 'Více informací.'; + + @override + String get name => 'Jméno'; + + @override + String get nedostatekKreditu => 'Nedostatek kreditu'; + + @override + String get neededPermission => 'Potřebné oprávnění'; + + @override + String get neededPermissionDescription_1 => + 'Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.'; + + @override + String get neededPermissionDescription_2 => 'Ta může vypadat takto:'; + + @override + String get neededPermissionDescription_3 => + 'Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.'; + + @override + String get nelzeObjednat => 'Nelze objednat'; + + @override + String get nelzeZrusit => 'Nelze zrušit'; + + @override + String get noFood => 'Žádná jídla pro tento den.'; + @override String get noThankYou => 'Ne, děkuji'; + @override + String get notificationDochaziVamKredit => 'Dochází vám kredit!'; + + @override + String notificationKreditPro(String first, String last, String ammount) { + return 'Kredit pro $first $last: $ammount Kč'; + } + + @override + String get notificationObjednejteSi => 'Objednejte si na příští týden'; + + @override + String notificationObjednejteSiDetail( + String first, String last, Object fist) { + return 'Uživatel $fist $last si stále ještě neobjenal na příští týden'; + } + + @override + String get notificationZtlumit => 'Ztlumit na týden'; + + @override + String get notifications => 'Oznámení'; + + @override + String notificationsFor(String username) { + return 'Oznámení pro $username'; + } + + @override + String objednanoChannelDescription(String username) { + return 'Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro $username'; + } + + @override + String get objednanoChannelName => 'Objednáno?'; + + @override + String get objednat => 'Objednat'; + + @override + String get objednatAction => 'Objednat náhodně'; + + @override + String get objednatZBurzy => 'Objednat z burzy'; + + @override + String get odebratZBurzy => 'Odebrat z burzy'; + + @override + String get ok => 'OK'; + + @override + String get orders => 'Objednávky'; + + @override + String ordersWithAutojidelna(int ammount) { + return 'Objednávky s Autojídelnou: $ammount'; + } + + @override + String get other => 'Ostatní'; + + @override + String get otherDescription => 'Ostatní oznámení, např. chybové hlášky'; + @override String get password => 'Heslo'; @@ -134,7 +454,42 @@ class TextsCs extends Texts { String get patch => 'patch'; @override - String providerId(String id) { + String get paymentAccountNumber => 'Číslo účtu'; + + @override + String get paymentInfo => 'Platební Údaje'; + + @override + String get personalInfo => 'Osobní Údaje'; + + @override + String get pickLocation => 'Vyberte výdejnu '; + + @override + String get popupChangelogNotAvailable => 'Changelog není k dispozici'; + + @override + String get popupNewUpdateInfo => 'Nová verze přináší: '; + + @override + String popupNewVersionAvailable(String version) { + return 'Nová verze aplikace - $version'; + } + + @override + String get popupNotNow => 'Teď ne'; + + @override + String get popupShowOnGithub => 'Zobrazit na Githubu'; + + @override + String get popupUpdate => 'Aktualizovat'; + + @override + String get privacyPolicy => 'Zásady ochrany osobních údajů'; + + @override + String providerId(Object id) { return 'ID poskytovatele: $id'; } @@ -170,7 +525,7 @@ class TextsCs extends Texts { 'Slouží k testování směrování s parametry.'; @override - String routingParamDetailPageDetail3(String filmId) { + String routingParamDetailPageDetail3(Object filmId) { return 'Film ID: $filmId'; } @@ -215,9 +570,97 @@ class TextsCs extends Texts { @override String get settings => 'Nastavení'; + @override + String get settingsAmoled => 'AMOLED mód'; + + @override + String get settingsAmoledSub => 'Přidej se k temné straně síly!'; + + @override + String get settingsAnotherOptions => 'Další možnosti v nastavení systému...'; + + @override + String get settingsAppearence => 'Vzhled'; + + @override + String get settingsCalendarBigMarkers => 'Velké ukazatele v kalendáři'; + + @override + String get settingsDataCollection => 'Shromažďování údajů'; + + @override + String get settingsDataCollectionDescription_1 => + 'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '; + + @override + String get settingsDataCollectionDescription_2 => 'Zdrojovém kódu'; + + @override + String get settingsDataCollectionDescription_3 => ' nebo v '; + + @override + String get settingsDataCollectionDescription_4 => + 'Zásadách ochrany osobních údajů.'; + + @override + String get settingsDebugForceNotifications => 'Force send notifications'; + + @override + String get settingsDebugNotifications => 'Send Notifications'; + + @override + String get settingsDebugOptions => 'Debug Options'; + + @override + String get settingsDisplay => 'Zobrazení'; + + @override + String get settingsNemateObjednano => 'Nemáte objednáno na příští týden'; + + @override + String settingsNotificationFor(String username) { + return 'Oznámení pro $username'; + } + + @override + String get settingsNotificationTime => 'Čas oznámení: '; + + @override + String get settingsRelativeTimestamps => 'Relativní časové značky'; + + @override + String settingsRelativeTimestampsSub(String date) { + return '„Dnes“ místo „$date“'; + } + + @override + String get settingsSkipWeekends => 'Přeskakovat víkendy'; + + @override + String get settingsStopDataCollection => + 'Zastavit sledování analytických služeb'; + + @override + String get settingsTheme => 'Schéma'; + + @override + String get settingsTitleCredit => 'Nízký credit'; + + @override + String get settingsTitleTodaysFood => 'Dnešní jídlo'; + + @override + String get shareApp => 'Sdílet aplikaci'; + + @override + String get shareDescription => 'Autojídelna (aplikace na objednávání jídla)'; + @override String get showLocale => 'Zobrazit lokalizaci'; + @override + String get sideDish => 'Přílohy'; + @override String get signInAnonymously => 'Přihlásit se anonymně'; @@ -234,29 +677,96 @@ class TextsCs extends Texts { @override String get signOut => 'Odhlásit se'; + @override + String get soup => 'Polévka'; + + @override + String get specificSymbol => 'Specifický symbol'; + + @override + String get stable => 'Stable'; + + @override + String get statistics => 'Statistiky'; + + @override + String get switchAccountPanelTitle => 'Účty'; + + @override + String get systemThemeMode => 'Systém'; + + @override + String get tabletUi => 'Tablet UI'; + + @override + String tabletUiOptions(String arg) { + String _temp0 = intl.Intl.selectLogic( + arg, + { + 'other': 'error', + 'auto': 'Automaticky', + 'always': 'Vždy', + 'landscape': 'Na šířku', + 'never': 'Nikdy', + }, + ); + return '$_temp0'; + } + + @override + String get toastExit => 'Zmáčkněte tlačítko zpět pro ukončení aplikace'; + + @override + String get tryAgain => 'Zkusit znovu'; + @override String get typeCrash => 'Napište \"crash\" pro pád aplikace'; @override - String userDisplayName(String name) { + String get updateSnackbarDownloaded => + 'Aktualizace byla stažena, instalování'; + + @override + String updateSnackbarDownloading(int value) { + return 'Nová Aktualizace se stahuje - $value%'; + } + + @override + String get updateSnackbarError => + 'Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu'; + + @override + String get updateSnackbarWaiting => 'Aktualizace - Čeká se na oprávnění'; + + @override + String userDisplayName(Object name) { return 'Zobrazované jméno uživatele: $name'; } @override - String userEmail(String email) { + String userEmail(Object email) { return 'E-mail uživatele: $email'; } @override - String userEmailVerified(String bool) { + String userEmailVerified(Object bool) { return 'E-mail uživatele ověřen: $bool'; } @override - String userId(String id) { + String userId(Object id) { return 'ID uživatele: $id'; } + @override + String get variableSymbol => 'Variabilní symbol'; + @override String get verifyEmail => 'Ověřit e-mail'; + + @override + String get version => 'Verze'; + + @override + String get vlozitNaBurzu => 'Vložit na burzu'; } diff --git a/lib/src/lang/output/texts_en.dart b/lib/src/lang/output/texts_en.dart deleted file mode 100644 index 32f421ac..00000000 --- a/lib/src/lang/output/texts_en.dart +++ /dev/null @@ -1,260 +0,0 @@ -import 'package:intl/intl.dart' as intl; - -import 'texts.dart'; - -/// The translations for English (`en`). -class TextsEn extends Texts { - TextsEn([String locale = 'en']) : super(locale); - - @override - String get accountStatus => 'Account Status'; - - @override - String accountcreationTime(DateTime date) { - final intl.DateFormat dateDateFormat = - intl.DateFormat.yMMMMEEEEd(localeName); - final String dateString = dateDateFormat.format(date); - - return 'Account Creation Time: $dateString'; - } - - @override - String get appDescription => - 'Application for ordering from the Icanteen system. The aim of this application is to simplify, speed up (or even automate) the ordering of lunches.'; - - @override - String get appName => 'Autojídelna'; - - @override - String get buttonPushed => 'You have pushed the button this many times:'; - - @override - String get connectedToANetwork => 'Connected to a network'; - - @override - String get connectedToTheInternet => 'Connected to the internet'; - - @override - String get counting => 'Counting'; - - @override - String get crashlytics => 'Crashlytics'; - - @override - String get crashlyticsPage => 'Crashlytics Page'; - - @override - String get crashlyticsTestCrash => 'Crashlytics test crash!'; - - @override - String get createAccount => 'Create account with email and password'; - - @override - String get debug => ' - debug'; - - @override - String get deleteAccount => 'Delete account'; - - @override - String get deleteAccountConfirm => 'Delete account'; - - @override - String get deleteAccountDialog => - 'Are you sure you want to delete your account?'; - - @override - String get demoPageTitle => 'Demo Page'; - - @override - String get disconnectedFromANetwork => 'Disconnected from a network'; - - @override - String get disconnectedFromTheInternet => 'Disconnected from the internet'; - - @override - String get email => 'Email'; - - @override - String get enterAValidEmailAddress => 'Please enter a valid email address'; - - @override - String get enterYourEmail => 'Please enter your email'; - - @override - String get enterYourPassword => 'Please enter your password'; - - @override - String get goBack => 'Go back'; - - @override - String get goToSettings => 'Go to settings'; - - @override - String get language => 'Language'; - - @override - String get languageCzech => 'Czech'; - - @override - String get languageEnglish => 'English'; - - @override - String get languageName => 'English'; - - @override - String lastSignInTime(DateTime date) { - final intl.DateFormat dateDateFormat = - intl.DateFormat.yMMMMEEEEd(localeName); - final String dateString = dateDateFormat.format(date); - - return 'Last Sign In Time: $dateString'; - } - - @override - String get localization => 'Localizations'; - - @override - String loggedIn(String bool) { - return 'Logged in: $bool'; - } - - @override - String get login => 'Login'; - - @override - String get noThankYou => 'No, thank you'; - - @override - String get password => 'Password'; - - @override - String get passwordMustBeAtLeast6CharactersLong => - 'Password must be at least 6 characters long'; - - @override - String get patch => 'patch'; - - @override - String providerId(String id) { - return 'Provider ID: $id'; - } - - @override - String get remoteConfig => 'Remote Config'; - - @override - String get requestNotificationPermission => 'Request Notification Permission'; - - @override - String get resetPassword => 'Reset password'; - - @override - String get routingGoToDetailDetail => 'Go to Detail Detail'; - - @override - String get routingGoToDetailPage => 'Go to Detail Page'; - - @override - String get routingGoToParamDetailPage => 'Go to Param Detail Page'; - - @override - String get routingParamDetailPageDetail => 'Routing Param Detail Page'; - - @override - String get routingParamDetailPageDetail1 => - 'This is a routing param detail page.'; - - @override - String get routingParamDetailPageDetail2 => - 'It is used to test routing with parameters.'; - - @override - String routingParamDetailPageDetail3(String filmId) { - return 'Film ID: $filmId'; - } - - @override - String get routingParamFilmId => 'Path param Film ID'; - - @override - String get routingParamPage => 'Routing Param Page'; - - @override - String get routingParamPageDetail => 'This is a routing param page.'; - - @override - String get routingParamPageDetail2 => - 'It is used to test routing with parameters.'; - - @override - String get routingParamQueryFilmId => 'Query param Film ID'; - - @override - String get routingTestDetailDetail => 'Routing Test Detail Detail'; - - @override - String get routingTestDetailDetailText => - 'This is a routing test detail detail page.'; - - @override - String get routingTestPage => 'Settings'; - - @override - String get routingTestPageDetail => 'This is a routing test page.'; - - @override - String get routingTestPageDetail1 => 'It is used to test routing.'; - - @override - String get secret => 'secret'; - - @override - String get secretPage => 'Secret Page'; - - @override - String get settings => 'Settings'; - - @override - String get showLocale => 'Show locale'; - - @override - String get signInAnonymously => 'Sign in Anonymously'; - - @override - String get signInWithApple => 'Sign in with Apple'; - - @override - String get signInWithEmailAndPassword => 'Sign in with email and password'; - - @override - String get signInWithGoogle => 'Sign in with Google'; - - @override - String get signOut => 'Sign out'; - - @override - String get typeCrash => 'Type \"crash\" to crash the app'; - - @override - String userDisplayName(String name) { - return 'User Display Name: $name'; - } - - @override - String userEmail(String email) { - return 'User Email: $email'; - } - - @override - String userEmailVerified(String bool) { - return 'User Email Verified: $bool'; - } - - @override - String userId(String id) { - return 'User ID: $id'; - } - - @override - String get verifyEmail => 'Verify email'; -} diff --git a/lib/src/logic/canteenwrapper.dart b/lib/src/logic/canteenwrapper.dart new file mode 100644 index 00000000..c039853a --- /dev/null +++ b/lib/src/logic/canteenwrapper.dart @@ -0,0 +1,560 @@ +// Hlavní soubor ve kterém Jsou indexovány obědy a zároveň je zde vytvořena instance canteenu + +// completer +import 'dart:async'; + +// json encoding and decoding +import 'dart:convert'; +import 'dart:math'; + +import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/logic/notifications.dart'; +import 'package:autojidelna/src/types/all.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; + +import 'package:canteenlib/canteenlib.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; + +import 'package:firebase_crashlytics/firebase_crashlytics.dart'; + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:hive_flutter/adapters.dart'; + +import 'package:http/http.dart' as http; +import 'package:internet_connection_checker/internet_connection_checker.dart'; + +//TODO: add functionality for analytics +bool analyticsEnabledGlobally = false; +FirebaseAnalytics? analytics; + +/// variable that sets how many max lunches are expected. The higher the worse performance but less missing lunches. This is a fix for the api sometimes not sending all the lunches +const int numberOfMaxLunches = 3; +// třída pro funkcionalitu celé aplikace +LoggedInCanteen loggedInCanteen = LoggedInCanteen(); + +class LoggedInCanteen { + LoggedInCanteen(); + Map> _currentlyLoading = {}; + Map checked = {}; + Completer? _loginCompleter; + + Completer _indexingCompleter = Completer(); + + CanteenData? _canteenData; + Canteen? _canteenInstance; + + /// Can throw ConnectionErrors + Future get canteenInstance async { + if (_canteenInstance != null && _canteenInstance!.prihlasen) { + return _canteenInstance!; + } + try { + await loginFromStorage(); + } catch (e) { + return Future.error(e); + } + return _canteenInstance!; + } + + /// Can throw ConnectionErrors + Future get canteenData async { + if (_canteenData != null && _canteenInstance!.prihlasen) { + return _canteenData!; + } + try { + await loginFromStorage(); + } catch (e) { + return Future.error(e); + } + return _canteenData!; + } + + /// this should be safe to get since we are always logged in and the data is created with the login. + /// DO NOT CALL BEFORE LOGGIN IN + Uzivatel? get uzivatel => _canteenData?.uzivatel; + + CanteenData? get canteenDataUnsafe => _canteenData; + + ///přidá +1 pro counter statistiky a pokud je zapnutý analytics tak ji pošle do firebase + void pridatStatistiku(TypStatistiky statistika) async { + Box box = Hive.box(Boxes.statistics); + switch (statistika) { + //default case + case TypStatistiky.objednavka: + int pocetStatistiky = box.get(HiveKeys.statistikaObjednavka, defaultValue: 0); + pocetStatistiky++; + if (analyticsEnabledGlobally && analytics != null) analytics!.logEvent(name: 'objednavka', parameters: {'pocet': pocetStatistiky}); + + box.put(HiveKeys.statistikaObjednavka, pocetStatistiky); + break; + case TypStatistiky.auto: + int pocetStatistiky = box.get(HiveKeys.statistikaAuto, defaultValue: 0); + pocetStatistiky++; + box.put(HiveKeys.statistikaAuto, pocetStatistiky); + break; + case TypStatistiky.burzaCatcher: + int pocetStatistiky = box.get(HiveKeys.statistikaBurzaCatcher, defaultValue: 0); + pocetStatistiky++; + box.put(HiveKeys.statistikaBurzaCatcher, pocetStatistiky); + break; + } + } + + Future runWithSafety(Future f) async { + try { + return await f; + } catch (e) { + handleError(e); + return Future.error(e); + } + } + + void handleError(dynamic e) { + //TODO: add error handling + /* + if (e == ConnectionErrors.badLogin) { + Future.delayed(Duration.zero, () => failedLoginDialog(MyApp.navigatorKey.currentState!.context, lang.errorsBadLogin)); + } else if (e == ConnectionErrors.wrongUrl) { + Future.delayed(Duration.zero, () => failedLoginDialog(MyApp.navigatorKey.currentState!.context, lang.errorsBadUrl)); + } else if (e == ConnectionErrors.noInternet) { + Future.delayed(Duration.zero, () => failedLoginDialog(MyApp.navigatorKey.currentState!.context, lang.errorsNoInternet)); + } else if (e == ConnectionErrors.connectionFailed) { + Future.delayed(Duration.zero, () => failedLoginDialog(MyApp.navigatorKey.currentState!.context, lang.errorsBadConnection)); + }*/ + } + + /// logs you in if you are already logged in or gets the already existing instance + /// We don't have to do much of error handling here because we already know that the user has been logged in. + /// If there is an error it's probably because of the internet connection or change of password. The popup is the best solution. + Future loginFromStorage() async { + try { + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + if (loginData.currentlyLoggedIn) { + _canteenInstance = await _login( + loginData.users[loginData.currentlyLoggedInId!].url, + loginData.users[loginData.currentlyLoggedInId!].username, + loginData.users[loginData.currentlyLoggedInId!].password, + safetyId: (_canteenData?.id ?? 0) + 1, + ); + return loginData.currentlyLoggedInId!; + } else { + return Future.error(ConnectionErrors.noLogin); + } + } catch (e) { + return Future.error(e); + } + } + + /// Returns a [Canteen] instance with a logged in user. + /// + /// Main logic about logging in is in this function + /// + /// Has to be called before using [canteenInstance]. + /// + /// If [url], [username] or [password] is null, it will try to get it from storage. + /// If user is logging in all [url], [username] and [password] has to be provided. + /// If user has already logged in nothing has to be provided + /// Can throw errors: + /// + /// [ConnectionErrors.noLogin] - user is not logged in (no username and password in secure storage) + /// + /// [ConnectionErrors.badLogin] - user has entered the wrong password/username + /// + /// [ConnectionErrors.wrongUrl] - user has entered the wrong url + /// + /// [ConnectionErrors.connectionFailed] - connection to the canteen server failed + /// + /// [ConnectionErrors.noInternet] - user is not connected to the internet + Future _login(String url, String username, String password, {int? safetyId, bool indexLunches = true}) async { + if (_loginCompleter == null || _loginCompleter!.isCompleted) { + _loginCompleter = Completer(); + } else { + return _loginCompleter!.future; + } + _canteenInstance = Canteen(url); + try { + if (!await _canteenInstance!.login(username, password)) { + _loginCompleter!.completeError(ConnectionErrors.badLogin); + return Future.error(ConnectionErrors.badLogin); + } + } catch (e) { + try { + await _canteenInstance!.login(username, password); //second try's the charm + } catch (e) { + bool connected = await InternetConnectionChecker().hasConnection; + _loginCompleter!.completeError(ConnectionErrors.noInternet); + if (!connected) return Future.error(ConnectionErrors.noInternet); + try { + await http.get(Uri.parse(url)); + } catch (e) { + return Future.error(ConnectionErrors.wrongUrl); + } + _loginCompleter!.completeError(ConnectionErrors.connectionFailed); + return Future.error(ConnectionErrors.connectionFailed); + } + } + try { + checked = {}; + _currentlyLoading = {}; + _canteenData = CanteenData( + id: (safetyId ?? 0) + 1, + pocetJidel: {}, + username: username, + url: url, + uzivatel: _canteenInstance!.missingFeatures.contains(Features.ziskatUzivatele) + ? Uzivatel(uzivatelskeJmeno: username) + : await _canteenInstance!.ziskejUzivatele(), + jidlaNaBurze: _canteenInstance!.missingFeatures.contains(Features.burza) ? const [] : await _canteenInstance!.ziskatBurzu(), + currentlyLoading: {}, + jidelnicky: {}, + vydejny: (await _canteenInstance!.jidelnicekDen()).vydejny, + ); + } catch (e) { + _loginCompleter!.completeError(ConnectionErrors.connectionFailed); + return Future.error(ConnectionErrors.connectionFailed); + } + if (indexLunches) { + int vydejna = (Hive.box(Boxes.appState).get(HiveKeys.location(username, url), defaultValue: 0)) + 1; + (await canteenInstance).vydejna = vydejna; + await _indexLunchesMonth(); + smartPreIndexing(DateTime.now()); + } + _loginCompleter!.complete(_canteenInstance!); + return canteenInstance; + } + + Future _indexLunchesMonth() async { + try { + if (_canteenInstance!.missingFeatures.contains(Features.jidelnicekMesic)) return; + List jidelnicky = await (await canteenInstance).jidelnicekMesic(); + for (Jidelnicek jidelnicek in jidelnicky) { + _canteenData!.jidelnicky[jidelnicek.den] = jidelnicek; + _canteenData!.pocetJidel[jidelnicek.den] = jidelnicek.jidla.length; + } + } catch (e) { + //indexing can be done later + } + } + + void zmenitVydejnu(int vydejna) async { + (await canteenInstance).vydejna = vydejna; + _canteenData!.id++; + _canteenData!.jidelnicky.clear(); + _canteenData!.pocetJidel.clear(); + await _indexLunchesMonth(); + smartPreIndexing(DateTime.now()); + } + + /// získá Jídelníček pro den [den] + /// tuto funkci nevolat globálně, nebere informace z canteenData a zároveň je neukládá + /// uživatel musí být přihlášen + /// Jinak vyhodí chybu 'Nejdříve se musíte přihlásit' + /// může vyhodit chybu 'no internet' + Future _ziskatJidelnicekDen(DateTime den, {int? tries}) async { + if (_currentlyLoading.containsKey(den) && (tries == 0 || tries == null)) { + return _currentlyLoading[den]!.future; + } + _currentlyLoading[den] ??= Completer(); + tries ??= 0; + try { + Jidelnicek jidelnicek = await (await canteenInstance).jidelnicekDen(den: den); + if (tries >= 2) { + try { + _currentlyLoading[den]!.complete(jidelnicek); + } catch (e) { + //nothing + } + Future.delayed(const Duration(seconds: 1), () => _currentlyLoading.remove(den)); + return jidelnicek; + } + //addition to fix api sometimes giving us less lunches that it should. This is a second layer for the fix + if (_canteenData!.pocetJidel[DateTime(den.year, den.month, den.day)] != null && + _canteenData!.pocetJidel[DateTime(den.year, den.month, den.day)]! > jidelnicek.jidla.length) { + return _ziskatJidelnicekDen(den, tries: tries + 1); + } + try { + _currentlyLoading[den]!.complete(jidelnicek); + } catch (e) { + //nothing + } + Future.delayed(const Duration(seconds: 1), () => _currentlyLoading.remove(den)); + return jidelnicek; + } catch (e) { + if (_currentlyLoading[den] != null) { + _currentlyLoading[den]!.completeError(e); + _currentlyLoading.remove(den); + } + if (e == CanteenLibExceptions.jePotrebaSePrihlasit) { + return _ziskatJidelnicekDen(den, tries: tries + 1); + } else if (analyticsEnabledGlobally && analytics != null) { + FirebaseCrashlytics.instance.log(e.toString()); + } + await loginFromStorage(); + return _ziskatJidelnicekDen(den, tries: tries + 1); + } + } + + /// this function should be called globally hovewer you need to be logged in or have credentials in the storage. + /// can throw errors if there is no internet connection or if there is no user logged in and if there are no credentials in storage. + /// in both cases it throws 'no internet' + Future getLunchesForDay(DateTime date, {bool? requireNew}) async { + date = DateTime(date.year, date.month, date.day); + if ((_canteenData == null || _canteenInstance == null || !_canteenInstance!.prihlasen)) { + try { + await loginFromStorage(); + } catch (e) { + return Future.error(e); + } + } + int id = _canteenData!.id; + requireNew ??= false; + + if (_canteenData!.jidelnicky.containsKey(DateTime(date.year, date.month, date.day)) && !requireNew) { + return _canteenData!.jidelnicky[DateTime(date.year, date.month, date.day)]!; + } + if (_canteenData!.currentlyLoading[date] != null) { + return _canteenData!.currentlyLoading[date]!.future; + } + if (!await InternetConnectionChecker().hasConnection) { + return Future.error(ConnectionErrors.connectionFailed); + } + Jidelnicek jidelnicek = await _ziskatJidelnicekDen(date); + + //saving to cache + if (_canteenData != null && _canteenData!.id == id) { + _canteenData!.jidelnicky[DateTime(date.year, date.month, date.day)] = jidelnicek; + + _canteenData!.pocetJidel[DateTime(date.year, date.month, date.day)] = jidelnicek.jidla.length; + } + return jidelnicek; + } + + Future smartPreIndexing(DateTime dateToBeJumpedTo) async { + preIndexLunchesRange(dateToBeJumpedTo, 3) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.subtract(const Duration(days: 2)), 2)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 3)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 6)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 9)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.subtract(const Duration(days: 5)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 12)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 15)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 18)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.add(const Duration(days: 21)), 3)) + .then((_) async => preIndexLunchesRange(dateToBeJumpedTo.subtract(const Duration(days: 8)), 3)); + } + + Future preIndexLunchesRange(DateTime start, int howManyDays) async { + _indexingCompleter = Completer(); + for (int i = 0; i < howManyDays; i++) { + preIndexLunches(start.add(Duration(days: i))); + } + await _indexingCompleter.future; + } + + Future preIndexLunches(DateTime date) async { + await getLunchesForDay(date); + try { + if (_canteenData!.currentlyLoading.isEmpty) { + _indexingCompleter.complete(); + } + } catch (e) { + return; + } + return; + } + + // just switches the account - YOU NEED TO CALL [loginFromStorage] AFTER THIS + Future switchAccount(int id) async { + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + loginData.currentlyLoggedInId = id; + await saveLoginToSecureStorage(loginData); + } + + // switches the account and logs in as the new account + Future changeAccount(int id, {bool indexLunches = false, bool saveToStorage = true}) async { + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + String url = loginData.users[id].url; + String username = loginData.users[id].username; + String password = loginData.users[id].password; + loginData.currentlyLoggedInId = id; + if (saveToStorage) { + saveLoginToSecureStorage(loginData); + } + try { + _canteenInstance = await _login(url, username, password, safetyId: (_canteenData?.id ?? 0) + 1, indexLunches: indexLunches); + return true; + } catch (e) { + return false; + } + } + + Future addAccount(String url, String username, String password) async { + try { + await _login(url, username, password, safetyId: (_canteenData?.id ?? 0) + 1); + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + loginData.users.add(LoggedInUser(username: username, password: password, url: url)); + loginData.currentlyLoggedInId = loginData.users.length - 1; + loginData.currentlyLoggedIn = true; + saveLoginToSecureStorage(loginData); + return true; + } catch (e) { + return Future.error(e); + } + } + + /// save data to secure storage used for storing username and password + Future saveStringToSharedPreferencesToSecureStorage(String key, String value) async { + const storage = FlutterSecureStorage(); + await storage.write(key: key, value: value); + } + + /// saves the loginData class to secure storage + Future saveLoginToSecureStorage(LoginDataAutojidelna loginData) async { + await saveStringToSharedPreferencesToSecureStorage('loginData', jsonEncode(loginData)); + initAwesome(); + } + + /// gets an instance of loginData. + + /// get data from secure storage + /// can return null if there is no data + Future getDataFromSecureStorage(String key) async { + const storage = FlutterSecureStorage(); + try { + String? value = await storage.read(key: key); + return value; + } catch (e) { + return null; + } + } + + ///logs out a user with [id]. + ///if [id] is null it will log out currently logged in user + Future logout({int? id}) async { + id ??= (await getLoginDataFromSecureStorage()).currentlyLoggedInId; + if (id == null) { + return logoutEveryone(); + } + if (analyticsEnabledGlobally && analytics != null) { + analytics!.logEvent(name: 'logout'); + } + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + bool isDuplicate = false; + for (int i = 0; i < loginData.users.length; i++) { + if (loginData.users[i].username == loginData.users[id].username && i != id) { + isDuplicate = true; + break; + } + } + if (!isDuplicate) { + AwesomeNotifications().removeChannel(NotificationIds.dnesniJidloChannel(loginData.users[id].username, loginData.users[id].url)); + AwesomeNotifications().removeChannel(NotificationIds.objednanoChannel(loginData.users[id].username, loginData.users[id].url)); + AwesomeNotifications().removeChannel(NotificationIds.kreditChannel(loginData.users[id].username, loginData.users[id].url)); + } + //removing just the one item from the array + + //ensuring correct loginData.currentlyloggedInId + if (id == loginData.currentlyLoggedInId) { + loginData.currentlyLoggedInId = loginData.users.length - 2; + } else if (loginData.currentlyLoggedInId != null && loginData.currentlyLoggedInId! > id) { + loginData.currentlyLoggedInId = loginData.currentlyLoggedInId! - 1; + } + + loginData.users.removeAt(id); + // if it's empty make sure to throw user on login screen + if (loginData.users.isEmpty) { + loginData.currentlyLoggedIn = false; + loginData.currentlyLoggedInId = null; + } + await saveLoginToSecureStorage(loginData); + if (loginData.currentlyLoggedInId == null) { + await logoutEveryone(); + } + return; + } + + ///logs out everyone + Future logoutEveryone() async { + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + loginData.currentlyLoggedIn = false; + loginData.users.clear(); + loginData.currentlyLoggedInId = null; + for (int id = 0; id < loginData.users.length; id++) { + AwesomeNotifications().removeChannel(NotificationIds.objednanoChannel(loginData.users[id].username, loginData.users[id].url)); + AwesomeNotifications().removeChannel(NotificationIds.kreditChannel(loginData.users[id].username, loginData.users[id].url)); + } + //even though I don't like this it is safe because this is called rarely + _canteenInstance = null; + _canteenData = null; + saveLoginToSecureStorage(loginData); + return; + } + + Future getLoginDataFromSecureStorage() async { + try { + String? value = await getDataFromSecureStorage('loginData'); + if (value == null || value.trim().isEmpty) { + return LoginDataAutojidelna(currentlyLoggedIn: false); + } + return LoginDataAutojidelna.fromJson(jsonDecode(value)); + } catch (e) { + return LoginDataAutojidelna(currentlyLoggedIn: false); + } + } + + ///Kontroluje jestli je jídlo na burze a vrátí true/false + bool jeJidloNaBurze(Jidlo jidlo) { + try { + String varianta = jidlo.varianta; + DateTime den = jidlo.den; + for (var jidloNaBurze in _canteenData!.jidlaNaBurze) { + if (jidloNaBurze.den == den && jidloNaBurze.varianta == varianta) { + return true; + } + } + } catch (e) { + return false; + } + return false; + } + + /// don't call from main thread + /// objedná první jídlo v každém dni, pokud už v tom dni nemáme objednáno. + Future quickOrder(String username) async { + if (_canteenInstance?.prihlasen != true) { + if (!await loginAsUsername(username)) return; + } + await _indexLunchesMonth(); + for (int i = 0; i < 10; i++) { + bool mameObjednano = false; + Jidelnicek jidelnicek = await getLunchesForDay(DateTime.now().add(Duration(days: i))); + for (Jidlo jidlo in jidelnicek.jidla) { + if (jidlo.objednano) { + mameObjednano = true; + break; + } + } + if (!mameObjednano && jidelnicek.jidla.isNotEmpty) { + jidelnicek = await getLunchesForDay(DateTime.now().add(Duration(days: i)), requireNew: true); + await _canteenInstance!.objednat(jidelnicek.jidla[Random().nextInt(jidelnicek.jidla.length)]); + } + } + return; + } + + Future loginAsUsername(String username, {bool saveToStorage = false}) async { + LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + for (LoggedInUser uzivatel in loginData.users) { + try { + if (uzivatel.username == username) { + await _login(uzivatel.url, uzivatel.username, uzivatel.password, safetyId: (_canteenData?.id ?? 0) + 1, indexLunches: false); + return true; + } + } catch (e) { + return false; + } + } + return false; + } +} diff --git a/lib/src/logic/github_release_logic.dart b/lib/src/logic/github_release_logic.dart deleted file mode 100644 index 3768f4a9..00000000 --- a/lib/src/logic/github_release_logic.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'dart:convert'; -import 'package:autojidelna/src/freezed/freezed.dart'; -import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; - -Future getLatestRelease() async { - const url = 'https://api.github.com/repos/App-Elevate/AUT.aplikace/releases/latest'; - final response = await http.get(Uri.parse(url)); - - GithubRelease release = GithubRelease.fromJson(json.decode(response.body)); - - debugPrint(release.assets[0].browserDownloadUrl); -} diff --git a/lib/src/logic/notifications.dart b/lib/src/logic/notifications.dart new file mode 100644 index 00000000..c0fd8fca --- /dev/null +++ b/lib/src/logic/notifications.dart @@ -0,0 +1,475 @@ +// File containing all code for notifications. This includes background fetch and awesome notifications. + +import 'package:autojidelna/src/_conf/dates.dart'; +import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/logic/canteenwrapper.dart'; +import 'package:autojidelna/src/types/all.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; + +import 'package:background_fetch/background_fetch.dart'; + +import 'package:canteenlib/canteenlib.dart'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:hive_flutter/adapters.dart'; + +// Platform messages are asynchronous, so we initialize in an async method. +Future initPlatformState() async { + // Configure BackgroundFetch. + await BackgroundFetch.configure( + BackgroundFetchConfig( + minimumFetchInterval: 120, + stopOnTerminate: false, + enableHeadless: true, + requiresBatteryNotLow: false, + requiresCharging: false, + requiresStorageNotLow: false, + requiresDeviceIdle: false, + startOnBoot: true, + requiredNetworkType: NetworkType.ANY, + ), (String taskId) async { + // <-- Event handler + // This is the fetch-event callback. + if (kDebugMode) { + print('[BackgroundFetch] Event received $taskId'); + } + // IMPORTANT: You must signal completion of your task or the OS can punish your app + // for taking too long in the background. + await doNotifications(); + BackgroundFetch.finish(taskId); + }, (String taskId) async { + // <-- Task timeout handler. + // This task has exceeded its allowed running-time. You must stop what you're doing and immediately .finish(taskId) + if (kDebugMode) { + print('[BackgroundFetch] TASK TIMEOUT taskId: $taskId'); + } + BackgroundFetch.finish(taskId); + }); + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. +} + +// [Android-only] This "Headless Task" is run when the Android app is terminated with `enableHeadless: true` +// Be sure to annotate your callback function to avoid issues in release mode on Flutter >= 3.3.0 +@pragma('vm:entry-point') +void backgroundFetchHeadlessTask(HeadlessTask task) async { + String taskId = task.taskId; + bool isTimeout = task.timeout; + if (isTimeout) { + // This task has exceeded its allowed running-time. + // You must stop what you're doing and immediately .finish(taskId) + if (kDebugMode) { + print('[BackgroundFetch] Headless task timed-out: $taskId'); + } + BackgroundFetch.finish(taskId); + return; + } + if (kDebugMode) { + print('[BackgroundFetch] Headless event received.'); + } + await doNotifications(); + BackgroundFetch.finish(taskId); +} + +Future initAwesome() async { + LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + List notificationChannelGroups = []; + List notificationChannels = []; + for (int i = 0; i < loginData.users.length; i++) { + LoggedInUser user = loginData.users[i]; + notificationChannelGroups.add( + NotificationChannelGroup( + channelGroupKey: NotificationIds.channelGroup(user.username, user.url), + channelGroupName: NotificationsTexts.notificationsFor(user.username), + ), + ); + notificationChannels.add( + NotificationChannel( + channelGroupKey: NotificationIds.channelGroup(user.username, user.url), + channelKey: NotificationIds.dnesniJidloChannel(user.username, user.url), + channelName: NotificationsTexts.jidloChannelName, + channelShowBadge: true, + channelDescription: NotificationsTexts.jidloChannelDescription(user.username), + defaultColor: const Color(0xFF9D50DD), + ledColor: Colors.white, + ), + ); + notificationChannels.add( + NotificationChannel( + channelGroupKey: NotificationIds.channelGroup(user.username, user.url), + channelKey: NotificationIds.kreditChannel(user.username, user.url), + channelName: NotificationsTexts.dochazejiciKreditChannelName, + channelShowBadge: true, + channelDescription: NotificationsTexts.dochazejiciKreditChannelDescription(user.username), + defaultColor: const Color(0xFF9D50DD), + ledColor: Colors.white, + ), + ); + notificationChannels.add( + NotificationChannel( + channelGroupKey: NotificationIds.channelGroup(user.username, user.url), + channelKey: NotificationIds.objednanoChannel(user.username, user.url), + channelName: NotificationsTexts.objednanoChannelName, + channelShowBadge: true, + channelDescription: NotificationsTexts.objednanoChannelDescription(user.username), + defaultColor: const Color(0xFF9D50DD), + ledColor: Colors.white, + ), + ); + } + notificationChannelGroups.add( + NotificationChannelGroup( + channelGroupKey: NotificationIds.channelGroupElse, + channelGroupName: NotificationsTexts.notificationOther, + ), + ); + notificationChannels.add( + NotificationChannel( + channelGroupKey: NotificationIds.channelGroupElse, + channelKey: NotificationIds.channelElse, + channelName: NotificationsTexts.notificationOther, + channelDescription: NotificationsTexts.notificationOtherDescription, + importance: NotificationImportance.Min, + playSound: false, + ), + ); + return await AwesomeNotifications().initialize( + // set the icon to null if you want to use the default app icon + null, + + notificationChannels, + + channelGroups: notificationChannelGroups, + // Channel groups are only visual and are not required + debug: false, + ); +} + +Future doNotifications({bool force = false}) async { + //TODO: add more langueages + final lang = lookupTexts(const Locale('cs')); + LoggedInCanteen loggedInCanteen = LoggedInCanteen(); + LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 588, + locked: true, + channelKey: NotificationIds.channelElse, + actionType: ActionType.Default, + title: lang.gettingDataNotifications, + ), + ); + // Don't send notifications before 9 and after 22 + for (int i = 0; i < loginData.users.length && !((DateTime.now().hour < 9 || DateTime.now().hour > 22) && !force); i++) { + //ensuring we only send the notifications once a day + bool jidloDne = true; + bool kredit = true; + bool objednavka = true; + DateTime now = DateTime.now(); + String nowString = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}'; + + TimeOfDay timeOfDay = const TimeOfDay(hour: 11, minute: 0); + DateTime time = DateTime(now.year, now.month, now.day, timeOfDay.hour, timeOfDay.minute); + int difference = time.difference(now).inMinutes; + + Box box = Hive.box(Boxes.notifications); + //difference from time of day to now + box.get(HiveKeys.lastNotificationCheck(loginData.users[i].username, loginData.users[i].url)); + if ((box.get(HiveKeys.lastNotificationCheck(loginData.users[i].username, loginData.users[i].url)) == nowString || + box.get(HiveKeys.dailyFoodInfo(loginData.users[i].username, loginData.users[i].url)) != '1' || + difference > 120 || + difference < -120) && + !force) { + jidloDne = false; + } else { + box.put(HiveKeys.lastJidloDneCheck(loginData.users[i].username, loginData.users[i].url), nowString); + } + + if (box.get(HiveKeys.lastNotificationCheck(loginData.users[i].username, loginData.users[i].url)) == nowString && !force) { + kredit = false; + objednavka = false; + } + + /* + if (kDebugMode) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: -1, + channelKey: 'else_channel', + actionType: ActionType.Default, + title: 'Notifikace Info', + body: 'jidloDne: $jidloDne, kredit: $kredit, objednavka: $objednavka', + )); + }*/ + if (!jidloDne && !kredit && !objednavka) { + continue; + } + + box.put(HiveKeys.lastNotificationCheck(loginData.users[i].username, loginData.users[i].url), nowString); + + try { + await loggedInCanteen.changeAccount(i, saveToStorage: false); + if (jidloDne || force) { + Jidelnicek jidelnicek = await loggedInCanteen.getLunchesForDay(now); + if (jidelnicek.jidla.isNotEmpty) { + for (int k = 0; k < jidelnicek.jidla.length; k++) { + if (!jidelnicek.jidla[k].objednano) { + continue; + } + if (difference > 0) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 1024 - i, + channelKey: NotificationIds.dnesniJidloChannel(loginData.users[i].username, loginData.users[i].url), + actionType: ActionType.Default, + title: NotificationsTexts.jidloChannelName, + payload: { + NotificationIds.payloadUser: loginData.users[i].username, + NotificationIds.payloadIndex: k.toString(), + NotificationIds.payloadIndexDne: jidelnicek.den.difference(minimalDate).inDays.toString(), + }, + body: jidelnicek.jidla[0].nazev, + ), + schedule: NotificationCalendar.fromDate(date: time), + ); + break; + } + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 1024 - i, + channelKey: NotificationIds.dnesniJidloChannel(loginData.users[i].username, loginData.users[i].url), + actionType: ActionType.Default, + title: NotificationsTexts.jidloChannelName, + payload: { + NotificationIds.payloadUser: loginData.users[i].username, + NotificationIds.payloadIndex: k.toString(), + NotificationIds.payloadIndexDne: jidelnicek.den.difference(minimalDate).inDays.toString(), + }, + body: jidelnicek.jidla[k].kategorizovano?.hlavniJidlo ?? jidelnicek.jidla[k].nazev, + ), + ); + break; + } + } else if (kDebugMode) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 1024, + channelKey: NotificationIds.dnesniJidloChannel(loginData.users[i].username, loginData.users[i].url), + actionType: ActionType.Default, + title: NotificationsTexts.jidloChannelName, + payload: { + NotificationIds.payloadUser: loginData.users[i].username, + }, + body: lang.noFood, + ), + ); + } else { + AwesomeNotifications().cancel(1024); + } + } + Uzivatel uzivatel = (await loggedInCanteen.canteenData).uzivatel; + //7 is limit for how many lunches we are gonna search for + int objednano = 0; + int cena = 0; + List> jidelnickyFuture = []; + for (int i = 0; i < 10; i++) { + jidelnickyFuture.add(loggedInCanteen.getLunchesForDay(DateTime.now().add(Duration(days: i)))); + } + await Future.wait(jidelnickyFuture); + for (int denIndex = 0; denIndex < 10; denIndex++) { + Jidelnicek jidelnicek = await loggedInCanteen.getLunchesForDay(DateTime.now().add(Duration(days: denIndex))); + //pokud nalezneme jídlo s cenou + if (jidelnicek.jidla.isNotEmpty && !(jidelnicek.jidla[0].cena?.isNaN ?? true)) { + cena += jidelnicek.jidla[0].cena!.toInt(); + } + if (jidelnicek.jidla.isEmpty) { + objednano++; + continue; + } + for (int jidloIndex = 0; jidloIndex < jidelnicek.jidla.length; jidloIndex++) { + if (jidelnicek.jidla[jidloIndex].objednano) { + objednano++; + } + } + } + //parse ignore date to DateTime + String? ignoreDateStr = box.get(HiveKeys.kreditNotifications(loginData.users[i].username, loginData.users[i].url)); + DateTime ignoreDate; + switch (ignoreDateStr) { + //not ignored + case '': + case null: + ignoreDate = DateTime.now().subtract(const Duration(days: 2)); + break; + //ignored forewer + case '1': + ignoreDate = DateTime.now().add(const Duration(days: 1)); + break; + //ignored for a week + default: + ignoreDate = DateTime.parse(ignoreDateStr); + break; + } + if (force || (cena != 0 && uzivatel.kredit < cena && kredit && ignoreDate.isBefore(DateTime.now()))) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 512 - i, + channelKey: NotificationIds.kreditChannel(loginData.users[i].username, loginData.users[i].url), + actionType: ActionType.Default, + title: NotificationsTexts.notificationDochaziVamKredit, + payload: {NotificationIds.payloadUser: loginData.users[i].username}, + body: NotificationsTexts.notificationKreditPro( + uzivatel.jmeno ?? '', + uzivatel.prijmeni ?? uzivatel.uzivatelskeJmeno ?? '', + uzivatel.kredit.toInt(), + ), + ), + actionButtons: [ + NotificationActionButton( + key: NotificationIds.kreditChannel(loginData.users[i].username, loginData.users[i].url), + label: NotificationsTexts.notificationZtlumit, + actionType: ActionType.Default, + enabled: true, + ), + ], + ); + } + //pokud chybí aspoň 3 obědy z příštích 10 dní + //parse ignore date to DateTime + String? ignoreDateStrObjednano = box.get(HiveKeys.nemateObjednanoNotifications(loginData.users[i].username, loginData.users[i].url)); + DateTime ignoreDateObjednano; + switch (ignoreDateStrObjednano) { + //not ignored + case '': + case null: + ignoreDateObjednano = DateTime.now().subtract(const Duration(days: 2)); + break; + //ignored forewer + case '1': + ignoreDateObjednano = DateTime.now().add(const Duration(days: 1)); + break; + //ignored for a week + default: + ignoreDateObjednano = DateTime.parse(ignoreDateStrObjednano); + break; + } + if (force || (objednano <= 7 && objednavka && ignoreDateObjednano.isBefore(DateTime.now()))) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: i, + channelKey: NotificationIds.objednanoChannel(loginData.users[i].username, loginData.users[i].url), + actionType: ActionType.Default, + title: NotificationsTexts.notificationObjednejteSi, + payload: {NotificationIds.payloadUser: loginData.users[i].username}, + body: NotificationsTexts.notificationObjednejteSiDetail(uzivatel.jmeno ?? '', uzivatel.prijmeni ?? uzivatel.uzivatelskeJmeno ?? ''), + ), + actionButtons: [ + NotificationActionButton( + key: NotificationIds.objednatButton(loginData.users[i].username, loginData.users[i].url), + label: NotificationsTexts.objednatAction, + isDangerousOption: false, + actionType: ActionType.Default, + enabled: true, + ), + NotificationActionButton( + key: NotificationIds.objednanoChannel(loginData.users[i].username, loginData.users[i].url), + label: NotificationsTexts.notificationZtlumit, + actionType: ActionType.Default, + enabled: true, + ), + ], + ); + } + } catch (e) { + await Future.delayed(const Duration(seconds: 5)); + AwesomeNotifications().cancel(588); + if (kDebugMode) { + AwesomeNotifications().createNotification( + content: NotificationContent( + id: 10, + channelKey: NotificationIds.channelElse, + actionType: ActionType.Default, + title: NotificationsTexts.nastalaChyba, + body: e.toString(), + ), + ); + } + } + } + await Future.delayed(const Duration(seconds: 5)); + AwesomeNotifications().cancel(588); + return; +} + +class NotificationController { + @pragma('vm:entry-point') + static Future handleNotificationAction(ReceivedAction? receivedAction) async { + //tlačítka ztlumení a objednání prvního oběda + if (receivedAction?.buttonKeyPressed != null && receivedAction?.buttonKeyPressed != '') { + if (receivedAction!.buttonKeyPressed.substring(0, 16) == HiveKeys.onlyNemateObjednanoNotifications) { + DateTime dateTillIgnore = DateTime.now().add(const Duration(days: 7)); + Hive.box(Boxes.notifications).put( + receivedAction.buttonKeyPressed, + '${dateTillIgnore.year}-${dateTillIgnore.month.toString().padLeft(2, '0')}-${dateTillIgnore.day.toString().padLeft(2, '0')}', + ); + } else if (receivedAction.buttonKeyPressed.substring(0, 14) == HiveKeys.onlykreditNotifications) { + DateTime dateTillIgnore = DateTime.now().add(const Duration(days: 7)); + Hive.box(Boxes.notifications).put( + receivedAction.buttonKeyPressed, + '${dateTillIgnore.year}-${dateTillIgnore.month.toString().padLeft(2, '0')}-${dateTillIgnore.day.toString().padLeft(2, '0')}', + ); + } else if (receivedAction.buttonKeyPressed.substring(0, 9) == NotificationIds.onlyObjednatButton) { + String username = receivedAction.buttonKeyPressed.substring(9).split('_')[0]; + LoggedInCanteen tempLoggedInCanteen = LoggedInCanteen(); + if (loggedInCanteen.uzivatel != null && loggedInCanteen.uzivatel?.uzivatelskeJmeno == username) { + tempLoggedInCanteen = loggedInCanteen; + } + await tempLoggedInCanteen.quickOrder(receivedAction.buttonKeyPressed.substring(9).split('_')[0]); + } + } + //přepnutí účtu, když uživatel klikne na notifikaci + if (receivedAction?.payload?[NotificationIds.payloadUser] != null) { + LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + for (LoggedInUser uzivatel in loginData.users) { + if (uzivatel.username == receivedAction?.payload?[NotificationIds.payloadUser]) { + await loggedInCanteen.switchAccount(loginData.users.indexOf(uzivatel)); + break; + } + } + } + /* + if (receivedAction?.payload?[NotificationIds.payloadIndex] != null) { + indexJidlaKtereMaBytZobrazeno = int.parse(receivedAction!.payload![NotificationIds.payloadIndex]!); + indexJidlaCoMaBytZobrazeno = int.parse(receivedAction.payload![NotificationIds.payloadIndexDne]!); + } + */ + //TODO: přidat, aby vás to hodilo na jídlo, na které jste klikli + } + + /// Use this method to detect when a new notification or a schedule is created + @pragma('vm:entry-point') + static Future onNotificationCreatedMethod(ReceivedNotification receivedNotification) async { + // Your code goes here + } + + /// Use this method to detect every time that a new notification is displayed + @pragma('vm:entry-point') + static Future onNotificationDisplayedMethod(ReceivedNotification receivedNotification) async { + // Your code goes here + } + + /// Use this method to detect if the user dismissed a notification + @pragma('vm:entry-point') + static Future onDismissActionReceivedMethod(ReceivedAction receivedAction) async {} + + /// This method is used to detect when an action button or notification is pressed when the application is open. + @pragma('vm:entry-point') + static Future onActionReceivedMethod(ReceivedAction receivedAction) async { + handleNotificationAction(receivedAction); + } +} diff --git a/lib/src/types/all.dart b/lib/src/types/all.dart new file mode 100644 index 00000000..834ff297 --- /dev/null +++ b/lib/src/types/all.dart @@ -0,0 +1,233 @@ +// Všechny objekty a enumy, které se používají v aplikaci +// TODO: převést na freezed +import 'dart:async'; + +import 'package:canteenlib/canteenlib.dart'; + +enum ConnectionErrors { + /// user is not logged in (no username and password in secure storage) + noLogin, + + /// user has entered the wrong password/username + badLogin, + + /// user has entered the wrong url + wrongUrl, + + /// connection to the canteen server failed + connectionFailed, + + /// user is not connected to the internet + noInternet, +} + +//classy pro přihlašování + +///samotný uživatel +class LoggedInUser { + String username; + String password; + String url; + LoggedInUser({ + required this.username, + required this.password, + required this.url, + }); + LoggedInUser.fromJson(Map json) + : username = json['username'], + password = json['password'], + url = json['url']; + Map toJson() => { + 'username': username, + 'password': password, + 'url': url, + }; +} + +///všichni přihlášení uživatelé +class LoginDataAutojidelna { + LoginDataAutojidelna({ + required this.currentlyLoggedIn, + }); + bool currentlyLoggedIn; + int? currentlyLoggedInId; + List users = []; + + LoginDataAutojidelna.fromJson(Map json) + : currentlyLoggedIn = json['currentlyLoggedIn'], + currentlyLoggedInId = json['currentlyLoggedInId'], + users = json['users'].map((e) => LoggedInUser.fromJson(e)).toList(); + + Map toJson() => { + 'currentlyLoggedIn': currentlyLoggedIn, + 'currentlyLoggedInId': currentlyLoggedInId, + 'users': users.map((e) => e.toJson()).toList(), + }; +} + +///omezená data pro zobrazení ve výběru účtů +class LoggedAccountsInAccountPanel { + List usernames; + int? loggedInID; + LoggedAccountsInAccountPanel({required this.usernames, required this.loggedInID}); +} + +///informace o nejnovější verzi aplikace (podpora jen pro android) +class ReleaseInfo { + ReleaseInfo({ + required this.isAndroid, + this.latestVersion, + this.downloadUrl, + this.changelog, + this.appStoreUrl, + this.isOnAppstore, + this.googlePlayUrl, + this.isOnGooglePlay, + required this.currentlyLatestVersion, + }); + String? latestVersion; + String? downloadUrl; + String? changelog; + bool? isOnAppstore; + bool? isOnGooglePlay; + String? googlePlayUrl; + String? appStoreUrl; + bool currentlyLatestVersion; + bool isAndroid; +} + +///Třída pro kešování dat Canteeny +class CanteenData { + /// id, aby se nám neindexovaly špatně jídelníčky + int id; + + /// login uživatele + String username; + + /// url kantýny + String url; + + /// info o uživateli - např kredit,jméno,příjmení... + Uzivatel uzivatel; + + /// seznam předindexovaných jídelníčků začínající Od Pondělí tohoto týdne + Map jidelnicky; + + /// fix pro api vracející méně jídel než by mělo + Map pocetJidel; + + /// seznam jídel, které jsou na burze + List jidlaNaBurze; + + /// jídelníčky, které aktuálně načítáme + Map> currentlyLoading; + + Map? vydejny; + + CanteenData({ + required this.username, + required this.url, + required this.uzivatel, + required this.jidlaNaBurze, + this.id = 0, + required this.currentlyLoading, + required this.jidelnicky, + required this.pocetJidel, + this.vydejny, + }); + CanteenData copyWith() { + return CanteenData( + username: username, + url: url, + uzivatel: uzivatel, + jidlaNaBurze: jidlaNaBurze, + currentlyLoading: currentlyLoading, + jidelnicky: jidelnicky, + pocetJidel: pocetJidel, + vydejny: vydejny, + ); + } +} + +///class pro general access o stavu snackbaru +class SnackBarShown { + SnackBarShown({required this.shown}); + bool shown = false; +} + +///Popisuje všechny možné stavy jídla +enum StavJidla { + /// je objednano a lze odebrat + objednano, + + /// je objednano a lze pouze dát na burzu + objednanoNelzeOdebrat, + + /// bylo objednano a pravděpodobně snězeno ;) + objednanoVyprsenaPlatnost, + + /// nabízíme jídlo na burze + naBurze, + + /// jídlo nemáme objednané, ale je dostupné na burze + dostupneNaBurze, + + /// jídlo nemáme objednané, ale můžeme stále ještě normálně objednat + neobjednano, + + /// jídlo nemáme objednané a není dostupné na burze, vypršela platnost nebo nemá uživatel dostatečný kredit + nedostupne +} + +///Popisuje možnosti kdy se login nepovedl +enum LoginFormErrorField { + ///heslo nebo uživatelské jméno je neplatné + password, + + ///url je neplatná + url, +} + +enum TypStatistiky { + ///normální objednávky + objednavka, + + ///automatické objednávky + auto, + + ///objednávky chycené burzaCatherem + burzaCatcher +} + +/// Describes what colors will be used by the app +enum ThemeStyle { + defaultStyle, + plumBrown, + blueMauve, + rustOlive, + evergreenSlate, + crimsonEarth, +} + +/// Describes what time format will be used by the app +enum DateFormatOptions { + dMy, + mmddyy, + ddmmyy, + yyyymmdd, + ddmmmyyyy, + mmmddyyyy, +} + +/// Class containing all fonts used by the apps +class Fonts { + static const String body = 'Inter'; + static const String headings = 'Lexend'; +} + +enum TabletUi { + auto, + always, + landscape, + never, +} diff --git a/lib/src/ui/pages/settings/settings_page.dart b/lib/src/ui/pages/settings/settings_page.dart index 770a0c01..2731894f 100644 --- a/lib/src/ui/pages/settings/settings_page.dart +++ b/lib/src/ui/pages/settings/settings_page.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; +import 'package:autojidelna/src/ui/widgets/buttons/test_notifications.dart'; import 'package:flutter/material.dart'; @RoutePage() @@ -22,6 +23,7 @@ class SettingsPage extends StatelessWidget { onPressed: () async => context.router.push(const LocalizationsPage()), child: Text(lang.language), ), + const NotificationActionButton(), ], ), ), diff --git a/lib/src/ui/widgets/buttons/test_notifications.dart b/lib/src/ui/widgets/buttons/test_notifications.dart new file mode 100644 index 00000000..4a69d1b3 --- /dev/null +++ b/lib/src/ui/widgets/buttons/test_notifications.dart @@ -0,0 +1,16 @@ +import 'package:autojidelna/src/logic/notifications.dart'; +import 'package:flutter/material.dart'; + +class NotificationActionButton extends StatelessWidget { + const NotificationActionButton({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + ElevatedButton(onPressed: () async => doNotifications(force: true), child: const Text('Notifications Force')), + ElevatedButton(onPressed: () async => doNotifications(), child: const Text('Notifications')), + ], + ); + } +} diff --git a/lib/src/ui/widgets/failed_login_dialog_widget.dart b/lib/src/ui/widgets/failed_login_dialog_widget.dart new file mode 100644 index 00000000..4411c260 --- /dev/null +++ b/lib/src/ui/widgets/failed_login_dialog_widget.dart @@ -0,0 +1,42 @@ +//TODO: add this file to the project +/* +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/logic/canteenwrapper.dart'; +import 'package:flutter/material.dart'; +void failedLoginDialog(BuildContext context, String message) async { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + final lang = context.l10n; + return PopScope( + canPop: false, + onPopInvoked: (hey) => false, + child: AlertDialog( + title: Text(lang.errorsLoginFailed), + content: Text(lang.errorsLoginFailedDetail(message)), + actionsAlignment: MainAxisAlignment.spaceBetween, + alignment: Alignment.bottomCenter, + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => const LoggingInWidget()), (route) => false); + }, + child: Text(lang.tryAgain), + ), + TextButton( + onPressed: () { + loggedInCanteen.logout(); + Navigator.of(context).pop(); + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => (LoginScreen())), (route) => false); + }, + child: Text(lang.logoutConfirm), + ), + ], + ), + ); + }, + ); +} +*/ diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b7e42cb4..3452dcd9 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import awesome_notifications +import awesome_notifications_core import firebase_analytics import firebase_core import firebase_crashlytics @@ -17,6 +19,8 @@ import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AwesomeNotificationsPlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsPlugin")) + AwesomeNotificationsCorePlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsCorePlugin")) FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 1fb7f201..e0332639 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -81,6 +81,30 @@ packages: url: "https://pub.dev" source: hosted version: "9.0.0" + awesome_notifications: + dependency: "direct main" + description: + name: awesome_notifications + sha256: d9e46ce7f5171ee1e9b1c5bc6dc40bd77528561f592842ce97ce3a0a9ae155ef + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + awesome_notifications_core: + dependency: "direct main" + description: + name: awesome_notifications_core + sha256: "38c9f9d2618c0c2abe0cea267dc161aa8c4a0a239ca2263400900b9610f33e6f" + url: "https://pub.dev" + source: hosted + version: "0.9.3" + background_fetch: + dependency: "direct main" + description: + name: background_fetch + sha256: e9f26ae54d88310b7ac2a68f2f9fcee0081a4d5f11100f233a70702021e7ac4f + url: "https://pub.dev" + source: hosted + version: "1.3.7" boolean_selector: dependency: transitive description: @@ -153,6 +177,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.2" + canteenlib: + dependency: "direct main" + description: + name: canteenlib + sha256: b4ae244c18fbc9bffbccf1b421a738a148b06ae5086f82f03a443235d1c0b4f2 + url: "https://pub.dev" + source: hosted + version: "4.1.0" characters: dependency: transitive description: @@ -225,6 +257,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.5" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" csv: dependency: transitive description: @@ -581,6 +621,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" http: dependency: "direct main" description: @@ -621,6 +669,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + internet_connection_checker: + dependency: "direct main" + description: + name: internet_connection_checker + sha256: "1c683e63e89c9ac66a40748b1b20889fd9804980da732bf2b58d6d5456c8e876" + url: "https://pub.dev" + source: hosted + version: "1.0.0+1" intl: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 3c05707a..67201afc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,11 @@ dependencies: json_annotation: ^4.9.0 http: ^1.2.1 shorebird_code_push: ^1.1.4 + awesome_notifications: ^0.9.3+1 + awesome_notifications_core: ^0.9.3 + background_fetch: ^1.3.7 + canteenlib: ^4.1.0 + internet_connection_checker: ^1.0.0+1 dev_dependencies: flutter_test: From bc588c0f6bfd83f89f528ebea3c11c18676b9ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 26 Sep 2024 19:20:37 +0200 Subject: [PATCH 03/57] add fonts --- assets/fonts/Inter-VariableFont_slnt,wght.ttf | Bin 0 -> 804612 bytes assets/fonts/Lexend-VariableFont_wght.ttf | Bin 0 -> 176220 bytes pubspec.yaml | 28 +++++------------- 3 files changed, 7 insertions(+), 21 deletions(-) create mode 100644 assets/fonts/Inter-VariableFont_slnt,wght.ttf create mode 100644 assets/fonts/Lexend-VariableFont_wght.ttf diff --git a/assets/fonts/Inter-VariableFont_slnt,wght.ttf b/assets/fonts/Inter-VariableFont_slnt,wght.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e72470871b8fc198da424b1e17ed729c202829cf GIT binary patch literal 804612 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

4*9^KT7^n>*M>|wJB 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%0DCo0&`A-%p#lSZ_a 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

r4&=ywuOFzp>FIx^> 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 Uh@3pmyhdg$M{-oyJW7cF3l>xKP5=M^ literal 0 HcmV?d00001 diff --git a/assets/fonts/Lexend-VariableFont_wght.ttf b/assets/fonts/Lexend-VariableFont_wght.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b294dc840ff5fc748fad8330e72d5dc99edf1c10 GIT binary patch literal 176220 zcmc${2Vhji_CJ1R?(QbL=^+WJn@uGokZd-UDyalSK#CwD5=ekRNO++mBBEkf>|N2P z*cBChh=}MzRBVWVh=}wO=^!PP{eNa|*-Z#Mec$iz``^vE_nbLr&YbCUXU^UbBcd=| zOw^-iX<51Jw=TaDS!;TUA@!ENH=|pLfME<8Mt|=NY z_=nZUi0l=J^FzOZS+03YhSU*pUuYdUa8S{pTN7?N19~6m=PIXFHgsRm1BtPPpfg8L zteiAGa>03`2SzYnX&1>+wF<+pfkW# zTR*z;v$MOW5(Pbi{5~_Wa>gX3lGZ_fIOH95l@qH!oO9?-A_ZXHF{ys?6#s@N8iRk`K1-SV_Qj_AKoWDiDF}B`uA(aPp<05Kknwy>LJItSZVPlj z?asQ;-dxi{hLk>92qWuCT1guQuix1C#{Rd28vpMCtWi%z?n)h#ydozjZ*ULlA%aCJ zjD552s=It{2?>gY%!F$PKmdbnLYf6Klo&e!2x2}+1J<%& z<_ipIu@Gj3MhCD^W>a;uHmZ894n+E>KH|a#St+4pr*z7vavDG*Xgp1m)(U%IjfN}2 z9t}4Mi;yQI$;`qgnML^+v+buTJ!Yd9l+ z91J183#3UGK?);wL^no5ixm53+W%P3rhozp=JI~)iT=@!w|5}$%Hamf1o`z6$} zT&E+I>9A0wsJGip3}N%PK-}nj8V9f`+9o+Rre;E2Zs2F1%_aYWbWOuikgn@pm&e{Ny|^XPoDth zojFPOp4~)q+1FT*2w5af+#Pp+vHQwJ`R<$F%yds&lI)(bJk4Dc9|ma4k|80cIVAYP zGdmVNv+4b(uUL9Z_m5uP{?VHwKDjmTi{E2cKQd$WYZtzJ&Hd$PJHB3$`OQP?zh6@S z!&@P1-|6||i^)HJpYr36z1F=Pz3#1|b)Q78`!V^aPkLs#+xgk?ookYIuIajSUGC1G za(AvT+quiWYnOfZ`m?(?rtjWTvU}&5-TP1P-hXEILI2(UXZEZ=yJz#DJ^Rn>*`K+m zF>~*xVS6`K?cMC&yEkCp`i}cHr|tVSZQoYM{tfN+Z|Srj$ll|PKLs{!jcWYe+IS%G zk6+UN*xdV%?J<8ew)=wzANV2iz^48OHVr%QOZtJWNe6xpIj}4Dz+UCRzQ_anLk@nM zbZ~?1;4c{mx1}81opf+_=YxBa4xY9jJYzn{emk@w?a6LD-$+hhA;j_u1jwm{O)xsicV0#{*BB`<%7~pV{g- zvpeI=h0Lby{!Kgln@;#Qxw|$oa}zf=`Ny5zZ9m)8_T0XpbH`%N9S=SS{A~ESbK&O? zv^#(N^!d~27g*p09(ch&*nQs5jSoBTHl?tpAjZ!z9?N(f3yWYWahx&ExZ6~cZf2-eqYoNm#7HCbMWV4;L*-qJPk+z69Kfm*SxVAmv-zM6>?Vkar4gtPh z144rXL(T`bdo}3i--7pc4h}yb;_n~g*b&+$EwpX_Hjxow2g1V4QQ_gPwjEDJ{<103 z9Uf^rWw#$lINULz({G7+7uuCRMPqsZ3 zek$U0#98xM+gba0^94L=xFZ--W{{sI#nvz0xpLp1`wtx5ee~q111K-%-xT13UN3vH zo7n=x61(DwPmrw1jkTLPY>-<#lPD``{YJt9OTG7?9zsqG1DOD^G71)^DFI3e;wik5 zH^H)Via&)YNlG!+V~l*2KqW{CRzj3EN|;irlwqv%p+$5jR@Z%~D`pz3zp=oM;_=YO zV2i?v@ibzgn7KM#A?ZYeUMgu{&>Y$ytX44#8=duhuU3Fv?xb|k_a2<~X7@Nm#!*xE7)bhmn z2mAxz|Kk6`^&|cft}FNoTvzecxUS)AaNWwc;ws8dLHUK_SuIJfl{uQ={2rcAC4IE6jt;HRh@2x#oM!kC|UEziIxL z`E&Dk=1u0E=0oN)7Lz5&5^X89^taSmW?JsFJYsp?@`mL@%jcHwEWcQGSJ@2KB7e;@x)|2Y2%{?q(#@xRyqY5zt3@A@zI|I&Y*|F(d_fN24D1Uw(` zdcX$(D+9g>*ci|hXbB7nj16oT=nCu>SP?ida75t!flmd#9Jn~}jHlZ+!uH% zs7p|J(A7aBgKi1>IOxlupMri5`Xe|nxP5SL@D;(mg9itX44x1?E%=t;dxKvNUL5>! z@ao_ngLefV4|a#xLc&8FAsHbBA;lqAg$xZD9a0xEGvv0A2ST0>SroD+WMjyVkVByv zq4}Xjp?yM!g;s}73cWFOe&~at&xXDc`eEp2q2Gr79J(X)VCd;KN}IqoQEgJ%INMy& zrgxi_ZN3e&hII)m54$>Sc-Z)`sbO=&mWKz1M~9CHuL++Lep~p;@NdF5hHno)9NrXR zj%X8Mk7yr}8*xQM?})(>BO@k6OpCZB;@*hIBVLR+*VdxP~?U4r~&qSG{f}>)i(xP&sdPMb!8Xh$+ z>Vc?5QSU~57quzsL^MVFMMp#@M0boXj4qAt7hM(odi00U+oKOepNioz0Wpy=NijoW zM#t2}%#3+GW^2s;m=iJXSX*p(Y*K7yY^T`L*nY9YVryb&#NHZvf9#X7zsEMl{uxJc zesK|T32`0b3gU|6u8Mm;?$@|IaYy6M*?sI0_FL@B?Puciicl_Yk=Q!@TkYG&+ONdWMPZ*dmBB3T>O2W+v zcPBiWurT3`gbx!AB%Dg*i2;d`iAjl>iJcNl69*>VkT^bZYU13)M-o3s{4DXi#9tD3 zC;23`Ps&ZYBB^)M;H1i=+N9}8^OEjMdO2xv(#J`wlYUIvot&PWm)s-y%H(U4tCH)J zXC>dByde4M_skL^R- z+uL8+zOwxT?Z0ThCp{*8Nc#BnkJ3+NP=+-lG$SS>Iiq7ne#R9U6&Y7&49gguQJXO} zV@}2$84EI=%y=>5jf^E3pJc4g_#tCc#`cWHjN=*SI+#1O>5$YRr$b4HfgMJ7nB3vk zi@r~G_@u+v9X52>-O;aOcE^bwU+?&S#~(VL$&Ag+$n2b1l6ht3z|8A1t1>5M&dj_e z^S;a{GhfJjE%V*XPcpyA{4R4t=8-I0R%zBvSr2Btob^`L2U(wFeUbHD)`qO#vi4{F z>157SXK&{<&QZ>(&O4pYIp1_Hb*^%L>s+7hm;G?|ewWR4i)&X-x16y#Pv*Rk^LEbX zIU91*a*J~B&E1oGD6b%IX5PQ^L-NPvzmtEWAgo|S!CeJ^7A6<=Exe=fgTf1)@;cRa zTHo2xxmV}v&Qm(y(fQ%dZ*<<-`DB;SE~#C*bh)NWLznxyGY+M#Pv*JrwJ>K4## zXtzn-?(X(lx6ivB>Ym^InJYS8QFg`HEAG1DhaSN_(tDKlnAc-jk8MT%MUh3BMV*T( zimoY|QgnCG+eM!htuH!N99rDHctY`q#f`-$OO%qJlBAM?lA4k^B~O-oQnI#WPpMyN zX6e5|grrK?K6EnQ!_rF2*6fzlJD=gLfF{$*ihoy*3QHI&_1_DI=_ zWsA$cFWXsmvOKsvy?j*p!t(dae=I-VGrZ?DJ)i0MRnOx+-4%WnZ7Y&1oE2RwDk^4G zJW%mw#itcJdYOB5=#|^6Yp5M0rhFuB^0M?Lqdo_BeZjJ;k13&$1WTyV!f#2imW**VyarH`;HvKVW~@ z{?n0ia?Etx<#@sIlH(P}YmT=Z?>RnjEOUI4 z&?X@wAu%B}Av0kFda)%jC^0lKJTW@ao|utXkvKB3I%UmSj(uEg72{dZi6`}iT8~rn++aHoSTIj%<)Dh~4#Q5aUa@0xYXo_Pla`aEfBIM`|$GgbU zM~>xQIl2xxG9yPJ$WfG$qblSG%SAp23!Rh57r8sIHW#)Etog^CbK!_PNDI4Jy}Qr4 zo7~6Tf4CdnyWKn8+b-OHVb+Cl7pj}bycD%FYe%f$?U5dzBRP6}g{yV-O z@4(7(hkZwaloIWUwm*;W-P@OKpTC`N+eNhPC%{s`r`windvM!i>}JRN#K|`JJ;WOs zcIL$gZ75yop!C5ir@t})E$JyO{3+!bt!Olekb|L0s?YM|u!TNDI{hNNJEwr6>&;foQpU&^+TlnotB=f;a zGMQyC7gn@avH@%et6{aQp3Pvh*nIXndy~DzK471*ui19C1O0d(`td#d9eyw0%*XJ0 zzLbB>m+^1-V*Z*E!C&VN{xtuU-^|}o9Q-Z5iC@hJC{b8}zRDYv1m2$~@MrjSd>9|j z|3PiAmbYPdHU!TVF_b{v(a&LNng`W zdYP?cQOp;6{|?rc*;xW>$BI}ED`4H(D0VFy&PK2f>^Al&yMx`$US<#SAF)FIk*#6h zu^-re_6GZdB3LY*9jw%r#Zf#p~qu^VXycH5`3n{ZNfGrOIhWY5z)b|*c~o~3`X*XULDHoeXk z(`)P8Uu#D1Zl*>AL! z?V??*k#^HTcAO5gKj{$8DIR2x(|7DAYDbwY8#`O|Y$~2PX0v%@WkEEAT}QXFyJ$80 zmU^+P=o$7RrDDG@ip5hb!>&7fiGs1WAI@T^GwVh@SP5OruBVZ#itfg#$P?^2dV{@7 zZ?X63EA~CDXPfCmwwzY7FX&#Jb-c)4rTcJB)X0t~6-rN~x6%vaWi0w_oYGdYD~U?H z63tKX(|9&wikZ9lpZu6&#U57^KTnA)jWSpkbzn{^VdYfJ$|#5B(^c$h8o;ih{%jCk z$8MlHhMiS5jV801G?U#-v+%rj6T1~-`67COy+Tj37w9RrkltkP(c5eZ{fm7{I%TeMz6QuV^#dMjP1{+Q#A? zXPxK7_A{+xo9G9&f%dUOw3i*E{p>LP!H)7#yo!(Iqxm>KkI&_| z@LTzl{3-q@o*AFukMVc$+&CFC+Gm)lKjAAevx)iobN+AsC7xWj^PT($%yql?&m6l2 zaug8IQc(7&UUJ2ZTZ^51@^C{v8MMM}OB z3CgF%HytzG#osHHYE!chp7j6T*R0%be0?#OUi|H(XkXLqEL@qu!Y}t##^ZaJa*yKt zFTUkUxl*W)uh156=!`JUQ*kp6i~r|eWvtReDOS2-|E<{Xc+-fG}7SmkiPDNohZf3W$7$utp zD|HIig_!3fnZGgyjKQ`B8-_X7p7EREQb+m zs#2f~#_F*foFol?cOhK5f`d~M1zVZ*HMj5B%VuUB*ses)) zVzJD@Z()hbB&D9kDpdernCW^dL+}kzLWDjY$8*Ab?9MrqVahO*4dXFmZIyP))jH0? z*j<<%=P832XLp*gnQLNLf%?%cEKr%olDPu@P~`@|M5R58ga3msMmrn4DSVWHoMQ{O z7oJ3>qwGvd2R@Jaa1*;j$-)XLo+aVQD+Q~?xyod0%SOYhS{7ku@BxTH>BCMIho`a% zQ=ln;*@e~r?>|_D{I7qMt5Lc$lxvg`P>p9-#Yb$KE5P_Ez#71tfX4thkHaiY^aJ2V zKp#LZR;!pYfMNgJJ^sRvw9tJ7R7diW9E9ST%0dh8aF3)VkGhA@bN_UAp@lEGtLe3u z-B;7wZ@7oi>+fOvT5PC`ha5)xK6;!MeDo&GU-1$>w(mN#+g4)sUe*MT_>O@vx+Ld?JxN9CB z?rwPgT6gJ-748XdcXCgBx5+)^!z6dV<&)eqKdo@j`pW9A-`>ML=WMXdpq8x%=B<3{ zj>dQHn6UV{;qN{hvHZca%O5LT{<{BXPbYr1(Eqc4`hT_}``4%d^E%-{aLA-s%7ITSdQoJ^7b)Nt?gx z^6Mitzpg3Y@^-~Vb?EjlL$+@jv~#&@=i2<8>$mUT zG-%KE%)P%}zjtfY-W^H%wq)&JQL%q(cH>58ZA@3mNqE!I&!%TN0(?`k!-wFZP*1E$#mN7w>q+Jdgf zDN%6bn2^{Wp?~xWi%kxXuZ>8!;BdA}Pp^`@D5B-uLigc0%_1sLw67C`&-OYy_WXFa z&C*|-5Ub5)^<(RP-n@F}H%+I`ony=|!ap=H9M68TMIQI@4GC=%858U1n3?U$%`YhI z+_kv0yl1cegRUEK!>FopwGA_F)LI?;*Js`efyL;XwiUvS2<`N8~`0OV$gsq z9oRh~=@Ta{#d(hzITe0CA?OTkux1R0FAmPTTagL+3o?O!K_=iY$lwg?KicE>7i4UI zLB{$QWPDqZ5ql3}_|VI+xy2??rzk~LieEx1va+&v3d&WwYw3`@?vvLY^14M{H_Gc;d0iu~tK@Y>-PDNlmMqpuMi=X1SxgMPV;s8G+5rYq*_vO*7XFwHq%^FB4$VJs~o_01?Fn8g71rO z53IqGaUSZz6Vx(%XJh}P5NC%yaQ1qL20*(=!58`)aQ1hMj?)SHlTOkpI!$Nb8+Vq@ z(RsQc4`^}9ja7>YOGyhm&CakUc9xxE=NV3dagd86aIWA%#>_3;hx>9Xw{bu24^PZM z9>jxr2oL3Lco+}o5xgzVD@Cq_zZc>8zXm-~>;QyePsoAi`YZ7)on_d@&|__&7*9p3 z67D7fhRM4bI|Fv?;e?VuPINh|=XP9&@F-k+bFs(L8)4D%KEx|_tc=Z3Qx+Zv*=imm zWvUU56INXHa+yK}d9K z&S5zPV3!)ZjM#CTP8@YM8(y+=_#85er)5}t7r&o;vD@_=1@cAMi3^oyxo!A4>`x?f zx8g^sVvSBYsQFN=9z@?%OD#;hn{Z03;M`bv{xa;>dGZ^Gv>ezg10d7{n2TDOugwq1 zs0p$Az7e3dd&2ISm__D7MsSv2#9>Uh{pc2ScOTGnrE0pwq9jxDiBN~A=WLEqTWS;a zq^E!sD=-U*6v)q_^es}pN1Pr8ZF?V-Y`y%%M{EFg5J@+{2`RYP(! z4H2+c%#tckw820C;|+)#0S?37Cun&kXk@Hj(DEuzD~z}zCt zKG+BDf%#U9f7sbWubv2>G_kLj4KIOt+%9`4`lINZu$5z#!GiT$8u(W7riu&CiP+Lc~(bg=1GX`G0L3 zP*-HJS}#dPDyL;SV$M((&3h0gefdxZXulY7$~6hmMmg#vl?`R%|JN+y*hw6Mnj`Gg zqs_`uN3@Ld)JBdv;d0bTl%r0P>?bMdl>rd?Q zHVONo8N(r3g;lX(XH7iPU=~3h)p8bn-GRA%F-|p}q6P5vo{jl(9NPUL>J1;)u1Md6 zQ4-I_aty(kfKkB@9w_JNA+jY8mA$1#w&V%2CC`v8 zc_y!*H2hK{>i+_iugNTczec0@E9AT+9H3F=0V-hL$Oeq^x{osbKoa;Eg#UHu{WoMs zahzviY<6A}&d@03TI$4c*8%5G6{e9mC&RrtxQ~G@(VzvdnQRX}k6aSAK(Bxy$m=ii z-bvuzpp4Y$Ig}=F2~jAwr-9>s5m?<@O^GeS1IelUUjwHs%!64i(={n5?^(zbK=9y8 zII0B{HKQk?to|xAL8m`-_MoIo!Y&%h|6js46shdG82DQh$sfT=>94@U7zbK_Y;(C( zrOcu#mWweX*L@mr3UCJSEZ~p|SmEVLh{e4SVM6W%a4YVA@N$$V!1OHI&*hZ{Z5zpNS*du6Wb?;z4?(G72 zA<_|$P8E1c?hUZx>{{G&ar!Inop3sfyZb1ecb`|Dq;dgtBP^zbN-t^<5;VoPjN3wi7Uo(r|`e;RP=CuzMHi0yWHi7(M}Me--!>)RE1_ z`ToVwRuALXBi)N3p_Q=KvfzV~4o?WIoS=7%SVzIXr5xS{ zmGGLl3i$s|a(o1Z;p{6P^Krh?7I-9e#pzR+(vR9H+3>T$*%|hjh{oUv2Tz#rtdKz8 zAxwOBAwPcPl6MQr?RuQR98iI|;nM?0m9&Q(E$*Ne%2pQ3_qVVz{TOP6<#7Pwi5hLC=5Fc zX@D?zk@&#}DGldqe()Gcg9k?n@|e;xocoYT`2zL46Z6qmXut6FLK{kEXDLpJrZ^r3 zFBcJaFO|??>It8qOzfjYu}5&9N*SgnG1rUuVvQ;0l2<4eps3UP7#eW9GQmNpJd0WiS*r#-%-L=KDPDfrU`&<&9np`|z1Ai*w z{=g?wF`$Q>Q?np<0qH)6@Dk)M2_Fc$u=+A{wkyoFBzQ21<5|p7i+qnlxA9l zc!T6#>`=4>ZxB1WJpt_i*8;Bgf)9Y#0v^(!Kkj0WX)$0p04+^|(03m|k1y^bOvDxX z#9hFX01;pCgpP#(k%o{F^b-J~NAT+aQ_y#>27CZ`NP{fghXcmI7iuW(_W`bjPgE`L zPY4?E#2%XtLjPdEe83$5k%w%+FhCK&0TA|f1YmEVS=k6X1PGmd09Sf}&?(Y@SEvM$ zH=$R^F9eAEJPx=|v`yJ|e?wZo!BnkBGAmIObuWR}8G;R%=qPrfxQ9lzK423~+2@mrZJ=EM$|3pRXXvknhpQSfou>P%&x&x>ri+h4nzH3hjLj9f5hwIjWvSZ zz(%r4Hj0ggM_?7J#>o5=8_TfEhVy_4@VtbVAok)Wv45}z_y<17rqDasx0}YMqb73b zAa-u@;F~!UyLLCS+3*;g1AnobF*omGx6oPq66sc)=--Z~vHcu-o-Kr5TqmrZUxd%( zOYCL%WOjwm*dqFvy~18)ufZ?$4fZCy*xrH%+}rSnUd-NQ@3HsU68MUK$o|EavXAhr z{xS9)K4B}^r|{MMjD61jjVJdnsFZ5hYW5}j3O=Q4*f;PmoB*H9@8OlX7XF#*&;x#= z@$ebnz&5g zUF@P9LVq2Mou;nXgX)gGsUEzDuE7pg3GK#Md=C2~<=C65;JxTBtQ>k{KdTS+x%%>c z*rggubA)Fu&Bf~W7L2Gj^TGTYK7oSMQxo_rPZj4T#+eQF+^{cmv)Gk^x8be) zHh#NyiX*(6?}0b*eeg*3KGAs;K8Wx{q?Pm;{C=O4zKKuM)8siVj>K7Dv^dR!NAa`# zIrvO3G|quu#%|9m@Hu`B9?5U;H{pr=Hhh*B!>jQ<_%$xU@AE#yuk)7Tw|UFpXDvJ& zSHQn2t?-Picd-Z$c{8T>nVV*h}1*&q^r*Kd%C{)v;x z7vW!h2lgf{*f+g`ujN0&Kl>+mXm7xpb0fV+@54`W6aNLX;AVJ7Z^4O%KlUw0VifJc ze}g~e?|d74DtFK-{LXI)=8_NTU-TNiPAjk*X2!GdPIy}G=6h%n<~}QSbLZ1NbT{2g zxAMJo1MQ=Ed>?(z_hWbK59|%yhEs-5$cG=|hv^i4`*#%ktjGBY?3JIC9<^uacKqt_ zF@Bbx!=CVAIzme^rayo)q zeOiuR6q>MGYk^myufAuC-8B8TpP};CpW#Xb{COkcbrvoCd*k4H7Y{$D1bFziayExw zJZ{0Pav%Lpo8YbfD`uKsXfti4Z8*=%#Ce`mp5EnPH$4yMeE;DT5586v@O$d5TnSID zt8fzA55AgL!-sUBG6+6i*I0^1HB?Wl_L*8&lU-I+rrwM5wYyWhyR>_*xI42;N>#c@ z(uh~0(OSHsLX9qx@-C;Qr%1m`eNLCt1UVZS;}PgEoCy2YIU|IU96QxiI%Gp&H56pG)mOca5-~rWzEdV zE-Tgwpja<}e4jEcqcS(yn#$~4pE5P$YSP6emY&iQzn-4VsyTDHY&~0~;&PfQMpZVb zQC&rT70u&hm$`CzuilnkMh&Cp%B41!Q!~(|=TRD(T~;E)Q8Pt8y)=V+sRmklO{uA^ zs`l&MJP~Jhj?4>G7g+kp3bXVv3KQI7Qy-YE+GvPsspn{^=IZrPWa+D_=LO=YR7(xo;Or^}_) zTaI4kT9YU#Gxr-;-%zI}SgM&{rfburO0_~Qa|ZMqHxk zo)$Y#rsYI$^6NLbwsP_~uhyTdY0gy}u*+3q8K4%_0I!0|({homS)HflB3nCEw|)S6GFnj>4KXI`qT_Uc5=PJW|3#cvyJ6sV=j z=n|NKG(()~@S9zdZ>g5~vs8OYWouH!T6Rk`vr9DdO0?{jsM&Qn^K8{ddRob7IV{$5 zSm0Cb-4U`imDzbd)oRYPc&cZ6ab~-6Y-3xb=E^pW^Gra+e&d?Q zK|9N{)EM>X%vOhCl)Gl7tK3>6TRuD_RXg;tyhKVsvY6M5_o>mcP@|e`sWE!5)0I=; zH@pkOUsg{K@U7IFVsgI7W2X}QSOtj^PNk*%jtZkg=Wt@5?Z=NI@* zZc)3gY^|X3HC6eViu_KdDPk^~;+3q*!z7~>M<;1Uc3Hk=bbh&Is&}2pISArf@@4wH zz&zDcwq=?D>Y_8dtV}O!O=($qz|@P&R&+h@vMoR?wLP1s$~kGO(W%XH;gyt zq)K%>uaw~$E(^^Vw#5+bMHG7mbTpZ4Z%&Rkk!KKM?3P4ur6)@U7wSEtAWFSC-f0ze z^5zs9gc#~25m>1gp}~VbmFHL4a>6U}SPKmrq0J0xd~JG=ggQq^G{`euNZPN`Yc3qC z295O;AqHFV%p${sy#`(xpw9I!HT59R5Nt3p%&Hks#@sN*47j1jBCq2mQENiLcsYjW zbW+=Qjye%KbBar>!u>c?TvSYWKKtTHEK?#=rq@fvHf0=!Q;Ax~)K6{Du$pO_+~k@W zs@!BeOV+7qbq!uGstVTCXbOcDSeVGQ9PY9M<1R-++-2*;U0R8|?0vY)6&3EX72__~ zgt&K7Z5CeE(q@SWn+2lTEKt>E6%#f~IbpMuQ*D;0YO@rSHVaI(xj@?NbQa6LkGnd+ zJJltK%UPh=T%g%ppxIoY*<7I6T+qpi(v|6q^OvQn;*km3TbH8n!A^xVig{np#_1Jw@U+IfhF#a8%{! z2_7<{MNF|Q#Sa}~S`U^QgfTFp)HbGO>{O(NCl}Q|br40*bNY>&iHWmLwWGRDh-mmk z0}q^3*?pfkR%&q8xrORj>4o;?O{vO!wweogz71VK!_IL5eXeTwFV_HvEC!p z#t3R524DTLkkxFFVlv1hW|>?)y1uST<}^Dy$67sk3RWpos`Ze3pGq|&YFQNL1&pq* zt*@Ji%AZo%Fw<03UpLlNHnpK%<7-`@sMJ(j(@?1eY87297ZF%-=UXOKPey!=t#zMb zIqhJnq}9LLxn0^kiF=-J^~6b2W+JAHnC(*Arpu{5sW^-C{6rn*IP(G7Ubxc>@8pH& zXgJ11LtfyzyufvNfy;i4d!ZJu5V)R>z_n4yS)lO?M3_~M#-r;ej&} z%W)QKVI`UPMTf{AcxvCwahB*jFL^c3InE-h9Fo1X!cJ#l8zc0FmZ=K9ZfUNjIakE- z!u1jm;n@M>>gy*|j;f!ArZRDqW}CW7%2C%r&K&jG9QR^>%*3OrYwM?bgk4&4YK1v- zTw11Gaxej{K85F~OF<{zf-NTtm?XPbuv!|jv|9$`$^cEgz?&-zUj_skHK3A4fq09{ zx{v{yvSM$-=X;sQxYv zrvUiicURaThYTlWLUltOrB1ADm_YW46DCf;xxesvR)4o8&P;`rs?Snzn@^KD*;EBz z=0Kbvi1#bnq(lWywHVF_;Ju9B55PB@)!^I(zak*~wt232fBVEy@;nj<18}Vw{AC@0&P9c?f4SGw}AA5jZ6(g?Df|zR~#A zkhp&cARdgv6KgZ(7diGI_nTwrDavve!#&c;52t@xYK44!IWrTZ2@?vY*l9 zx@SKG>=T3qXWt2IE3k-c@g8)Mk|XJ1=5*v5(j8BtX5kF2%H;LU#&4&niLWNn>MZn@ z%7J$>(QQ)Zs=Rb?@VgT&&ds@lq-2$(&ngkQ<0Y;0E7jIRFN1F)(T0#WeloXIO5LE* zt8;U4Vy{pmU!B`oau!RD$CB4nS`lxDvgNOsg^Ql6!D9lQLuiyt|NC^ zoOlPju&x7IxI$k@neNDYq?FkWjtjqCQE0j3B!gpCV}nzOz9h;}{6V5&$m_iTA)=$hHP(>aJ8ktQQEK-m*fUzYN3JqyJh% z@w}5&A63MN^CG^Yk@@2!Z#?`*dQ%U|ho40(&Mr}|ZhzOtj*mzzfC@XHZNhu9FWP1Y zv=|%8TF9X6Gd`Cbf9I->V`Nw$+2YrW(MFSTxw?yXz#KY_SI8zJP0F4Dr~_0125EGz zN;|tk!^Q89HIuL$zX0KjFj{an8`k^4Gb0)&q>te=I~VPmJ5D5!|aqyW^-$Vlp zKFl^y_>TjygFDtc)@U+ehD;cGm@P@Xfi^_QpyefNGLITEk7|1G{}~{o;FMBJfwmYa zbP*g!gJT@6#0hSs_`Qv?K$lY%Xma>Xl+@4%t=5IPM9P`+bU9O=AtzIUf0mw?`3A=% zHTU(;7W7J*g1&e_%1R#e_2s+UQog)GL0p4;wKsx~rKyVA5kRvrbt4X^zYBD3W zyO2S=tjz|^vhXh5tR;Zg0Z#!0jeeDdI0g&@-XG8dfJCxV0cf{b=qH)y00%T2HJK%3 zTY=1PA@@08sRyJ^Z&{)5RT*E}lQ|D%W@*+31L5zOC{DxS*`1^m!9C9n^sVk0nYcz8SfGxjU(m4(gry%6a-Oi(Fd?VuGcb?bU)7Sn^Fkb8bfZ0#9qSnk@mOYI>o@oUjiE@sFBe8oy&68MzfsHdT z!5u2O&BOY(h%4k^J+2Krb#O@Jd3gMG;x1?EX3c{Rd5lw8!jhN0#)OmI6%s2nu*_DlWFt((fVH@K3fKD00ohFaFb3W1^Sa1}X~b(siDRV)E@c466(|t;J^|_=wS(iE{m16!tLBjm`KAZ zH9K12ww8urm6rvoYXPT$nV%jDkwBy5uf2!cgLxW>45$BW#j^p^j8JX^X05xE^Nrq}CdSTxe-{ zuwo<36T^kDG-Q|TkpN$T#a*~8CQ3w=+ht&$7|wz16_hUlv>C&5d3r<1RMB78;l*Y=IFr*T5zj*ccs)fi0T8 z;d)rKVM`3^EhbP{AB~=@Vj?VB)?hSpq;W-gs&Zb~#riy&qX!sV0~5BW<>J9wEumsv zF1mw(#TuA}DC(rJIcg7Ji^RSK_PNB~1NN%Ko&a{I#AX;+oq-AN2+8f+EDUoY=;m^r zWmr1Gqa|k3vB)L^J7QqMDpd|KA~%W{kp?$Pgsqlg%bUr;Zg3D5sbVhzgN?Y}iT^1x z3iqLx#3~GKp~MoK#fUVxsKLmgZ7;Mv)OJ@})MMLK2Da?7*y{%ODFYK)7Dz4gjWCZE z^u)Fp14SAJCc+lTu=z&VvevLx^m#N-Gq|37)EZ$Pxlu;g0HlEu!WE^{HdA7D0}C@S zla588R#mx(M!d9pn}`vy7O+xciw$g%fngNTxc3^Eh%rybm|=u@Vzh>hgB;pq#GnYY zLJjL|U`_)Qa;bnpLOVvMV&D+~|L}8o!Pfx;+hJgv3=Co6-%B}9SZkOkt_NFjSuJlH zT#vrzjIjH4OjxQ}aGM?$?n$E+%qwrRj2Pn$%oAf6H1`)J5?+2;tgFFw8JH0x6*Z{t z3#6mfXuE0#=Gg%XPej~EnVK&)iZ2K(>=0m=#L&OO)(Ffq*5OR+m=FR0!@%LJC@yIjNUesuzKM{61bcmUb_ z7T`>xt&HcVyhAqIV$fWr`AM?dKE&?+Dd-9F!++dleqzVmwj7pk6*Ba-p#8*~<_>B) zaK2>|Cy(1C?JrKOY+FG8rt;k`8W5f?G=WoL!>NhX+1<9z(Eb%HFiGhxB+j%%IlU=q z@!m?cH2j3^w)Nob5F9!Ny?w%x>uX)1VK(a$NIRvp;N;qH!XagBHWN74OAh*j zmIt*|lVm#4;O9wx6!>bMq9jM;_8Q5V4V_`uWze|*n9W)a&J~g)=uGQEgYy_TQ&f(j zZGq5ceGi--k`r%m;w9$^aN0{w7HVP2y1}WODID=$a zD2*9y#z|>d<%{-0gM|zolvaw9*-BL}=)S&9hU5`&9upiMPI{R{sFI+Q0SewI2CIF~ zK{8V1NLsX~p@OEBID5+tSu8OZ4GP^RFeMJ>T_WArA!DIAnj}u(OankaqtX6k3t0pD zYL!MC2;&PyeA2CXT5#|_^ER5kHlQsedk3xLRa!mHlTv*UORcv)(nj$g8t)VwI)f5w z2rUP81SK%T=YAOmYm`-x`BIY+)^r6uRnkXL2Yr2(XmLt?PzN%$dft4$DkI9*=XJz6 zuj(M(?$sI}W#_XJ=PlwiOQG2)tIXirB<7;NAwv6NsbdUu6l*fVt`49FNm}%tTpwY( zz-&Ik!m+9(>8TCWBt>eXd^-yozZlocql+jHpF(inl^l$?T1j=496LBmTjhve^P%LN zM;y`feaNiRh$-qA@A(DoqqWLhKEI5OwuT(y?+ssX%KQ`!jX3?8+ zMNbLt4lGZ~Y=jPV49G>gBh1@`j3{OEM#TPIjg3}WD)Z?p>F)^TFnBfig(@Gk+EWIK zvNW%QPCZwG{v5PPN~WXs?Sb==Mukkx7g)L*wT)l&TWGSB5u8%9$p1jnYj=X={6lJ= z0?E;aq|KZO`W1~9sSN@>QPSTbulAq;&?GEY`^9%shZ8cd3K_g}vjJm@#Bi0lpmo~m zD&7pK%4oEOE=YQg$VI?P#GZo`h6Wyy7;-@~p!X^%b0^+yWy7l#Ep)3I$4F-m>FKOD z^aiRj2Hi){OjxX19VVSY?~IUQRC>^Sh`VW|B#$AXz$L) zK!?C`VS}RedqF32tU*|rQJS?{9M}$@EenkkG=3?r+xms39o}Vv!%{>p`KypoBrW>? zYOeQxJD2?*>AZ(`BxyYo|DDM~lu4OxZjAPReL=@*7NFm;ZANOM|KBV*#|bsyBie|M8dJ~!3-y$AuE-190{Tjo zkN#n^Ed>3%M!TrH-x_E>fj6M3F{h~<(npQ~M(L-j9D{yV((OzgSOBbH54ls;rnHw-jZ$)tr&Q3a zn?XOR(x_2kALc&L7J5R4zM~AFWSj8+OETmeRgV4~z@h|A3m|E;am0K_(oezCQP!`( zc?q0M%X`4a2pQ{E$o#0vfbMSnUX!s|S7F7?Bxfz@*5<2{pw$uJDJ@;R|5k8VZ=_Rf z9VswqE40o9Hb|y34e9)>%CHgehm+E}9@bm8pI(wOJ!Bj)t__g1&|7E~vz5@BX%($a z)hk-tH>wP2R(WZAKyro{oFPU!S(39)q~k04b&#Zw3GKe3r<{|VmEd$zIff3;bDCXp z#u%J2hW0ecnGG+@2FomHYryDj^9_ZzW0KPV&Jz|?Ey{402<^A&q6j^a>Ae^Sa5hOiT^+@-b61}0T!l?FAWHl^DExHp*?9b zUm?%%pGF}q+Sv(7JH-4dt#cst3ZDg#ak$ar%)KGgL6gBKU|9fKwc7z3GF3^`uS|zI zNN+dkY8)e-?vkDlzHCQ$zq@Y19?7}M;M`o4iyD2Yt-HHbMJ>GrjVm6J{C zSOgt6YBItOv7+fHX;DwPQnEry&Iac@Rg(17GE_;C+LglMM8f8FpNENzMy` z!?_*@|J6V*!+*&*_lVR*d9W}^&quwewY*QpbRnjV*5GN*Bxt-FNpBx#3{8hsjzOQ3 z^i3$)Osql__8_oY-EJBkJsn12;K9lqvki1u^gXBOdIR<09Xq^hX10~yF z7Ngo7;EXf7G;D;q7}$eS8qW>Prb;6hr6h8mgR5xeaJdEtV}r^^sBC?BU$$Nzhg6P1 z@0Ij@qLpKvqOki!D>uC^G1Mimg4O?4WsrKN39A?OxUj>t7@R*;4(WB}*@O99au!3I z-GtQ|TWrWIHqu@tWbnpny)M*T4TPjxHzvVneGK_fRoopw5uY zk(}3&a?LDOz&<1pxqlJsGe-8jVoj_@HDYd-k1O3uepQuMMU zRT6Y}L(+!%*Fr-Chl$Z%ElV^%XgUm9_9{B8r%stt@+PD%^^8z@7IWT;%pka%uRk#xFDs}v<6+ddnCdJ_9g z7M7rC!OSmcns3mhvIU6MgVaxVfMcP#f{!;w>b9!3j{vRaa)gn~UXbK?bC~)cfYPV~ z-Yb|zQ?P!XMzd%V{*S;Myor7;Gvm3&2k#8LfHwwKuq3?WZydV<@8z3|_x8=hd-bMb zE{|k0@b<6|@aDIF;p>k#h<$|jzpcO*Z>_}J!h-Oour>HEJ6rK>L;YalyRt?8WT=Ma}sK)Q$krnayB7IqUkvq`CWXvW!bBdf=Xs0R(Y9T-^5s_mi*8~|744Trx)w#-y$m$8s%3u0koT4Gb$Ju{OIp{jkQisM(Z>d@%Io^@8wSXWQVzg4;Q4(_IEBC;znn4a zd42FdljPXqK8fG@0a||C->4z(6WaY#k3>s(x2TO4AG{C!qK~etB}3ZMGEk%4zcpvL z(QCy=zU%lb?mua?TfMiu3VClGdRi^>&@x_2+Wiakpv;W;YdsRu7Of0rd5W@a@p11* z+#}5cWjsyR(5us;URu+$ShHgxDDIY_SI1vzQ>~V>x%Kq_PN-h*mx|M@tRbY&Czq0M87}mh$V&l0Kl$dCg>6)1j5W>~o^7-_$Jvj{a_Z!a#eKsVslgQ8O7$*uBq)b#eWO zI`h(_OSU#n2%a2wF0uB}kLVr;}#7#M6r4 zi?+2)EC2fupoL3bD|r{;%|1w1d|I}j*2+zly!6$({=KD)Ja`ATg13}wNw*T^zYe;b zZtpfF67VjY%f-`;X<3JQxPHffM35iZ-o(76)2nm|ElfO9;bXK{?8(WskQfIwp5%*p z3?T7`qPU9Ts>c_72mMi`Bkb4h)9bk9-H8AH5Yf~8J4qPp!vBxG_W+NqxYCAi-7Bf3 zmef+K)oR6-IxB~6wOVN;jq;2}8cl-9Fo_w$0t1*FX2?S@HrQkXHYVBN>~+EzW5e41 zyz32KFE+toV{C(M3^u`L)cw8Zy`3~8jQ4x?`Ty_vpMQGv_U&`)R-LLkb?Vfqx>d|q^+dd#NX%-Q)QHRXEAs3Z0g?PJ4^h^s-Gq9l9Y%qeJ3SvOi%2Sq@GXN zuc_ZhJ&iP3&&huB$onZ7If^cQsq{}rJeQIa37;;vBOXqbNt!HrDoe(edUh#2k$5c~ z18p+wfAHS_O5gj||4ny}%xAhCXEAwXn5q~svGZc^8*m!Rch_mMKC@yw>M}c@ zN8QXK92IV`QcC{lf14|l+T_Sv@^;4m?7!@C$i6-*l`NYD-aJhk%nBj*QulLko$1~1 zav6S$o`_|I!6pAKQ7=MY%7!HUJ?cWrRqW6IiGSD!>^=W2Y8T1zOe!#CF4<0&@(-rM zrM{(&Eae|erIC{J#M=l5nY6Bd$Gx zUidqjtW#7-Uexkzei#S>B99*BPF2KHF7hyWcq7GtJP&wvxufX+{ z>LEP)DfKCwo%w0?X@q=OJq*et>Pxu$W%Vtr4tQKWj+noVxlbETE_*@C#d%{dY7Oca zSod0i)5dsm3+7kf){;_P?3X6~I;B=vzAR=@7Y`K2f7C*nlPlk}5tb|dNr zrzfIraMtIo`mI_uYUnmx->%<|ve!|=QU?a>Acu7jMCk`W4Qe6Oip*sztqn6(PRwXe zptdIQ39)V}C_7fxiWRl8S8KouihZb|6Y;TP@3&KNeHuPRm;>LBYmqN2<*NwwC%eSm zi%$+~(ZgC)ti>|a;@43tQh$o|=VJZkvi=%be>JSXCf1*g^;ZdreI44c|fT- z9W~dC^D0{~^InJ3`j8{czqjFp(stDeN|)+FX@+HW4$j?Mf$&nte%5g{>$m`??d?XL z?ZNq*Md}2#FInqFsP$8|dO1%I=c?{k`w{0Ekb@G)!9kqze5tw=;V**(6hHzVM9dFC z4)Wx5J6wwdG*bc`lz?JNfKCZ0rvz9i0j-pPT1r40C7?7Z0dK3fv7=X&UWIiqI0FvX zwV3@b(d%#)T#@e9-C91*f~yBbzz$&-u^A)#Rejce9?&#PZ+1^0)ea;`^NMX5WR`pJ2Cd z>!MGkFDLc!9`^p`=ueVYa_oKK|KRhK_iB{Df9vCY%6qE!`0TX){^#-R|G+2M%2+17 zy+?dB&-XlEN`F4$IdJqR!)ta9{_g8jgJ*lr@SNn?>Y4NOds;pIhL;i&uQ3HN8*_t(8ud4l6y$9CIyt)o_J!Pj$tmg~l+G^a8r$G|?W#tX*N#&@CDnxHqT zHN4D=9;F)kEC5a42rX7e&E?1GhU+mazZ)8=jk>9qx~ZR9X#o1@Gg!&~4fGo)LgV0c zM{1T!saYh4e+70BIF%ts11Q zs($vK1A0*JP=oA4C-u|xv+!0CPBc_=IJxi&HLoAi52-cmTh~H!->x>uiGyk*P73_K z+AJsksVz9!?>V&%XZ!tJZP#DaU&M*zh8`5lNpBZhL+_wvp!8;1kV+3Fe}`yc82J5N zglc5iHdKDXc5?>qK#NWEG62BWkd(DoaiK05M9JdVimEPxSQjsJ%Zp}Fo$RnX;Jya z0-}{zNGu{26K%v2Vkyy1EF(IIU@fAl^&-B=J7t{lo`| z4-y|DK1_Uv_!r_|iSH5*6BmeaVnR^Yh>EBa4Pp*4mzYPi5c7!zL`t|$3D+s%Iwf4E zgzJ=Wof587!qL8^T^FN$Lpy4_+1mFIA7!h0hWIQ!_Ajy*_(f7jKu@EciT)2Uxm6S57A5X5&gs|;xusuaV2qvxQaMS+)a-55D$=Y zka#KaGUDaLD~MMTuOePeJVd;PcrEcd;`PK25^o@Wi1=aRjl`RXA0d8}cr)=9;;qEn zh_@5(Al^y*81XLR-Nbu{A18i-crWpO;x~wYv+SWKr8mqWS|mL5q+kKjN-QK65sQg7 zVhOR7XeX8t9mH~?lUPA?5i5yR#A;#Gw#1Z0h;wW*9I8K}(P7*1x ziV~|Rv5Jz0H*uu=DQSw5rYLEOlBOtWcvnWkP|_47O;OSmB~4M%6eUej(iA04QPLD8 zO;OSmB~4M%6eUej(iA04QPLD8O;OSmB~4M%6eUf4lAPQ}q|~Vgc>N&pA>zZtcZh!> z{+0MH@i1|L7$+tKq5T9EQ70P29AYjpk7yz06AOrxTWCLtfpQD&C)bo)Xg|58+(P@w z_0gK^yP8`pIIW)8K=cs3L?6*loFYyWR}fbcXNaqav&7w^A+4MAuZv0~U?Db~{euU*vtTiRttW(n}Vrr<1bj<}jQPh3Mh zQRcDKNkp6qgX@FD|F7yN_)?L_PsKbizjkdaWfb@gJONo~eFDG6>ypnho@oM5B;x)u; ziPsUYCw`E41Mx$|4-;=B-bDNe@uS3>iMJ4MCEiB7op=ZFPU6RicM`TVxo=6RRgM&*LGqV(Lv;#n{x8Hg6JYv603;f z-O^MIv6d)vIvRG65UeLQ5dFje5${FeZiv`OY$7%jTZpZ)E(HE@{KLD2f*r(8Vi%FK zS}MZpZeoJS@CaSQVh&AsxSQ z4c`?I^NGO2#06rUh|sX01YoTZ`9n8&okPqe<`FH#d}0BS60TFiQViB>JXd{*oONn-38PP#3 zCpw80L>IA=SVgQRx~U23i48;#(M$9Z{lqCE{UsXxCE7|-W{9hZv&6+C*Qb&9gQQq`xo#%55L**3fYQe6c47yylh{QJ6C=cKVwBiJj1hZ@ zeZ+p^0CAAGj5tIbCXNu76Gw?-#Bt&Tags>u0Ao|(oYsM&T>$G*D6|XId;9Pt3~d37 zV&$5)07kKLO-&hb3owcm%7es*hz}FL%yG>> z62C(HD)DQ?uM^F&&!fElCh;-iw}_9+N+?)tqGf+gz55Ph{tNN1#CM5@i3`LyF(HVN zv7jRAM1z<^%q8X#EyR3c0gbK)w=&Gx)W>zu$Kpf$zjAH>*7C2V)Uk3y@+5pJ*wOFc+rYQfNGoRilQlxxYeHj< zy(nwNv1SdE@ojh+~ZSdE@ojh+~Z zSdE@ojdKke=NdH5HE5h`&^XtiajrqDWGYp}YT|C@X^$ZErXc5Kkb~EmW8qVBEPZ(u z=HaC0{3h`+;L@nzz#iN7KK zmiP+sRY9}^aEAFo)XsmCFUi6GGkoDqf66&|#p(vm8e)f<5X-hv=0MFHpgqWSJMly* z8~r3HMLdtZ>i?OHMQkyN1z}|u0hWOI%fK9}#L!0kIY%540;Q8oRYyt^;yRI5#PXl4 z{S1d_vzWU*2`H&b$OlA*u?DDBW*_x4L;`RJ+6Q)&TtC2BNjyV7vY#oyGlvnvymLB6 zo|?X2+KPS_+mRXe9L9Bpj6joVVWwK*H0L|@GlWz9Eb?+TpFT&{tLazB_!TpxlDF$v z|2pC=$1ldqaW3X)lU!Z_=|yN6siVwJVqVT+&T{Y+sL9+ig#JOU!nJDaq=u4w>?a2) zZlqP5E#qj!FM95Z#1DYMv^Nsl&Jv%0|%*X-OzjL&RRbujQ4u88LMbK>EP)aD7 z!>oLmPlWjd_6fri;rDr>K+_LMJzktZo74{w4+^5R%-X+3Bnhoe@Pm}TZg^QBJ@B#! zHV{2TFVRQz6Q_vN#1+Jq#2Ml$;wBwj_lns|t4t}?im*VhrR zCw`E41Mx$|4-;=B-bDNe@uS3>iMJ4MCEiB7op=ZFPU6RicM}FD^Rmj0d5pUGq9r1*n_Htjq6YdGAU>>dm6+NK)Jl;IljL)aO z;Pb`j)W-~6kMGcP)IaJux$&L&<=SgiY8_*AYBU-~h*Iampbo=wy5 zMOt>Oe$*l=qI^cX5sKLiixG=?Tve*%R8@TDJ%+ua%y8w|9c6iUTN~97wuf05SNB_b zMq~NP-rXOu$G3lG-#$6Nn=u-#j64ry@zU8134}v341G zB!{WcDGsxrsY*Z7rX4V!k&@2I&^xt{WYIHRc4SgE9!T@Eyfe*@abBA0GkF(o^heWF zlvg@OnR>txk!kAJ(_u%lQcIP1o-vvg!}fI8K{ITk7blsgQnMJ7YIPcu}sW4 zy-8}&09CUXP1-paXQyOkfBKnT+*N3CnsG5?5}v|{@;K9yK{x=k5Qs?Y6C|FMr`@h?}uc4r`h(M)Wdm<-7PIG zV)ukADxBqcmZ)2ImfLh+C=%}JiFOBrK3_C>>GSPW{;{nc!@V7oq55UV#GZJxsjuEM z*z}bzxI1bFd+*mDZCu^gH(ye2jjZYl&vw`BtL*U9x4QOKHrKRuB2S%(xAe>OC$LIS z%k{SF(e5EVf^=P$cHQT-Az?Ru_w>YEHeFr3;{45B(d`#bM|P~PnywpIR^PQ@*zX(J z)Z-cHb@jMb@3407xP0}@!JR$zG2cvGs5~&brKfM(sIScH+E~+Ch1@ee=3eX)De=2m zOD0{U-=ueG*CpwN!e5e}XG~ly($bj#H62S(s7J*mt-y?{RfD%Nowi7+Ne@aI&^1!> zkD}y@uoj!;o+@yZ_z;Q&Md6F>RAn>g9n;>v;ryBVjZa3`^|{^sYoib3>5qoDADEjv zxGlV`&^x@fuW!qUw?I-uthqIaRaSL_JMDM+x5x$Q#zjeb$fSe&E<^lwhSrtj#=zSG z^_u30dYlGiVJV)vRM9izSMN^p6@N9-EQe{%ROe&-& z6Bg3bM?IePgvgHhMC+1$PDR(6)a6y_u++6C)tAM$$hJuhCUY9rQMzd=_)FG)b_q6)WvHTo z%@{_~InR_8G;mgGqJhn@gPE{7?MZ6T0F|xsc=$cp9`u@{?lx*;=3Qv-45!fE8oceP zrwq}=W=g$?)6|uXkQ(eBX39;(Za`)zH>V7$6XUn2n`sF&@7t&FC)!&y%zr@BA)fcv zbZG8TmoMruTbsIL)#bZmv0az1itbrkJ?S1E_4I6+2sTb_>kdu!xJ!PbdURcNZrE>) z?YwN&%%wYe+&#V(b;0uB_?DjTZIg|z=2(5X?c_qIqhMnH+BW2eTu@G@C`n=MHs;f$ zi=>+Lu0?c_N0Z*F-I@$vEV)V3$F(c6;t@G8!v`0|BQ<8y2PK|lN#2qvNsk?E5Pwpd zddn#b|Lc@x3ft!`jI%VGq$G1R2)SX}fhFh*F+b*rMqKCvoxYIAqOxM>JF8t?qG_KjSy*-k%$E+mt2;Xfm_(hOnR$!sY!=^$_{Un z@Tlo&0IHvo5slbUolc)U;+)>UU(M~`zgzuz_wINREs5#GTaZZ6(d#5dZMS-!F*640 z7@s( zq|!n$ss5~ZrG8Cn(4;29lH)YhmK9bkEi-K6s~LW!otxAV;q0iqjb_ClQe%c4G{Yu( z7o|37NDL#$#mCrE&9J?2dnhf8RyU6lt~Og;DCRb3yCiD`c8$`!L(%4vai_1Lq0Hao zKA<+9;#s!NTITJjopSrjEuQ{>IuBKLQRkXLucX8{DGxBfAt$YPXDKDiU(3jHEQDc$ zNTZ6WNAuKaA6)qCDQb88&+}^R$LFcjk}`e5M0^9{+?goGZl6+uC$PrH&l2vXuc<(c zxzaaD@3iw2yeshN!owUuzVc{qp+Gd7M3>b}u0Xb&e>ck``(pP7PE|)Hz<2c!= z8+$pT?S=v_gL#{%Q@(~@AcJT@m(9j6HS?J)g*d{?NX#B_pjhobdpB%C?64SvjcVU{ zQX-=C-KP{3+I}_qd|_dM{%CxMQg>k}R=@c}Q-SzhYJ1bz^*iF?!ArUUap~^vMau&FxQf+EAaQ7f~tYBnYFDi zqcR(9%Qg%IDhuMzvHTKm<(|m8K}Aa47*%Oq@)gz%>99ZHyGYi~S7;HL^e*itlMcB6 zSK!v9kEiIuE!(U~52onIU3Pez(BTJvJ~5z+tkmH|zEBt=WXYkCmBaG9yxdTKzvL6S zGnh>y4};yw?(50rqrPKjN_qidleWNb3{GmTn{DM&x57o8Ql@y>R$l@t!u7%kW zcdL7573w3&<8!R2B=4>`snA)Kx1l+7^jyyJ%(V zJF;QO=NsA(iEJ45dWSbydv;tlH+R{No}QhT&CXu7v**O%#I{&$+e9!pzO6U5eLN_+ zW}2+~10oZs`+Ha#CSCNpNe^pSk&q5An%$&#EuxEVH|eeEu?q4;E77F4W0!g}p0NHr z^_9>=ka$_~AbKk`#*yc$(($z=Z6ETLMeo$Unc<7pqM1%dc0BA|gq~+C-;~LP^cZGn z-=bXnIY|#0q=TzL#3uHdSt^Ag$VrNwB$Tez9p z%*g8KqS}<6+ALkErF3{&-9itsc2oIC*YXngh3}iuLv+F}mv-vHJA1=YKS6O3z#U*X z%cXu|uDrZZ+Hvq6we)n$Xidj5Z%~v*S!rQeey?@-1F5E*`aYtrz84L`@pHVN_bXfp*U-1hrQV0d3x@UC@%YzLyrjO5;K>u!|E*(T z?5xvp<*_Z9p5 zHVrj|w;i0DJFq>x?`!-1*FLqqZ|ksE{mwhG1*u3MK8sX}%w9a{!OHXb>~^+gI8vOsP{%GIM!NHva@jt7x>Lc~_VRu$sHu2oTB5;ad3jQ#}=1lp& z;0oJ$%IA-Y?GlM@SO4{ICL^O9-$*%5%0w<~!a%ANlD?HAdmVjG{OwIDFaE=nG^D{4nT+%q`1d)Z^E`wOQ%6<_ha zy7p?%K;U8h(Sbd~eJHHIsKKiEr_||nk$PX$4Vh!?l(`2WbFe#)6%Algr57`)UE?OT zSU5>j$9D>Kx$wsx#0LhJt~m(ciaYb^Xe&%|pQ!>R!;8Y&GE~~7CNH2OPk4gX z-CO#1^q*)0i)ukU$|2M98*{^s6>TUojeZt-M0Us?G+U(tp3ira$kLEW!Ge1bYoQb6^r3nNKLb87lfi7 zmq&(=NuR7YFV7MZHqBl~T{(Wh|jOSXbN029<~nHAMB5=Wj|)p zrS%IPvtZ|n{F+p0A11Xciz@cANp0oKn;BNTn9j86L#WG^r!!q{?FfRwg|EN0$f2V-XaIC3a-N1Uo`oJtOVzqswPmcXVwyzdL>k ziYb-q0?X;2k0__Gj |(DRH8=b6xXMuzhRLpV3Xg7ajVF3@5ysl93Hb=1_7OR*0> zvt+%DW|fp!hh~`!X5ygU5-R+)C@BlZ0q4T<(@~eblpq)OX?QQYZ%M)W!V=cr?nT13 zq;2=a-;}`f)4azryt7oy9A%XXttc}`peAMZX0(Y)G}|wtO_#y~QW1ySa9Lo=IwDGS z#(#6c14Ry7QC_vB)LC-J#qpQn!Z@}*+~hA)mEA)j_0Yn&8H4dd#NdTiFc8kHs7=OJ)ZR=7WivIu!#P^KH??4``sF7=!w_ku4^u3&$HK~#_liIpk@@rBhUnbQz zzZ5lSQlTlqO**VCE3A}&8AIb_CI)GBCUqn$HEA&>buf!6qcxM-yIS%-h+J$n^B##R zmq%tILLTR!x}hX~p?WudW~q8`wO(Q0H@EOxJ3WVdg8BYkR=!QDXit;cMXpV%?y=Pr!%Z`e za^9VI%c#WNAkUMxV9%9q%1=KYZ6MEYm^^wHf`T?O@jOB?_B)tTrQ%%y6F+=+p2dVUmn^eD0v2&WH{X8pd z(4^x0sh_iq%&<06YY}fwRz4bUmKb^w!@JbIX4nz(c4Y2G$-|!!!>}Q;VTK))uvoj= ztNk*a8fLH(7iyA^R}p%en#v5_iwSS~#j$4_eX8Q~fM1;R?ChsAKJmJirYg9^Gyd=p zylQZVKNqhOXE;(7i*&V=sWMo4t=g9)RapIRjlADgBxkbahgSB7{Bq3wf+ zr%SJdHfT)tklj5!Vp_REoI=6M8@Mgafdbzw>B;WTxVad$GTMgK!`rYeZm+LewY#bM@|uJki``fD3gr7~e){E;k`Ke8V; z%j&K)_4UzI*se?o8qk#Ka?MGHeIv=Ca8j9~N?E1DX6oSWjtteA4qK2(4fFR&&WyrL z4EjH(skupNuRfkm&0>^k&t>t3bx~&S3@sD0@ph6L6e?BNgJWB|$4?nj3!ip(cuFgRRsQ7>TdQk){*1Ev z#){Udy0N;kRZSf$qqWw?sm|t+7N@<^)9r3t-5*`kUhSQ6`OC-7TfOXrnI<)Q=8D!r zSG}{sQ&!blGv@1dtHNDn4Hd=yz!=7?<$;)=s{~N{#unByd^jwb@3HMd>+5s+OR2Ui z+C(Ni?V%wImQ4S`QEhjtcPtjjtKPe}G}jv)YM458Wcbu$+NYb*b~~nzY`7`^>VAVCkH#Z|zB!tk`hrisReox;kdt+h#kv=GxU)mIul`qt*6geca0^DHUJmQYTZV^sEfFua7~ebXQKyS|`q(8-g|njc<#!uBEPMTHPO8 z(^~CaQR#Q4%GgIa4oe>NcT(*G+(_?dQWIHJ>9tJiLXujT6&5W4Iut$Sl205?Q|H+` zneqJLJd=|!;z`Ax?$6Rs__CgOjh3^N*&zEfGoC-5mdTOyXD0P^u1}I)E-Rmg_3cbp z>CeotZ)Bw=E!CvHnWPGTRViw^wim^#zfJ!MYtxWkjxiVoE%pnVJ0>9awau5 zLpAP9hs|G-YJmYQI;2-PgI{J@a#Y3o$8R$NyyJFd3h23T^ z=q>QH?fH9z?0W-^Z6o0dpLejq;lhkcX`TJCzf|cE3#iTJ{wqjAsWceBKCxk{f4Mp zWPiTRl>PDZ*fLOhP{TN<^_Q5%sFblws=HxoSbOgCdS&6#!N$q)ur9VTSeP4I+cNWk@v#rAaQAiwD~*c1fyvziU8|Z~X1Y3OT3Tja_SMdp zxQhLg-FqzceSTAOmDDu&OY<*?JBD|R`P4xBd^arPjy327X&*Nxghy%LGi>#V8M8GA zRa&4)U09NOI72o3sjx;-7FAk~8N-_yDkYp$BNty>QH9fQUxE&onHW3VCNwN$8Avc_ z5nD>ietK`2wST^OaK3SGWjNpt2b_`OYW=17H;a4&fsW%>#2;6EZ38vB!`oIJe?nSA z5kTTKw1$)q^*v)RQbqr|WCCl@34HcFlY#D^#=0`3f}F0E5;Pp0Qi9WxwsCKo+S<{` zu;E2vZJ0RI`F_m5Vts`nJDx}h7%~rv@sUhOZQ2|4_yZ02(~B4Wq#yLw*ZJiSKf$7@NsclY1ouQh^6bdx4sKBd%cMCN37cIPnt{b~WqTq$iT}mq0IKZJYFkB>iWg zS7gx-C+R1Ft}^i()&zY1i2p~RdkoQ`W;|~s!~ZMjUgJAy`kxY)&`ytlyKfpIBWCzF z&G6bJM%E|~&@rl%-t@x~`(a%FFq5kOb^?4Lw-uoOlp2*71|8v2Z{yT6iWh*J?~=>N@cvVtW*I zUAQ=|d_Ld4Ci^+$1))_VYYt_EKKSs5#1|(r+0ORBb*-^bj4Rk8p_sZq_uXsbp1tor zwL+;+p8gjI+Di+yzaESKL`rx%VUy=jlJK3NK1wk_Kx~-JE2s1&V}nZ$8H`|}@t)jw z&x`l%_~W-H-oE_=C1Q&|RoW4M98$XyaeSU!P-<81m86ggeCP0-JdRXOV=7IzNQ*&e zbs<70srtLUGON~|uxZ~TM`qa4%Y{z~`+;;=3wBF?jH}xEAWz@P3T-n(ql_M-97r6H z1MFZSa`1X$PFb@;mtQ8exq!H}WZ7X=8&;fBC-3 zc28}mALV^|QFUja!adlQV|O(*ly&Z05r0xe+xlvu_iEx#saR8=+u?x<{4PoaElGGm znVu_o#M+?$z;{aHRwgwrc>Hf@+~QM~RJcgZ)Oj+_7mF4aqh810^q}5@*s#1LDXmgm$ zLluOU$R65Z0hgKWEw=T|gxITe1*KPMLt~OfW_r;j&W311=W*;=+WV6|%csyXC9hZ$ z>8JEa>X06Nok$PpbBnktr>}!0LmgrAs%BXW;1xOG_!jyhmet*X>lD-ARBZ|M^{ZsB zw|B2SHtGe#(&`8MvpYS#cx`oamGp%Vf=gN;Z|TEGq2!1$G*>!^N(%Lu){QF<9=Gn< z^ClPO0(wEHtI0@8k+o?@ zj;q9+e~$t`KinH$7cOXz+3kgnd>K<6|2LZ3_XeBVhPx^n>wEn6s^n10Y8y&^88d2}g?NB9kmX zEnf7cCvB+)5jl3!)lfaYzB9Uc)DL&c_8hgVEwnu3?`v{4tzDLMrv!SoO}iRglgEaa zR+9|_jZOUxSRD*!OIu5zx4yD{c~fLvCq|sEfU~~8Q8o5AENVj1o~ILj9W!~bXoIN1 ztd0v^fcTd~F}vf45#sc|(!Aa^Ep)I>v>!8QslGGI&HAkV+j9%tG2i6*tLHA53iQ|8 z;vZLGOpZiWx3>Z3+taDO1S=IDC!`9;E{jl{et$dF=%z9M@Tp5AYdj9WF4ApWv1{PH z5@s#>VOOSRh3w+slms(=PmGGy5gAthRNl}t>YF-!`N(OLp{YK&J>v^mF3)GxCUJ6_ zGF#mY$LFDi3e~k}*lWJSa|kJ8{fgLVrh(wHNM9(U&FOvC!stZ6USCjCRA;N{3RLLD z_cdaTSYFQQxfW-jt1kXLWFNh{Iz-uj#FYJal9r7+#GcHgE|3~d*gzF+PpVORDZ(aX z*dQr-sJ=v4iAEn==fPc2WB zDWOnw2+I@2nFS9=(%(eW%o0j2P>e>L>i*8@n(mtR%J!JEZM>tdxz^Sf?i`)kk#t=rP zB_wRWD*C1b|JmlvKTAD=I+Q2AY&cK@-)7CeyMMP(6NQpmifY)Ol(Mcx>&T{-J|$F_ zaEAG}R19xCbu7b%7lpMkY%SVBb`0fDN;{ZF**h^ttxEP1;F#;wI4;1P3OWL%^{#8% zTNew}b^6Np?ky|oo3nOrU#`aEPq&Zx9p27bHMsDnQ;PzFKH-TmQeMAr%4;-DrKM|9 z6IoQTX-(?FlGMYbdW6$VyoU9SbiA}W%^2QD#(;?yy*L%GVavpui9vtclZiq6&y2w+ z=uVZ(PW=+G6lgbQmx~OVlIzuc;;39yKvjXtqP5PBkXwdLD~~EDTU|?S<9Jt5-@@w$ z%e_7IDGqj$FByAcRG7{KH~?RyX5}F}Y$gvoY5kgEk%weW?4)IAQn8R^iTe3#hDzOO zmO^2s#Aq3s)Z7f!xHeg0K?79y(B6RMcNOFB)f>}gFLTb2?sU2`=WNEMWu+^#$|g0N zN3nxUs=+#e7fKI7R;3kU^_K;!z5e|CY4c)jXN!=lwVbyK)6~fno zl~4>TE5pA3#eD}{*A87*b8z41r*3pztrx5KIXV_Z{ZLnj;DMPl;$H@@jDa=s3)G0r zf#1wLm@$jIn)JijbV{K~e`66{#wsTLZCQ^1T~UIZ_?VMIx%PxYM#SZEcpNSZeNOj% zs^qy#AF%&y;rBmUcH@(M2hV@bq3V8C5&xyKt#~p%{ZEq1T==C&5C?pju9&R&LhodO z(T!5E+;ftO|MlEY=GtmRy?D!x<{`Xj0$EqKfCiq`sM9E5Mwo6<}di5`SG?5`QyCIge2%6>VA{zaw`OQe=4M z`wcVSrUk-SB;O`AX_p9%U~e=A^^Ek>pP}5sQm4NJ%YG18*;6sM03PumzHuSzFZ7CbcjV16zto z%}r8!)obb0L=Rt09cI?J=wUN7gfJB|*Zv3fH9uAMPnBv*+U1GG}F_bLHum^qst_dC0SJcyPwMthTPb zrl!4)_{Z&2Rc%3AzAaqs@YYzI?r=wSWL;NoeqO=)>iSS!X=Fp#QBqdEX;sHe%VvkS z!rRmYaHt#ct_pmGRn674EwXctnOn%YUdEP^a7ekCROpN(bzw>B;S5#g0nM;RQ5F>% zG#SI28LHH2GHfoXZ7B8<%)bV4N+;?Er*$4;oeKRI^tB2-WYTf}Sk$_3*_If{`O8uF zL*{+)&E`OjN;t%Wd4Od6nRrgi#ABSE703DQ}E3x#$t&tmLX1$Ojia-Vo}q_YXI9MN77AE2;0+D?E-y zpS{jrQm3wJnT@nhH;oPTj>Vr^5p?(Z#wuIu+M`v?RSg|gNUdC5t>*AP3w^y=sil3r zrZ>b)=yPq8O-+++ZBtm1)#j|X+v}Z9H&9*OG}YF=qPb-S?lnzSgsN&9U9QHOs!)ZL zfDPIDCh9Fue~~2uyBaH@pTh4K_qALf#V$Lapq*f(;{u*x z-=bHnE7)TFWwClTvS&|me5LxK4=5$q4jt9SykO5HTBzn^d@3)=K~s5!>X<)sXz0xO z`Ll+G&YE8_KfeNh){P%O?X-_?G;!yli!M4Oe-iJpVCt)g*POAkyDXRjvs=K{PXpJ~ zeWUwXHP@y0)~?vTd*S3Rb6=MT9?QWKUi7^(g_9~o^W7k>J}@j6tjFHw`H4N?byjtF z>U!IY*V!j_^bKt7wpMsM+;^9&jcZ>o>j-yMG_+NEhnl+k*R^&X+vn~Gd3o=y{D;oP^xcpaD`GKO=**?$mQ?29k(LhIqZzvRs)me(ItN&2HyD?s!WAO~EZW}*&NNNc) zZ~7?GhJAt6^#(HIkzE+n@l`M9s4vE??dsTddUsy@*G0QFt54!p1w0c<`~})k)^SVy zm>z~~ejSJ;mMJ96VW^4I1A`q9yU|c!D1?DksIN(#AOC^VQ)TTOs2SNaFnWe%cwnqM z=pPC;4hM3}9J8uvx8wObtD|^e-`K=y%Ta?OQC9tXn9t|{x8CHNWwD6Mg7>)p){?}U z?oG=BCH1X!TTaY5)!osMU+HL#^t$_Z3@kfkGPKO+9}F~&`29nH(ak+IWAmFjZ?}Fe zvUQDTZ+%BY>F~ZGti0GA7;6bEZw!uvn#V#YgFzI;yC?&(*tsy@rA}AgBJ4-;d0YIq z`ne6eCl(H&Cy6E&bQ{8n_jn>D&v>&#wrEJpwXkmv`ja|A+yYbzNA(&Wtc?e>iV|!?5^#s_e9+8h{xSortuzT^8xPMZjC91U7s!P<3`p&_4lS;*h( z@$_2N*Vnn*J@&!f15^7){mVCWR`pG78T^bo7E3!q*aU7_lW#Bp{gc!S=rQ62eLH&t)-qj{l{Jj^$3H1yn*oiO zN3Jt<1?&T{pl_9kafNo#kVr>oZ8XdlbDeQH;JwZ~rSsH$tM z4mqpa>S`k`rOOM(Bg-#$IKIb2cNYb}cQ^oM)vI_iQ0o{{>> ziiQSfWdm{urvU1DBX-5bn9RZAH`ZTW^u?!Z4i%{8`tfl5XDGkc#G5J#?%a@#p0s4f z;AqY?e7qSLN>9+FIgH`0LDMr>Uh(b#zq&)e%MsV!HYM*pDSLpOtFE@Aw9wjAQ`cTw+g@j{tIRL7b=B5&xrf~qp|0IthPtZwec5Y9Wo73Y+72Kdt3e47cbZ%ffh5sD?@#x75D+C#cU$2y6`C@39?9_{?@3VH&lMgMwa|ls-_f zuL>w|neeH$M2}jp-3bb6gki#o4y>yDFeoT-QhbSi)vP@TN-X(Qlret@l-^{R)5rsY<5!tGOxFv9cwc&Y<45Z^ZnKtVaH&w|pdKA{?o zLQsU~Pk_>gr<&jmF?p7!+7M>Fkq?SU{wF~RtGiU#&_EHM9{|Ot?orJcZJRtl2uf6a z3Nh=T2+yAarB&UbqDB!Y!n4HeLp;r-2+#MUZIz>8uS9=oNWU6UDspuTCF^aK&{rOEw7Tz_rx{Vj4os_x+Za@_yD{urL`PCTQIm*@AG_iy9< z!Ni;TFO$y~oAHmx{XX@X)p}7Rv?Ij|Pg#9rFHoU3+OMlYrD`KIc9F&;ZL#KKPS$&i$ za>V`Z>d;V|yQIFy+c;A*({j%8;oSo@;ju>h>8uP?$bVdKt*Y~eDzJM-EId5AqI+|% zXSlc3w)rNrnnF?@6^S)S*JGxuTsFKLTi&c%}4D9w5L@Myo>P5#xf&Pj;kIC34ANP`Rd#=Czto+ z_KZyGXI_#&xja@FlS}OMSdYTF3UQkIY>KBC-rWF3W4ZX2nI(1Fxtq_8AES@O4P2Zr zgOr8wN7k)-M84IN>(&WpWr+)QJ7dw{Cst+Z&Ry|6mm4F8AD6qGiI2h;O1VV3rsB)f&ynAW*Ac@7 znBhVRC%!AI4bl6wB)*oU=&A=iM739;sn>`;lX_v)Y3 zd?wtjzu&dXq#GSs&+C8v{ch3!$?$mo0C~f235Va91YRos#PRw?iO)#HGr+&ySsO z^2sNBebr0XUHhw5LsL(lamJHVlDl#|HEBMT(pK201&U#Y5A@>EuP1{K@nJmEihlYs z)LsB7VXzc~hJ&FCRTq*C0x?zZ!VcDAJz3DATxx&UWSdh(I$GK~y3{ed%38Y0^=Mc{ zqFBe$@;z&P`$+R~{ma!VH8ODA+Re@hTSKJjxc*fohJ97vaZTX{h#=nMN1CUZX}Yj5 zz)T9+MB*6dVu*&cTrgoVI78~qWi6e~R3e?NWs5lY-jOMIY!gRvffVNxqo}nJzpvx(dHi036|i~w^@uBh zbWcLM@*C%P;CHg$!S9nOXZWoiLqCLm0&;8tn%<#C^^AI0e+~58w0A+jP5V*eUEv4x zkCJ{n!{4s`kn-QCUeKP?|1ABP>A%7l87dOm5^ED6DA(4uRab<%-N8_}0;2-2dI6nS zb-2}A&|cPVFD}n7t1Pa>;0v;*o`GHV8e>|jXY5Z!QDa7_o?#453uCAYdnHzIS_muW zG4)^Q<36VSCwR=mx3sKA(4Qy$F70X3?_v%RUi&TR@Cd|0QE0}P>r;2%HGGabC;TJ* z$8Dc3{IqZ(0B z+|=W7`I8tCR>P(b(y}FFART~txKKTY-p9sA)%M(J+xivW{%UuH$JW@EKV_TStoGNJ*~arNc5kJ+ZElslY$V^()EYl!683tG*+e3FZLWCt?g5?VuC6tRr6 z3i74yI`-Nfk##qH=d}3)Tf0J&+j_9)l|{FeM8+Fi#)96FjnVq9dZV&>PsAv!D0X)T zD@M-SaKil`7!IvGb+Ti8C>R)6KV9z~Zp$@t$^%uQkzn8x(H&Q>{lGUan`m2q=H&PV z$Hl5z>r1?4t!x!0TvxZ((%t6v}=8{bh%qaUmrO9?iwA*BeQvX|nyWC}I&? zjy}Al^pUD|>~XejS=(G+@th;pRNq`t6>KcIw(f@bKTMr9aqRk$k)g(!?zWl1P{G#x zre&*--%I3~n`6uN ztsg+wj=mQRp8%bHqN|_s;qzCw|N^j4GuHHT4YQrg|KWU{?bnpzvGBQsrr(U_~x-qc>z+-vvOZkt_U7@g}*46a#G6ZUUu3ip+JU1v{@H_gSY zE}tXVa$I1%rG4{(p`40_GMC#LG|FKp21h!o%L28dWmQGZUc0+8zoufYuWQs3f5+8S zz1r6j@Y$=&Eq>>0U&}=Eq~UazR|bk|tc}C%k<~Iaq51J9?jJDra6pSp9xd&mQ~`#M zdZ}U5 z$D;##XIoom_YNe#E%I3Earype&-TH-?Y*vw8Jj)d+vf}PH#i)toE0AmK7fT8Z%Y}hzG?q>3uP0R1TvMe}gZkjFEjq z{^50<9qWeSon6=2KGW7V)84VFt!>qOAlmw+Q$0;B^;2b~UG@q`S&u^*gC`7ktX+ov zTi0~R_i)R~wzie6t%5CWyKQH@*4WU{RIvAerKG6X2KS8tj@RoiLQa$WjpHpAOiidlt#A&^ zTdg98-gHyrjaOk*G z1{+pi74`N695q-h==YRZ?L~QY5w9)aEo|_vwvL~>s`JFX?IRmI)a+2_X=n5_&yLmh z1$XraW>-zu*Z8WtCR^*rmiM{3*S6c8mce?D)M~r-ggQb0G4q1awB!bRyg6ljap#U7 zsowbaRPPgd*}@+_yKdbL$d|6QU~Il#pTKM#JR{k&POgePA6`E-yO3CqDX127aPmer z+Z^gq4X?Rqa`K`zbLUOxs$y$=Yi@O0f5YhUev7rB*f2UydaXbmgWV1WgIKOwID6%W zW3F5^e!&{6&GJNEMU}m$4?9~M`8nhLYQmaxn^95iaC`GGN{*lro z^H)dC89;`Q*yGyxR@Yo>+iX`Cmj15(Pqq0gRRO0nP=%Mjo&Lk$SYiWgbwb-*7)yjZ z=EGg9+wR-6Nz_VtTiK@A1Kf$J^BoF~4-NoAt@kXGf?4&s6$@Vyyyblh=32jTqWka{h_An2x#U6e*Q!5b zR^HTwA(Rg0*|N%qo&t01A9J~~rYPA5(V<1Q=)tcVv6S8J^gwQDZkGZTPd&AG^<2nM^?{m$0zE$pZkwv?G zUb~}l#}4cGc=nE;w%%jM2iri@MLF?nS#53Hx_QSOrceXqJ^w z+5Q$6c)|Kp3?Lz0M>k*D@bO!X6V1(&EuLt=;@+{N+}HPy>WZJZg06~SC3bfy_gj_a z#?IB9UGp7vJ%Jk4xbVWMIn_P>8|UVJS=~}q(^6g4Qj6(36`2>0LJ4&CYMf8v2VdAJ zBV$QRyF1!M4#0GmKlR9p3pay5g)s`~4?vCV{Ucw>(<=(mTfdV1qi>c;q~ z>PBn#ahI=|J-8!U=qy=hw+APW>l@rL8OSd!TwmfW{LOZK+fCclHk1q8Nf=FJd400i z5-VifuZsR9b|b*^Gy3DKJi+4S`4AYTOHV6jL?~#y|Kd3j^N-}LOdS;wzb_%D zMZ_;Z?zs5l%&43gp+>NOKn~_eUd7HkPocy{v~gMgA4`s9MbeXlEy*%EpVSaJ4^Cq= z1feBo*kBgJm=ZN6J)itNIa5(zR9;k++q-9CY?o_giNDDe=xcCVt>t#__g!Py8OU#Q zc804OL%Xolzs1>EQQKSBU4LwRy}C8NPu&`I7EQO*4i5%8y`^J&Vr`ARrOra{K(KyA zoqNLV?u+d$v*cLw^KI6t$|`G#rNmygyw?4~h7IR#*dXn=7P8oh(vs8ns?0GY3Q6A9 z#OTZj;mC+w{QbTmSh&*~oEmH`+?q46<@6tg)cV%=O@h|kT$I(hzA|5zyE?R@&-?Z9 zZ;dtJPc%FFOZ{fUW5%7@#R11ia5n)KmR)RtohuHk$!r^W=??Wd?6rwaBIEPw0dt$u z_@=n-TX;_5w1RE%F&4`FYxa3GsNEy_S?hMMt~GDl*|ZRM=PcE&_HVOT@IU_4dv>5w zMv{x4Qlhw*vnT|WI=gqx43chOY`2AI! z5MplmZHvGBfz6w5-?r^oTYa}1JAcE&XK3Sz1pEGKv|FU*K$bb&z<2`*`9fS^1Mh+Z z%d5ozzNhJw);?^GeVO{l$9A>NV{9?FrtQ)fPkZxssz_O4T_YXv7VO(MQrk5aYMCAM zruNSM!sg9LE!B!c*l-Np80H-~PGfiVevSC3HZ1z_$(fQ$n~_&+eV-=WFcWAD9p6>g zxwr*Ko%zA;I$N!;)%`vV*j|#|e$_^4y}Im;!d*%WrBBP29LL|-v$XvjkG{pf|LU%V zmpjMbfB#Z7y3J<8|Nl+id%#C^T>Im5@AlQMq+My%SH1TJh$zT9(@pEwA7!e{cyc@1?q#*N z_5u=_ir)L~L+v0kpE=6Z^0h-SuUNfC&irW_^Pu^Y>CA>1%K+worO##_Ohc(e;=~3q z27I!f3$@O*x4d1eH%CJz!hB-=p2&2VwZ2;G{~C?(0bey*-@^6lbG3T{=4<#cCdMp!;lBHRz)*rzW)m?}%yjYb)ev3C6p8Nnc;-p-`|(KfTzqlP#l@Fa z@I5DH&hh0!LMCB8nIvKUfycHz9dCZ0c~X37#U)yp(wmNdl2|D)QaZvyWE3YIWm#@a zj>PYr~=`l$y?@62$s@oly0s1*VYNMtI_zJQXa7(H(GuH3NUEoQSB8>&>MKVb%$ ze`BqZ3g*yT{0#3d6OzXe)S?D#3UwyO{VVfFZDPDe6%y*G(J_nklf$&}an7oc5Vcmb z$SWyiygxENPA)Quv&zF&f=v+qvztE~G2L(PSbso&g_E1iHRgG`(?{13Jl(n=y2VOe zb4qp?^?{kkouZ?h9E1GiT9-ws(^Yz#v#yup-M{opO7crw8Wp+3tV_g|O-mE~5|jMD^oX}EsiVBT zCcA&FPe_aljNa|;<&zi`l<4E(u`?jpDSqAb8EfO?*Up%}F5WRDV5g@$|5q>f-M)d2 z(4;_17oLIUflv06-yTFCEOlLgMbCq8Criof5~r7<%fS`p!>)2PKM&=yBfgJJtxIHEajDf=ugCKpMiw?VrmZ@rV!7Cj{#rc|@j) zPYu*X_(^3SvRloU<5K_ubY~Gsqn1yM6!K^+$b#b`gte4{=V?*XWFc}eD8r@wO6}3-sHLqRMOM6@Oa(pyA@ zlk6jih~|hEz*2pS-p0PHM8Qg?gvpplcl>q9r z-Qt+}>ou#`rAz0i=;<8QoTXcSo%*&N$3D=3=->!C_`D12q=PByR^~6F(li(_oW`{> zxr4Jttx-FNYMfmYToD;@)N1gI!y#>cp>$Cw+#DQKGKE|zPgOg__}+cQVkU{+P)8Me<1n@ZClr+Lfd1?H%n-B<~Wk&8~*)hLS@McHjDX}NDSW> zd0p@t`1CUjby#})XXZiSa=LokMTA+li|K6dbbedG{sy>?TXA_?b;OP#X$Uqtg5D7j zeJQ;EmiF9lY{+cyZ=(~jm%!7w3G+uMfxW}+N`&mkT(z6!a8Ew}e4HWp2W&*zZ%PD? zpQG$+^qwZRXBdvR*#{Y%HwX2E0bNYmj@f@^AAE4-?|^^E-{^gB-v$18Hv3@G?^aSB zS0$TP7}f!%}mHjgDUg|7q%THl9#74sD*Ywh3!wtxH?>0DAKu zZEf)FFk~mwz|3X8;qzFigL5mxlTMep9*&+)GL=>ptPhCM`o}U2kz$QbDV2*PS|>N} z$RL+sKQA;wHbAf5!=1xu(WcQh-4V2(mU;rE-n5s(9;mzQ($k^8^Zi}u)9gbSRSN^2 z2mRJkq8#ADVwXyWmc!n(oqt=MD4PU?y8p5Z0c}}rEcOtQLpI!+47VBV(pB?SVX?7c zs`+$>?oaFn<|$Deq|R#?Z4_$>K1PMvnC=-{&tDGsB>MR#>U|S^@xM;5*Xexp>;@#G z>*MwKA0}nGw~Nlp+tme#7>v6onGe`T`W#`5f-$Ta6YJ{j!?VyVzd>pz}0OY8~47hiDT{+%gtq zirdHT&tZ37gYS%SN7ukVXM9*Z8;jQ9M>}p`u$HCwE)cRAJ^yp|WsKktP(v6sblZec z{A%fj%c$J+^3*@Q3j`y|QQVXV;D3{n`tst%bTrZ)f1h2!Y!K<_%G6~7+g?4EO9h7wa~vo>u5lX|JEMXr|>Y+?EVJ37Q=ua5R`|V zuq1O~g>=?2L^r>zIgz%#0JC?JPei2JL+$CTmMgWP?1LfUI5Flbj$}1%4oWF2QtLcC zf#+jpH!>ieqU#u!Nf<=*_K%Mf<5vdV!|a|tb!rkW<4398IBA}0`Hsd(psjW-w%OZ@ zHkG6HaRti$%UTxm%23-lROfHgY&!}&D)5M#Vdh${QXZ|@m=jpQ&e04YL*B!!GY=qg ziIWBVO{_He0#mz;Uv~Uc=8+s680n~9Fg+?UF(_qD_atXem7}v<`9g*=KFBNF8)k|j ze?n&HlO%#hKp_E$z%Fns|EcH)^ohQ1k+Z@B^oe>GC;B8(nQv6CPn?fuM4-1rgw!WU z>+H(k=0@?Yv$!!ISZLIn;v3>+4$NE&4>R7|J02e9+QuO!5VfAgO*fk@@6oYCvv{9n zJikTC34>=X8<|YzUiv$Y^8J!g8P~73k0>$n`!JU9-8OIHej@94+dL;_dq;flvwpW} zv6LOKez(mfxK-Br-8O4Tp}+i?hxZK2j$0C}-)%M4?X7 zTVF{<8os_Dbtyfi4c%JC_A;M~em#ND@(51p;Vgb&hw#q!2J1b;hXS?ER$N%k(|MfE zC>WoJpxJeMsNb^3XK!4Kfb47GUG(3{&#$i=ij;l^4?K-{UMhC?sn0S4ztLxe?FQ|s zR@&*TXK!cVHX>2}UX=Y<)D7DiikoNYlaq-R$0oLmc@|G$f;g={%kr}cd)cnV>z@by z&G_3h{NE@q{{qcy7igq%Th6w@XZhI5>qI_F+X$Z}fo)}ui@rcz-h*&=2lln0*$V;z zY-{`vPw>V$Tb_M<9Cqc6*Ex2)<*(LTwDOeMmM?!u1 zM+077_;SGO`gf^c-WB}lqrs_hf?w{BI#U<#fMx8tI zr++VCO7)1)Xg!qtN+nzuq*Z$>9i6aJaSaw4c*#*Fr;C(`nT~R)16`!V`GBt&w3ln; zD{Kf~6U;BmgjQdcDim5LCw`S?T|0QHT%55=<9UjaYw>rLQiaF73A2sP6X*LdZm24d zwQLXbq3Cylu=(wA;D5cJh*?F8EZcCr0 z^7HZWQ%y@hFj_a;DTo6FcfT?pM#svr`h2M5#_M?M6Mq4p_?0{JiTx6N^oe)`vRM2*)QM|`^NkD#QX9-vAc(tj`xX|hzRqQ==otjF(108(K;Hrr+xx6&pi&$9#X0` zOEaQ%;VzEe3P)#ViAM}fs$3>_ahW_FBSh}%tWWl*)_pOsekpc>RZFpYgw#IL=h*VU z$MV0!Vn$$fVgKD~1yO#8CB0YV0_*r7wSv^kyO&uka^XG5W%$eI))rfSpz)81OJhSXqdo59A;OkHMe?*AAYtVy9L0uKC|Qx@qiKI z7CXpv%_D@^KV77VnG+G29xLYuFWW}Pt1xy^^J8WUbMHv+E+%?I)N*Fa%BfRv(Gs;D zJ1uJXS^0PBXLXJ4XT1wQYs1)n)L{y_p_9# zRyQjq)K{5gce6Z0sKyCrBan;uvDKdtPMP5Q`_Mgx_#@lxP25)^SVT<9@a6bReBSg< z!WncutMm5Ov05Ag$N$VMcbyCMnrETj*Frt&HDl>1+yOMp)!R$Q;MBEW0;`?r>Eh}! zi$P6m9E)b@K0~$;8haM9bpM-KXa15>GKYB%`MbGRokqxg&Lh~LqJM&)1VDN9646rn zO}!Go&=*b=)4RtQ6<`|RDZt+Wxc~!9HqEs{SvC`}15g2{2m2P(mk|9F@DAVv0G^@P zAFvGYTfkNT&b3Iet0qYUJd2|*xD-i>&$4xd$R7l}0XP7tCq&@|SO9pD5GBeeQC|5m zAr6}W-vLSpQDGNCl>&GQ@F@UWZfeZR>g9k}0XqTU#Sy$X&I0@#0A3t(0pP_6yf}du zr%b>O0B|}3r!#OmzW~?*!0CeDU4YLO^toOHmR19AYM->n*b=Vn8zBall^*@mvph4bVu4mj?j! zdSwB?n-_TV25;V=!yEGP{s?fM5T8T;DAu8=fO15b_QD4p2!*kTU>s3j&Wpz#RnKL4AY-hXO!Ha3_#TGuVcP&`D;#nRp9}zR;lLMOL`Y-~AyGR4WrRel02u(_jRxMBPYH=#O-P&@ zA@TS~ZKfVL;0?MY~R655{h4%RcF zgrv*@WC3aknTj^1qR!M80iOe|5i$+5PumIrozta&WWb|mrD+TZb;A28kK}QI{($8G)J@+>$QaIY! zRRmB?$Z8J&+F$(&0613H5^^u-TN6*n+D`#j2*OVQe82BOzar;b;KxKk^(Qk46&m z82aZi)O}n9KpT$(-{WZGakTrBj|q7KJU_7wfHt3$1Kt9h1px0;iGU{nXzQtqggg!U zpPmf(DFF08jrQ@8{4^PWaz916pI#;8XTbBb6NLOc1@LnKetQOWpLrR8ww^&-&nf}< z`?H|)*^dBu0JQmEYY2G`{62>|&wl{G@6Y4+7eLDk4+H)RI7Y}X4guN;`K2#lB_Y3> zM#zi!{Ni%JbAY!1I{}r1yo9!1g4|wu7VswE2%v(Hm)!tM0HE>ZHvpjR*XYYv@cS#^ z^A*tY%8P(^0DAz}00u&S;|7>a$ZtO-4tU!L8EpiPjVQbEJp}uJb8`j&7W5Az$EcUjpY>lL^@xNyyjF0nqMt(6r+apqY?wUIPIC&hvOI5P1AH zgOFWmgnYLF@GT*G{0Z5M?|YX4@Y`O{y7y(kCII-@3mW(C1OVS&;Mj{k*;@|)&VAr- zA86VK9Q$GcGXRSK>i|yxehJ6|yafRN`?diN06^ouYk+EOHKG1~(6s**0RFxo_z$Q6 zvj9II1yJq)c(McN`2KUi6+#Xw0pR6eA0B)Knh)g>a=0B}CgjM&gdFt(yaPZR$6Nt{ z0>tB;0?Hf%?qkOQz;_(@j)RWlkjZh>JH7=_2>{L$K7a*)orIk9CFB%voel+nzSHN2 zKsO<|D4RPM0Df{I(_G-s1&%YQcLrt8{uZzeaEOp|9)RZn2La&iJaC>*0jvf*O2`Gs z>Jr+xEC*~NB!4R*1<8b51J1%sLW;rxD*@o6C=ZYB0={CDD{ds@#x+7pmji&m>pry8_W>dOasYnoKZVD3gBH^o0PvbXk2wRY zh*|K$wS-|_1(Xm5H{dYr0m2{_&xj0!k>HjD=@r5#RsyyXMmYm;kuWOUz@bJN_1lDT zgp2OvMi^%m;22>vZvhSxMjHu0JuSX#QO5;n&o%$ zoOeHZiyWw_Igo9oR3=a=6DXBYO4&M4wJ{TiBEO(-HNdlRoYJ+!N*n)&rR4%8a)A;# zr9@Oqk#EWrU8S_(-AK`I!XF^z(P{s2sQKT=Ey%opm$_*IDPH4cewZ(9wwE45iWE7O zBE?RnNYRfgMXHzR`jb5VUOWEL1`>`;~Abu?F6{*lt+HN4X1k|N`~W}sB|Sy_t!k#Hz%N5phVEZTeuyB(di(JPKR5g zlOxWsB?WYVa-&jBVxRr%vVPpE^}uuG5ul)9Ki)qyR5)y=`}E!O{-pFNmH{>=RBXK7?VC*2WPvXZn;&KlL~ zD6CpK0D3T93}|a(CZ2yu>+v@8UV)=~1aH&f4+FfuYSJ|Q+H3hx0rm1>d7 zPy|$PoEN`lXceD*E>5qi#zHr zA3Ai1*Nb}ux!fbjWf|lWrqd`T=n9M3!kPyO8xkF$V!O-o&YU@OrK(q?^bF9mjKql; zIZnwih;<@g1TW4tI4oi6)Ts#pDq^^qck<-PvzMK`lY?9)lZizVxl$@srKcx( z$-DCp?%cWahx~SngFY%=!6IPkz-0xP2ThDbj2CuV<}O&Ze*O9-iO#0xOMAci>Z@)4 z-fiq3%n6J1Q&}+Ao1~s$AwdyI0}6duNb-^gpL*)4hwhmc8x^2)Or0?)mUwZTKg)_G zN+(CW++}$uT=K7x3u^4^t3m(_vW4KHLCq%V`KdtjlC!HNH3QyH6xA>_2C>( zV2E6;?IjBDXbg=R*?N_#qqefHwY9bGW^KowZ#w#16XwmEm!RwG`1c;tL#vw21UFf7 zjyo|B4i$A1b>tijfYsUh)>da%KjeEPM)|rruTOC{m0yI$U#u`Wr>rNDLt71BzI^%o zWF2X`upcT`G@kwIB{!-3dq@d=izKUs9v*%E?rlbKNWZ5ZxR%VQi$XEdM5Nb z#Aieg;!TI%;KzwXkO?*=sP9gwC&8g?4u_KXCz8t<)t2+K@mN?#*Wf{(1`|(%o1KP{ zrTKZHm*i1Wd&nWYF_D-jJ``xS&9Judrv}ZLA}lxaIF1;hOFhM?vsb@A?GGMvka zC>f6XR%zRK9_}#@(&8NHzmkRe^Xyu8z-)X?!(CJsXy9qp@tJ*kHU>?($@7M zVIh7#oY?U^*~wd&#|3PU3E1fEKM7*1AI>snlhJ5qnUDx?$zWIcWq5yi<=rCJ=;?Fj z%*l|;MJ#+j*f$X|aa^?7XdEOAcJSdelF+a?%=fYW%E8tf7f~<2#_SmB>swRP)KpvB z+B=w&&|@%);1aSXLr=fKU`j{~R`k@KJAnCmU+&FLml>-zY}l}hVZXE`oPhcXrSA?c0wxg)UjVdbPzO)&_)oNH->kdRjZ-CiV@= zU48t6!dv?kE}Ee9`{5?8pB?O`Xe~T z9XovZ@YynhL>rxc&pr1noDmxq@8~#v`gC6o9vQ>WUebqo|4#ZaKg&_OOZ_`jCWH3@ zczMWHOj|ZvgSzy^u z&cvVFEV>pMd5s@~@q&KF3;G!k+@4icx!-l)+_tT}?)a6qw%xmni$DH2H}~>o@@LLr zF0Ms!RpJ_;Y18Iz7J1jycxQW-m!J8UvGmhVueEQ#Y%+cRc}dBpP5bs07LqKEU1%_H zQiEaP!qn7-n?(_Yg%R1FMMc{yDU>dBGkJ?e|;-c+rX*bFpJt7eFNlxzS z8XO$7h!muSQ{WcnQ;DK~sNXBF9j$SaN(WU%q<1ymH4EU+y}cf3r^_K^$cJ z_HVxVX4k=7vK>(!Ms)7%;oX?(_FOeATgFM2EhC1mz8oI~)7#nB;_oW%YilUj`}yae zfA*P@zGPA<38yWZOy;;O!F_5YR?|e?%m&zk2%Ke z;3g)vKSv!|cQTq<{DLaKIYh-VU0$1*8qaa*xe2@=BoAotCPgit9)&=U%?`mvh_N>W zTc^w`KblDprBv;?a3~W-NYuK1mL`)dA7PDbHF>^|q9DxBAy}}V(Uvr1s?d^5Xh|k; z&X;fH=@OLCiD-nwXIIPGoA7zxp`su_W#uxV3(_UwE>c?uqR(hmt{$P{MVqP{+k1HFY&ji`v=|np3RXQxU~Djf&#jC_IuGg?~u)$C`DpS z%3^lx$Z@!^&41SE(@A(-EotOL71N(~$zql-7xXAb=z(ORl{jdsJG8V>9@N+v931TH z>D4MNxp6HoFOPI{ST>3fd5O0}z48B<&wA0Hp#7f|Aqd-~9xJ$pzU z3ZFZhoz7spon%Tk{8l9T^@dkxlT!?v%Z05cv(~&CkA<1UfCQr)oRH=@(4h*s~g@c2`?%m=OxyOIl zzn8LjjLTv_{_6d?mKQ8bEHM@@i+A>XOyn<(!!bdFOMfl3wd1S2(fg%$bX)IduBp=2#xLOditZ zZ<8;{c69tUvP)D_(<{pMbFXbjVDrAV%XydbE?>SpX;Ojv0}ns?$U_g{wQ3Rx;>3oG zjCmOxuLE0=KfRfG`tfY(u@ByQ^Kb8N#uyOAIrbWaxS37*BQ@b5y40!(_wbtV+?{Ab zC9etU2{d82-rUlJ1%mw72=b?=n1ftG!Xv^ku3`#Hi?3Y)&v_VaI#&Gy|@6;xN8!^C5-u-QTFP8y9PMw-Kk+*3ym?!!2< zjz5cpAAY+}QpJ>`BhH;aclxw}A8>DzuOR)ckpHgiVZFogoe@;M>+5fiUc7km!nzIX z*WSAd;}65~=<#F6j$21%q>mZ0kfTFpL^@k)2GcF;EXysAi#Pvk--*-NbIHHScgSu( zNZx0jf1DF}kS+ti^0MuhtsWwY2uv+>YNh{*#3K3Sgt zBperFfzvZMh!}#=WX86R$wCl7DC-zh=pzxukMxlbc9iFx$&Qf2PeCXE|Hu_er9wgf zk$X>H{qVyNub%ELHxwK~RNzp7fjDy<-5;|f3d})jmJsbRrBLC zmX=HVw`WIqYb7SSMI_OB1;wR+yp*^gFGWi+o$ zM(Il~6=k_R^w5f_9+J+>`@jDB>-~8h5|3#s9vY#m!>y1Q{KEXmK_TA6Ksw$kPc*Ew z*N<9SphUq_;ynTGE}oJuzO>$6di40Jh$2T^RZg+<(ca|oKsi%JV#zi*6L|9zH=4 z5mi;?*Uq0lU)Fzz)*}jzI9{fnjt+y!H8eILEC}nev8>5duUpo{6%S*bmOg9Rv}rHC z_|kLt&wXU=yz#Az-fmqKav9o`s9jy12b(JEYO0!zlK*Sg=Eu>Nadk_uk`w8z3$M3$ z_B*u)w`|ksxbJRE4A=5ol#D)7#k4p-#ub!!evErjGe5x?7gKQxHR%8pYSKYyuen(m zS(}8BwGksLH7+s&udpD0JXS!4DbF<^dgkoNfS4g8Zru4d6YaV;HFb6Nba(aiIw<8# zcf)l|%@^}3Dw^(iW=@Tbn=)m}r1}4U?HN8~430ZvXM$&UB*2uG z<5kw**VR;-fB3V{KKu9ns|6)@I+v#=guu-TPn^9ZWBID3^XJc>Gjqn2$;;-Y4jGl> z&heQLw|jH*z<@=fbarua@$hofxWS?J@Q|3AhtK{KjK>FszIs6DtF`E>m|j=6?mO)l ztbj$L)^^JscR@^VP*CTciktXwBB%NW<(*1421^1T9~bE$ocTeii+6DR)R{A9PK^)t zR<_=_bm`KKR;73Jf(=hT`Q(NL(O8IW`p-Qjr8NeCeF+~9qgpw^>P{G^w^@t{$Eo}- z$0;=*!Yn?dCY}84<8DIsK8R5`$lytf+5VQUt{XQxI&R!( zYddqMsL3qS>Dt<=3eJ#LxVtEV4KQ<-Z1Uu~I=%kvSS)9(C|t&0ud_jSi0lrty;f+O>J2omOgo9wQEQMsu(-!iq9fQL9k^bZmGI{6h!kB zrwA0=;>p-((>UkZQ{R94?YG~bJOjedR$8#2Ak}C0kb|g)vMnaQEIEJvd`UOaL|`$W?M>sL zL#SVGr+z)C&vL_R-A%>z)WU+2xVSh!xw*Rp8<)a*WTZvfKrK>iDw0;%0@_YkJ3-T)4#ZXJBp(zi2mn{=1R0@r!rzfZG=wzy@s+tECx=5<4$Y(1p zI<;@#zEg#zd-mx4bHCejy@^Ftg{5Z?*@~)44_~;bK0chfwFH5`vt=TEv{h%3&!+MW zMJ8vchib`^AAX36T2fJRiH2iZ`<5WOoh@Tn(q0X<$#!6nv?=Xry?M@_wK=*M)CFo` zRvXYV-o*A8`RJuPhn4o4pmZ5ux`4-hEB-z@?l!*kHNLdpkBa;5=q?{diOf#P^TODF zUa(g5uDq140m6#Qt~WLIJE6~X4oqL~AWKt|&He37O_jwZB4*IgT62}UQpI)c$Q!1w z1_Uj$63wRbR}c&<>%l!;o?gf}&}*a;F~PFN*w@?dA3*yW4+$LTYHO;iYwql9>@nx0 z^uR^yKf32yqsbFi&fm#cQ(E2F0vpp}1^FOIOg+4EDLPkuz)`+7=(+OV4YtF4j!(@z`i`U4vQ_k~nYlmhe4>a>JlNC6=K}%=ZcSA;& z<@c33c+9mt=39FwBTJ9Z@5s{Qkie(=TNync)|y=PdUe_&u>aCl6D#cZs&uz%O?-FsCI%AV>bLrX=_73UWf6_pf`GaMIzu;#J77*bWL(6o7}^HO8{wZ@i)RwsQ*%9L4iX2x4A z$&t$T_VycjoJx!w2{O>p)lbBIeK|2{DG>qwi&9|&pr3tihqhY}1QJ=ovdZ(&&%<)z%SMQvuOSLCEglfqq1ogIx;)e?)v)YWHZX}AVgz`+j=lc;pw zEiFDij$LKwhZ~LkW|77Z+=K=Mu!95EcrF4ogO;3ViMgMqaYY8~-u}(;2B~}U;&toR z%?}r~wN@4ts>C95M;|N2X*`8ePMkPSFVp&mS69cyxi_DIl#dp)4Jt!sz)a1VHdSOY zWl0%kaGtmGIcV>TS! zJ~biBfYVvC3-M2D0cPNWR(wLXp(WehEOv5pb31b6$oV?6YeH&jDjkCZ*cr=m#xWQR zsXdCN&e2->(X!Fq&3b$U8vx59-Ix-%T=2tV{7JN}wA(aHa?{-S(xcBZygiqLCiDv) zvP|uH^ca1@+g#a@vYB|M$d6fCphHCI$Yk9oz%Aw}Y2! zBmDoh=KVN*GP>U}bi7PF2Hbh=pc~xKYR?I@W4NA9q~%~Zxk=&=s+kDNMp z)`G?JU{|M4N{)-om^tM()wXH$*nw8w65mqwF*SUcy%cQPtsc5N%^IUWY4`K}X*J%~ z{v>YP(Ebb(`ZHSS&mi=tww*b2{`}eVc~|p`%PT5H-yg-|GE0eD0Z#1O`t_kRx#u=% z+fDzdD87_?-F0^!4`ioYni{1Ywr)rI&v9`2F{C)l0(ZmH7fKO9WcxgO=bX=F}-<3S7vm ztEy@pXgs+0z|phkD=I3haiFzz=ZT`co7c&|xh#(>$B&;syMN!-f9)^awd?ZP6W@Qc z=iA+f&gK_nGwxnFJ~vIDe7W`O?ceS@bFr|zy6lZVWOHwS@!kGIM~)poaUsp}yyT4^ z_8j>Z`8dx2*Z14M+56q6pM3b)-s2}v9=}w2;=O-v`D*L7fA7m?X3owDK2bmp%YrNWz%WUk{U56r*lnR zZm4vXRB<`XwfxucSZlHJ(+f9TzumQcJ2W?w7_yk7hd9QeHAjs=Q|0pI6z~ArMDEX{ z&p!Ov6i)pJAt5{`ZA2f)1fGYL76LI|6O7B+Llb+7Wnwz(7Yi>qTWTxoG%*m5EQOI%RQgY0iRh+D{ z^7VHsE3qw*DLQk{%9WgG$}Z$ma!gSOCkqK#N0FsZTol{sSIScskY*)79f6sr@fMGFi@Bd-Zl#zPjKIue zqBPlV`9a@VPZ?YDe1$Ch#vUOFAIT;(0bj;(Dr*9MX+B*+HuY!I%zJks^M1>=6MW*m zkaUmOzYvm`NW+J<#1AHftG^G>!6vDQeqsy`8s6m5t%bmiE(tw+f}1-kawD#unFZn*jaO#ZmU(3T8?ux!<$7U z2(SKLeBeY9jf0qT%Fi!rA5`iQ_tPr}JInL4BVAQuL|G&xgQj*mZo{$^=;eTSCZL{#r4(FUcjS+gcRh{STvxS)a&TNC^o zb-qD9N+qY08v6&#%>4ODuHv4e6DLj-^@v@Q<_mjj%7^(lkIfd*7%`%rEMux=jIekE zG%{=b!95n~_SRL}n031NI<-Gi9h*OEJDtw2PrABjpIA?)x6_soti=v#EPk?`P5IcPh6*)uR}xk zcdV-hzD}3Dj^D)Xbn>G!RE9eqxxstRM&P8*@Is#v^HD?TRox3zEwqwY5DJtpSl zM;@s*?uVYyp{cOoo;M~p8MD=Wf&lK!hTQ7QTimDwOKv;ePQ4QxX*Z&oOvYG?G>1BB zt~gSRj~-OonT&EZpZzeV#K)1|4xzp8gt>M*+DjE|cK^V@)I>a4Cq%6nz@AQ1H*1kO zV;v|LDYZJCPUEO@bdq4g7-%b}*%jAY2N*|pA7^KUyBU9Wb7tCWi}Kn!I@{Y@8fuU- zg2S*mo`b!e9Ua(D>UPGQ;;SYdrC8A97a?afD~VynG6^vnP1xK(*i54mlb&jXjVqeE zG!7!-FL(A1MlFADqjjzt=zKLUY{>{46sTiLMt8`iMi<# zc4E&}_l9{Zh>L?~%nVF)lcG@sufEQvdUf{9L6bE(r{6eu5R3k@KCvzqhtMP4w5tAQ zH5n93`db&sL5NGRvROS?s$eP67Q89^= zkl9CAD&YQJgTY|wZ=&}{UF&xZNy7qgZnDWRkd=gk32<(dN(YIt3wzQy(Wuqa8+byT zrOmjkv!n2O{(0o#TrQO0&^)}L!KRWXUbk#Ji9_emEOcllout@kh>0HsD%LiG+I*6= zf@WELlIGgVvf{!^XBp=F`3ske%Iex$+K`9X-f9rL`}_OrSVLnW=KG>1EGv-YB-i;d zgM*yDqwr>XAN5V>E)}_YwY+ms>4QL=k8-fR>}qyo$+e58j~(6qwb{IV`*-_~=H}lh zt%QWiOPZMgT+QWA8cU8MkLPF!sRmk!CS+1DMSJ@D3pL&76yqR0gn+H?2D3IEU7Vmb z)t}jy9l0=L{^Di#Jh;qke(bS~`3vUFn?E-d-ISW4S2Y(F7B)HPdNa<+`se`!J6yoQhW*T#Mf4BQo9Z`A)1`QY#xK;-!Fy74IT&zyVn3z2~K}Q@?zcs{Zf$1F9fMr^LudB2pup+v0CNq?mcC4w4c^N z-3N0lyky=XAtBzf{zhcpoJUd)6X)FBf=AnQaFYiIje|(#XDJbmzObS$!O@}EejFU= z=`a`vkuBT7Xu@DULYWEl#S7YbE z;I3UK8yL^23l}a-@n9NG?ur$;ikR5g>Deh-F&M=KD~_(NIycu7C(d52>?TT$Z+I+> zceJ0Ys2(W~^&;NZr-c{{cuuB^ixWL8t{m($ba%AUEXM&Z(A3k`R9mUU4!%;Ql8Z=2 zMv^OOxq#t&p@q06Wwf+(XA}Hy_25RHc*f1K*0Fjbm!5e3_8XjdCL7Z5kW}H!^8-Q; z;Wz8L{Xyt$EX@YF8{M^DpLT}|EP=T1LW!-ns@<8>aOC-6W+#Eo<_6`x1I$(fZ*6W z_|azNR*kSeE76M)HBDU@WwR=O4|k@v>gws!r_Wuhu59VWa=i%$ zPdOz9H8V(U#h{sU(`Z_d{?_G$*&5znS2?`BD@7*DMi%;*6=X8BG}KpDl$MknDU6JP zQDK_Pj{ke-zYkxnY!j2B!m1Wh$Z^4pL@KfvF{UkIg~Hn#sk0SUUo2W>X*qB8#RiP# zoG?rc7$&d?{fyEHch7iv<(@cky0~-DEd_&WT9Bu6UxQX6a>(X_MRErmEy7DidON$j z8OGe#m=D(n4pUe<9Hx2613mp?%wjTsA%4(y#X5@(g2s)ANsxXrM)bg5qn5AH@FUb1 z*~8XM5m8Ys?E>p8R!dvil*y?2vv2k8$oc3$psbkZ<%*3Lv5ouDDXY0fS<78fc7t!H z%+`*{*3Ou`T;yw%+iI{A)~MraG}>xR+>;G_4TG%)GhrJwd<}cw_f1%1Ol=uyIrtoc z8gxBu0Ua_3vZ@ed9c>+M@9~lJOw990DGmJ3IT*9=#^m{bqeiA+`!anoXPAb#5=Z7EmAGqAyX2#KdnX$FK=0;CvV_gek&&9>1mGu}#c;qYcyc-)G9i5zH z&6u-F+l+EO=CFt$dajka!o4_I!(@lIw)f(jJK4VV%PqUFHDUS)3-e%m>hlXNmhQ%; zno=wjZ``DV-bW@i_x9G*1Ox>5GuIFzxZ2IQPFk>F!Hk(w37aJ~n+66Mi7Y!*HrR!f z)Y@7cb599z6g8bepyE_%UAx@9)i~JGO{~iOSHk;8%?`U_!Hz9>-s5-6Y6+SuRM&`{UdVGyg;YG=8{(A?fb*8*K_ z9o_UoZ@C&i@%56L`gVG3hv}#$x41IDo82Xu$hjwFQB)3DEG&59{rM9i8dOK_KPh8?$dwP3& z4cHo~AJkZb5E>)h8kwdtmF0JKx7O8H&BUSAir zu^17b8%DKnDppvjzVHRP$r8ov^m)*+nK40*8b=qLdC@9yI|U@7cG2maop8IJvz#T1 z7f$*x>!?UzU-eXUhc zmTFv2p6Q7D6uP?`D+*~SqoScZTS5g{*q9}6C_IjI=#$8C$aZjZ6L;Q3G`^yfb<5VY zx369u>;!A!6g(9NE2okLz=K1Ky}dHGARHP9aZ~gPV_o$yze{S1imCirL?&oTy(F&y zJI|cxn{UWBxXjb~n_>NOq7=@IjAU2o;D$S<^BkH-c>Ge%!8*lqr8oZJCbEj;(dc24lr<1yCA z_I8>_O6*oUHco6gf&A%+60!xfGdqw+F`a&(H+IrX1xH)`+(|1A!ico(!8u?=W{R4t z@eC4dci@iT>$%{EBW5^Ok#lkVU?x%WHwTY762_6kNWW|{TJvlrVj3lcz0a?{*$l6y z>E<^QSqdl4^r!n2qrC=rj|AR_Ik?g%nDsVY^AhN^-Epa>bY8e(+C}Fw zWyStna*7kl3*q)Lahe?Uj$J*kQ`@S{|Ho(0Eyn5aCT4~rhka5mP9vPcY<~1nxz8g% zCqLov?EmG4VzSlW?KggEHt*WyUHVF{bfNy`i{_DGOnn*td@ezxqnp<@Vv)br=b1#YuMt37%Y$Kp35x&7gX$p)m* z(NQ!yUv;Pfz8X*-ZyqSk^EFo7c=vu9H~#y(h#Su)eOHJ8hIJT*}2dN8mSff-Wyyfx!lUA+S| z>5j=#h&4gc(b2&kN-?KkT|($*cLkf1WHf%Ub;rJA$B!O8eB{K*Gr4Dx%zpLCRX8xX z{Ki|<-B3h#m$6%=?5xN?yc3}aa+S-{;o2lQP79g{W9sbex6n*9){bKM=bCWw^eWoamy8&2UpQc*=eKO=6U4? zcDxa7fPA3xjUXRyx8_dU{lPZBpWYt~zyIu|8zm*B6*r1_zaN|LjU|`uet)I|a_%IE zZ`1AV5uX3o@cj258prd;dSP_Wf7Q62f2K7LU`*fNHpXmr%sy)xZdh$>1$B9?gDxn; zW@Bw5##V=V)FQQo6muIz-Xc1fMZ0MuI;4=+lor*}iwrzJmu3BGzH9Ej+j93rzBu<&kJA z74Dbh6tdA{u>%LMhQ)a2^g@qxBb?#~uW)WL&54Vpu$iL9Pc!*q@Wi9sOJorf9&-9F|p8ZVx^ zc%2`Ng;l-K9yRq)Du`{xorQ%~i#4i;;aJ^_p2+m~3-%eh@HU&j-oE?$BmB5LTigX= z9MKIIb8m?~Th(9?7Uk9+2oRMuGz?vWo6W1%tzW%}Uz;zROBb7JT^Xd=ZGoV?pL+(IeRFdeZ4e40RLc%-kK*M^Nos*@|E?~UpaZ=P&wtC(h%iiNtX#Enh6kxXv19v=6ZP0evLb+v z@d%JH(@0#b!75kekL=41a95kL*fgu%1LKj86d&j=s=ktcrCQ`3x#<4&_b-YhF*r2N zi1_O{6*7s4AxoA_^^|m6K79D_l}?H0)Fphh($@dBTzk6(V%n(%BCgrI{c($-_J=+% z!|rtmyVQNOAoJt=eW=B{jiP3rq6UGY06Rqvf{H?)>jf_$yppOs?0L4Y1djj=sTWhD1Jtz+v3 zFCBL~FOLX4X}c%x5m=Tu`-nrtxvPIrjBBnMD{tH=X&7((x$@%=S5unJy&WArjHAxc zMKShh)M7Lan#_!Y23|{DU1|Q6D|KUzO(4hEq#;Cj6!a!cw-7g9CyM;Gks4K z+!2Xho)0~A-;)22z4ri<>#EX46=j!T8opWwwwbaUTlyg8fI1CsDV_@(M0}Ss@ zpFS-ch6@JF8)nA9Tn~dW#$YVxELqWtEw!Z1Id@lAb>&?3{#|uSwq?umyzzIx`+e`7 zR##Q4PS|_xz1LcMt$(ex<+`nxUAMLQb&F~`5JRvVB6U^3w~VBhpWQ0HC?!DQ4#8(T zk{`z-1avO#C{}`@aP`txm#sA`VZDEl(rw+Kk7a5_uLq zSz&Mmi2%>!_(bo8iTP-7xbM{ap2;f-ih}yJaNpD#MRYO{2q+6HSFh9QtrY;wev=D@m2r0#Y3`CNkBQAj_j!rI1Kmc8lub48FXqf$uRTNT#Iv z3@tZV-}gOUNd)CA;JbKQU&GV-deFLjL2e9QT=|!mwTvQ2S*|E>#WMv(o-0s|(RyOG zD@xvSi>0#iQ&5DZ3k&~uN#M_NZIQX3mkr{3b36Z>M2Qh5k(CWJCFr2s2$kVQN(-;6 z{tG{jzv9R7UonpD7spVb(J9R;rKPCYS)kYH(#h3umtD24)TI-GnF=%(Q&EjpZ*vtG z)LOGjuVtcH%}VhB)r#br%#cDb;JeEsXU`5V;{(7?76N|CgrZugSQW)4MPMk0eoAv@ zWl?>tOOb^#e^doCg6SJ->WW%QikdfXT+`av(4dsvzXidD_^JP!+pk(*qK02rU$bKK z?KjudtZd)dTw2*$TwiCrRAr;8vrVhX3WlkDPe1kc6grhhQ86JkQQlUU%2SIMVN{*w zg3Y@>x5@HRnbCf6e(7WqxlEMs%(w#)5VEZaiPiu3&hTPLS%T6UPA23X>W;Y={DBxF z5eh{LeNGQld_WNdO0_;OP|Qf2SY;-9E)T|1(#z*yDL65bGL>x1qp>>8;hEu~>Cj~~ z#=OTrpWpr_jB*uCzjx|P-{_owIRL#h==07^jSn6_9u*hDgIgesx`{KT&yCca9p#CH zyLToG69+kviy%+xBZGtI-g|f7 zv(GM4Md-ULGe5ZR`RAYCHwX_p%5|3>d820;1`XU081qa-KARv?CMshAmsSU3=3F_up?Ah$PM52xMr4S?Bq09dY6>a^I? zD5N3*M7AK+Lmy>^w#CwGRkIs%iT8@hnArerzv4ktCgEA0Wsl zP^3DYe)icH-#*qiJ3YGqtO!b3^qxHY_Os6}ORCVD3gPm|JMd5K8$kskkfiMRfqp+o zl067b#D$H;geG%I9id5!J~eyfWe#_}|NbmZuG-Re1)_8+c#9z-URdwjx-QG6s0^jZ|>%Jgo2MW{Fvh5d%%lx$=O46cEWlt}7|fE5$;((;*a##Bxo6YxUZhnYgqRMWjll(W!$kyzs)oDNsce&f=*%U3pAE zjG(MDnUBH&YEGS+9UqyPA;1S<0OqGBNBa6ldPZ7Xje<#}_?;9OD|W#AwW9(t2_2PU zq-sbK3<#;zjYDrQEw#&J6e1-}qEOb~j|p=zQnHz+P9x7Ln=xZ7*)??L*wNFcPj(Lt z43D2Xb`&uQuxWP~5{Wt?v0H&+tt$YPu5s#=T^1~mKR)-zCx5qh?_XXxa^S$>*Z%a( zvnWvYpKPbDA{ikjie&P(+u)Aexu&6soPP5c)^FH!&CR#mx_d)=b4BCU+wQyXK3M-d zu=P#(VnVcAq4>97J^AF5e|-Jqg)4Yk+=sIksu4Vnw@_X50_68uc?-nFJ>_KXnqwbx zjfAI2{+gVhcrItrA0QWy+6KGv_Q73L{_KlSn8`h%_u><3FShD4dcuFX5A(S`4CeY! zeX$SU=6jq++k6LeU@fq>)Yz~)L>r3`fMwQ*5gsI!z&|a>U^rv3gwddrME%nPJw0cU znsVMZJu>FTyhx`xc9n#ho*Eh&8k<>;2sK7afmNfF3#m-Dk_dutEQKz_B-nLgK(3WK}CXI&;0l>;@1*Fvi=lm?MVLxSb>M8gDHVR zt%svbqtsZ7EwX%0hI?~f`24P!%pe*+GL#3sX!KCqVf4u9sFKT^k67^zO3ZKC`SZ#C zLd1_Qxi3JX34}8s5ITE8$CbV(GdzENzJ1yCkWETJ#W}16Q7#eqf8j~FJG_5!&YF{d z&XwBv@mJ@g)fAY!9aOw4XLb>hEak-Pl3lC$c#`k&yzU{KyLRyG!GkY8e{|S~!4gKN z`}!sVY2;B1&YykbjW=Muo12~-9R#lI@H0>R_O&wuWLA%b!~OjvBoleABZ2YpalZgz zj2eB=v*=9-wTREs(wzmE?Ksi`-{|m6(7Uu848_t^k>6j$RloV%Q@`8u=x<*iLK)nI z7vYeD3lT`g`TlpFe)?%_uNDTnkG+Ffk|(*%nTIofr+WPPH-Pcmf57L1&kkI;kk-0_ z1K7OvWYR*V)e)GVTFNLL8#it&jj+}PLmaB{G_yQBx)fTR7@zYlhG^xXLrQL~)Zi*z zRVhzSz%2dFk@0kTdGI(s4h8jCZh-3zE<}@B2tX*tdW*9ZU2*Bg#^9(Cqql*nZMVX= zvck;FoIbFBYP9F@Td)5GJo;?xQ3dQfb7%Lx9SR~3CC9uWmA;XqdEO%Sf!rJUtc{w1 zjC&StuVzYE_+E5+q?6u73Hvt$Y*wLyk{_ffGW)FjY|m$Gw0U6JML9hbj7%5qgB8ueQ>g z_|?a+raZsTNr%~7OvW7Yn`1?&C@U`=KAzL_@gCk!ceXcoZ~koQXL@fwmSj2C67|J< zUy4v5UM+zT={-%*15We|P6jC8NY9>?38S%i3Z70@8&3!UpB;hndSPTf7)vBN1(*w6 zHVL>HO#=n_`svY`h!{ng-+D`{7Ky|X>MfQPL_$ecHg@uDI697;?LNpc3XD~kEfx%b zt0NQXHH~(4WCp8l)25~I5CT0=Z$O{PAfudI9@DM5=9+6ZHCe!DSs1aQu=4xA%gTL! zPgYm(>adx zcWzYkBlO|i5;FuelGV>Hyp_!@VIqqyCwVSQ3BFe!w{k9f&1X#UeEvEeFGEdOp)#-k zt={v=W5i?Kfus?yy$GONfO1)b0g+le?>_$mAhu@zjDpwrPnyF{G5+m^M2bZ zc&e81BbCJ-tD{22(c#ml1#0i1lXK>NVEj8o7HJ|e9bv_?28tO?BsiUVF(UcxD}VZP zT-5iQr_XC%0M4p|E-|w7Ob~gu+bBuT9$nx1xcYmh-B$^HyoJ5)>p7qdnaxNBfQ+ zOeFT`Q~t30kAoxU&rXi^UywZYyWf-C+jP8*mHheX!{;xYc;#7^3UulFgCXjxT1%nT zWwX16wzW1;+b~K*DW)Xw}ps-nJ3%jH+t&o3Ovj<*|+%8hr)wkwYJ zcJqWT1BScjk;bh$$BKhmmC(ff&9Px>$RzVyG< zlgsk5Pk2r~gQtU^VyiMC$Tf{PKE^5+SaP_LNUeQzSjD!Teq%iKpr`mq|%RA zA`3_gI0k&=#f(1hje3!ArmG1hq&zXkV4Rvs8=TEB{2&uEf50^5Sba6IY_6)Y#wSOn zrsmuzH{YS29)~*vX>~{_nw$>qF{5SZD=Y~k?zG%eoy);P(N~i03SpM-n9=0i%yF!} z;>;1`t^peFGr2~=k7PbhBx_?q@(YYk&dh?349T8?oSJL#UwICH*%kX4x9`(G$Ns;a zc9(5iI5$R%7ssgTV%t7*dPj24id=kF(Zy$7wtWk^YoZsgskrhrOzs-y;x(UQuEH8b zGBRo|UQ>SM=OEhzx#s=({rzstz*!Ns1 zW8EiEZ!gb(_VSYCMM#o%11UpTR9aEL7GU(oRc-5AD&bRb*$RvWwnB|s9rpNW7@Ksa z0(k<6+L+FuM(z)V#^55tqTJA726j9oE+}2OY15{ar3H!@&Wg&BHyP2@!VHqU2@~N! z8qiv?D3O-R#DdQCq^3lswA5KsZILOoh0Cr~>1C9Efy=eHa^p=mY(S>{m8;j@vZXH9VvWi`T72Q;0x^#n3k!mCFnG-e^DVC0 ziQt@8gT)VE@kpwm?m7g^Tvt~hoH~2KuHN{KZ+z`;n3(X;YFoqF zE7|`{HCfJK0?~3SqUDQMl&1e5xkf-4KN9uRA>bpKj$^;hbBw&FC2!Fe5zUa9JWTxu zNiKB!pP>?NV;|uVfdP#G7W}+4%jfRSWv!V!{2w^+tI!?k^X<6?lq$0rumwgyzQ$Zu z<#M^*E>~5t!?lp5cfrBq~Lf-5U_S;#Um znKaItrsmn%rly(_hl|maB4vYK=(_++NMC>xBjjHMhSgbE&Trh9RRN}2rDeh+q@ZhvIHVjxnNm&i zk{UEhnUFepax|f|uK|>6ja``-J;@bUl~{2TYe`l8YAEfi8&HQ1lrtAsHm-%QY)w4^ zIb9%)NFqgo1eDk&=ya>qq?QYTrS(NPm-=a5_>X@b~ll8mBE+$bs50&pEA7I*4M`qVh} z;)?@R1@h)qPy;V=^7SPQ#3)m;{?>=Lpp*E~Jbdf=dI;0{^;hFIS5x1<^x-$&SWb<> zEjmV(-T5RKXKf- zbB{g>E+OpQ@VV_sgpLU5KX<7xS;xo2yLb2XedjyWgE0U9>PZnt-*_WNoba{nJpFd^ z^t%dA>oDn|T&x4lYK@Zg;$Sao$kCZ(3aMT)LT%xZzC9hfvlPw9v?eFX!n(TAmH{~x z+1z9rYjx}CBS*T-KINUa-*E?=Uz-X=@rjd1L=rJD7s*a(DlIgY{AO=B%ysDA0Gxu+ z6qav96x@wlsxx9yr$VSQXjOVg>(kKks^VDN_{7xA^!V}Tkp=(NGlK}BQvm0ejzXgm(CquYy_xTA9&1N3R94AkG}S-i zPKgYa=!{E*opdZF+Op1QoS8X0G(G7BNFIEHk#MXzL(LAIL$Z|7<+#WN;80VUIn=ab zMW-O?i*<_9iD)RE?xIyH*1qrPXiVa22MBPjRVGRy2>EMwIGs`7iwDk6rdScO{i9xD z_Kv-WUPYpulU~}e8u|Kf*wPqYvuhWt)W&B*#N8{%BruUG0E zs3y5`L(`bjV!7t?cf##`)pfVuhpL00zlQo6%a)7u8@F7GXSbK=g+#BIoSK&W@uhd< z@+mKPiP5Ons=&+mIbh+bV&Ufii82-f3G(JkV3^vPJsrYZZa#SWG)s*?B7}+Hso%4L z2~j)#`|tkYl^0%MsW%@{B@$oXQF_~LMz`pTU!<;vQAsH8i$wnNmuTJ&-p)TG@BO*~ z&)_sOBMDkt1=LBsRhAh$Kg-FE_nhb+oDC$B=^t>K@qQq~#*@ITK-a8tm3E3(u51x4 z1(F==rh1S2>4FU~Tx==RW_k~tNeNilfw%VVKR4|MZ1D$1#C=kykHByHo?lV8 z27cCcm8CPRX4kHrp8lCIkPR4Fq#Wg{>IzeV8keiY5JhxpP!6P!!kQM;)fH^oBs3IN zHLYxeg1xQ<;561uGaIf(!r09fX3;#5Hi#4r$>s07!%BQf891|2#K*Kg!1wt9p04+y z&&|*f^%wx;g-#oWhAvDjyGNFn10keP5`*7}qzX$tK!XhyS!M~Cj3t^XVjII@_>5y= z&s1MGj6#c)&8aze9;vW!j1EnC!v_wW9-R$Ip%{z(Gs7njaLr0xL80AlGbshBik>rX z?>}+|wS*U!5bu%AtR&VHwS#Dzid4x_07*wlx@hv0fZreVPM$py491q@GJEZjQ@ukZ z#%yF@YB~J$({J?6rR~_LSYy-YUVEBrHfY2o-);n1egeC86<4ikYb@63Tn&xQD>0_E zHj6xjY|tT@sjLlQduoU&s!$pmK@yPR zh@@a8j|RW<0XLblsMUz#>u!gAS zE?M{6$=O-0p@A|G&&(y4~%69`3+FtkvPyL1YL zQm8U4ffWlGe95{_of`C~r3JvL6iCy)!BcZ{K7qyPgck?5ex6u-8Y<){hZA)WynFF{xbQa8x$s`d+ z>Y1JkhZUAugn`tUWbsj`VWV*>4Y52@WRWwSQbwwlGnkrb76n;HdnQ;7rej#BEd#eN zRWX6VQ(S#bT|+~CZB0c9>XHCcC#KV}5cE6u?7aVi)V2eb z4xXKhifmOpt;9U7#Qdz!`xU+C*lJ1 zln1=e!#$>i_8X$KsI07|mWR0xNVXrTXi8TH9l}OU!+t!AlTMr%^i!nVWC6lNIcJqi zk3m5q;O2JpWn*(yX(1*6_$)fx1cjC@6e={vLWuW5BWmYT&CS(T4TXWHG_K~Ho@D3S zX6M^Rydp}I$(B^v0s)~^3&INpwN=(Ao6T^{DPg8qmRXjTBz8+sHp{BmcClo++eCsw#?$i}lik-!GF(gbYPO zXN79@(6Cs{b*M+=dZR{VCRl7OtS+50Xz3cO%P}!M-Q|#LSG29eYO|{7WU9zvkc%^9 zYa!ApPoKaxr9<5#Guo|YvLNfLR8m2wOr+EnR8$v3|LAf>m&3FKnySj6v6RLbxz7>(poY^F`$oZ#oqE&XShzSbU*Mp&@PahxmrJ|j*K!TeLBCzD#LW%^Mloc*FG&Zub z8s9<;$`P>ad&*6y?moD@Q?=n=`7qF3p7tLg4~1Vy$Zgf{0Lfa*tu{iWO_E))L6@ zwe$0`iQ&Lni~(f*;v&RyG@Zt7WN|TLvGDWhYQ8ns@|3?0tu>@P;SnZMKw6B$o;)@F%CUK#gScCAgKaq8hq^%cvj|fKiu}B$Fj- zgOWT&AQaGfRNHNQ&p%l6sVcj5RcK5wMe0;CMP`1INybCShnPrYL=q#Ii%yh)97u4Y zRLVWK6zy~|Vp}nmbbQpJLUU2?DwIe~PWlpJFcL}9H_25ARp8E2fh6t6nh>OChx_B< zW#4iD;yghMEnw(IK>(5}Kr)ieO)bSbT{3xN6V{t#${ck?- zNLAZ0iRDEr)?9US`??hyT34+ouvOHzY(N0WrWN&7Sn3sZE5Q0%QBZe9a3<6~? zDx0ufmJ|_*AtGhV9S(znfk+a{^$vbk7OH&lfUcV@OOO}cU_fXQ0oEu zga{@Ug#?=nBEf=@SSm^^6$#|KM1syt0Bbyyk-|EGM3ta_n1fgZ6jA`*DijL^og%!! z-oQGr)2FaIg6ht|{L3T)vwnYCqCw!J76ZVo%7|202r32ATWhs)CKFr6gjzsSN-y4* zV;Kebs4BCBd@jowC8(&#ER)Zi3SfEwka2I3SSDsV%NemOTb}~q#mNla*Eb)e(L5SS zS{4^m@&W`rSrHb-t+5$Mp<6^ZW5%R}dRuwxx^-(;HP+NLV^Oq}+01B%#a>Ln!S<|y z#a;w{S46F1*%bn@%xu+(WonDnfzfkVEn2x$th1V7j;0C<^lFlc9x!+$F-4UV+(@T4 zn)xxz*AK}@>g)!!JE~}@JSC7x9pyzuLWN4NQxavL%I1urg#slWqNIGt4<6)9B#dij z6rB&7ZId3%HbzRgzgB0WW2yQ1Fs%epm4e7TSDg~;HPNI%Y%Hm&m8*>gqYm-SG66+Y zv!p`$sZ=y&F9a*LTMb1POeVG2Ra8W% zrcww~rKJUW!jhpUmO?kUXk)q&wxjp|(tYT!q7VI5@S(px{GI+o-?e?{FUg1gTJ@p7 zK78i?-UUUTvSb%9(%OR+WOugP1+KlmIW z#1u;1J|c|#@!zR`$9qlfM(Tn56(YVLAH0I20ywR*wjMa~M}*~Dx02Jdz5e+7!^*cr z?*Gn9)RW}?H8p^PeNu~{!%_1%(|6=7^)}vhx^m)1$Z6DqcLaUWnbRW66 zIy$Hw?E5Px_ZJx>`@K2c{DbSZP&I!P$_6rh$n&9iThp1_&{*1E}p@ zP9YY12ab^Jn*$y(^4B4kQ$lI2gmt5OC)1UbJGM&KjsN1RfR>IC2fP(D;5k3pmi@#4IIK2 z>F{6xyLi)DOMz0X6vgI822LUTse3LYaIR?QEOB>;gtaEZfT{>|1trMHRcaO@N3dzg zv*`2t0!s@aAWQ|H%wap=X;JXFnM{b6?W0I#~_s&pC_D2eu4$hG=9GVNzoVC1m#oBf2rlzMC z0x?Z7l_HUarcVsrQn=>0TyVXxlBO{J?=s0ZG?+tkvuE1$0$-}<= z?QehMfiG@fjp?vv`z?RO!QCqHo9Gg#TiqLvjw%tV!Y^MG|y~}Q<-ld*W z-(#avDP7shYmwf$OrPQkzWTMl`~LU85BY15krGeQYSda#1^R=Av2(CN%nQ#Z_U85^4E5i-S%bn0pyfZ2V6cR7mG&eUpvxFSj z$gb}3BqfF-FpH}2?CiWJn52|WOum{@hJ+3xiFz`MDIUH!G8iSUCZ^M20^r_aLH-!mQ4Qm?R8?+gx%%mx{Sbv1VXTdT4GudtyD zQ_$hxIk)fkzyJN)=jO4R7q}W>Y_9iQFLVO0uDp43J0sCq>=h8$<#vt4C=eKm8sG}5 zFVYLBTDGjE7(t22kbi>2>Aw3GMKnCr%!$np_x82q*L5eQ`Y^)nL-d(Oz7}i@&YbC+ z@kS-u`NcpaC4p{%yz*Mvg$q;2Dle7By^|LReXtFIl|@JeClDccVHlQ7F%rX5LR6y@ z$uG_T%m%LJ>7V}m@t^^@TP7@6KxSy)$RQ&X6x2p6m)^f@&;<&6uKYFFF!*I&PJD-{P5gF{bh zDXp$Lm7hJGRN#HC%VOPkbr26)1;2VL_}Qe($O@pj!h9W`gZefXCWcJA-6%}>C$Y7d z^e2QyJEzO&o1i>3=`%~+NEp>kjB=WF>#7y88ImOby_uMzdL7SI^4`al{1dWyRkd0} zMpaU#$-oL22rkR97fQ-QD7PwytsOR!xF{+0&JM7$`8gkAk79bOqswY9aHLGFt1M|( zfqmXHrw$JdMKq{sh%}8Iviho$kSM91>OaEDMh0e(HY-?ES=(h*TIxh|TK$5!$s*ge zZPo1$@7(#V+uF9>1aF_EFBus|`fvR*)o?4DE_xB?g zv_NpzT@J_g?K0W@_mg+(ew+a9qmO^h%I-YUQ_Vk{)YcZ2TNk5v9t1sQMhn8@2 zsvQ3~ktg(pJE<)!YNt_Np7Qw&qxpLf&$}oZJ$4Lo`B9NC^z2g*1mJ8aQ6lQ@Ub~iR zWMS!lUyCJk0KtOQi%XZj@k->Lv(7!6@J)M$SQxH{N5b3^C&4uI0iOnIJ{t87A5FDMfQ^u z`6phg?P-ey)T4~k?RG-XYZxDI;IcQSB%7&6s2>Z;CV1cLrPrxGcwOW8cw_E5f#kt& z2}&n&`cJ-hAFw}CFl)%!E`fwn<26iuH{Y&LaqbsB?71d?5}N08g6DIsqGb%IPV^KZ z<%B_ye1@Z!T8+>A`)>;t;EXAzORkBIBb_0%#-JUk-ZunW+oT^o=$h; zbdXYBwD^9Uom3-qRwI`~wG+lX93&Bqcycj9$xMzPYEFh_P^Z*k;IweyIUVAjK@X)Z zuK%H?+C7K@AcJlQLL7Knhq%h7q=M6ZKg^Bq^?a}LXptMytI8y{ywE$8LL_`5J94E` zl?-}jV8fc2TU?wY?=zkt)Oev(A`vsJL<$KCvt^VOr{YnIQ6uT3GJ6=94CcAYnXm)` z7NE7H!4Mbg0lAXQ4D^z;q$kex51c3OXL<)v2vMk3$|Sg%5>_%ul^`odn0^_mPG)Zw zn(QCqDkCWG4XHXf=Z{4EbL5jZVk&8YcVLaxy<{ctEhQ$(#xh}8*gGYDm@8rAQg@1_ z^4H%!IqqheWLPd_g~rl#*WSqUk&mT8TC6g`XFJr7W&RKhJgg)La)2mGmKI65$}(|m0sfguL1Tk}yw69) zWmPTf;P2ejT3v>UC*)HdXdnvj*wX4UvW!q3PO?(>$l(|Nf?_R9r$h~!fHMA00_@1H z8a>aQ@;+rfcmoNUW*C7`?jCj@?VyXsSnN7ZoqGPImtH(|ih7pq6v2IjvTR-ai5<+2 zukLVk&`*2`5e!(>I{uz{{;VTW)P&n%0pk+fS|A)+9D4gGJyz5y9!W%^BhNp}967Rf zZD;=L-WPfu4*E+^bmm%l=`JC+^5bk53)j!(Sbr#)|k-0CEG zDdq1c;aA;<(O-Sk%LM)PPe6Ymt7#|B&P7G!&zA5KCKvtPhcxkfIt0I>eo5Y{sC>5X zk3V}Pm%a91sb7$@>!`ox?|tb$F`J1coK|DHsWU#$z%;gh^FCs}_P_*fYG^2fPlAqy zlUkkCWHxJUuHwoD&Jv)lz)G4^6a8;?!|XUd(}(Fbi)s$0yYIe!WtCkR@J0(Qj$&s; z^_tCFZ@8Ni0PX}pkJ?_|+CZ$()pgi-IH(P*>DgzWf8*T~quzL8eqm&AbYyV2`_OC8 z=5*gnTbte0YDx>h6OBqMGN)=#Tosi+ylEwA?TR9o#a3u7GU+s=db6^y1n#+YoTa3_ z768veQz>>-MrmRK2Dj<7m9+N0_APB|*0(ej7ntSP#wtsjH{ABXS2;@o>ip?+PLzsP zDvKIh*P;^X+Qwqi+`qiL|77=x6WylQ}^uepZW$w~$jW{<2|md_fi;^(&Z z11*+$qsMwxme~-b(~sy^yEkS2p80X@wt2G5ek7}}{O-dl>7BPw-y&(7P!gb)e^J!2|~j&lpL8yMy*Fh*^6%?7vsVl-Tr%&&t)jdWq-@@m;{UEd-aF4m!14- z&ifj-^F7{)G2-lzG$YX$+HFpU7O9yisURNq`%xb?O5AlECz~IEVP|sDO=UWz8OmtK zrrgMMGF6PQnq!>|h1ef?L0M&GeSLvUOj8CemgCI$*m!_=>bNZO;mi?a(Ks_ciNr0i z=F|17;H@tq#Y)>U)CLZPqcVO1xhgbhwV{Y(Rojm1OKV!2x88m4-+yaUVd0uJ(5G2v zl6oL}eCdIy1a^!H>2H1uRMzuH+8xwW;qX&DJ&*FEdX(?ukI=_8i23SD5WBWy=lXib)pn_e1_2ye7Y&&^_6)SkQ;g_#)t%3 zn^9yd5NjND0M*0bUuP6$79rlFP%>FD%?N>9i38A|1p z5p|-#aIBtf4!B1F5A7daiVF*1FE9x+GR8j*Wc$R-Bn1G=id4zsgE<8@A_&5Rmc zfOnFNNU8KsbY|)D_{2CsN$#}RPz}|of_qGs&c?_^;j8H^%R*;kDTJ|r(m!G~P_??#so0c_Ew9PdYxnZaNR=;YE;7A4}Pa+I~}a8AurY7Ij&Ps8{L zpjbf(oI!R;G!#wK)S*)V^`*s~ii#p8;Tr`@@1G9+lX+Mozi{;MNlb}zr%#+X^v;2F zc=W`}kMGF*WA^78nR_z#X8wlmKd>qDw*ncR?lijxp87MYhU}k?$x2(>+QN|(ki^uV z@ceV9X^ol=$Kh&?#Zq*p0=X47)yiYYY^JAv{!FJXk&;Ed%e6(R`0P=b3HF`yvPfA= z(_J=c!+f%pZ`voMbc?bCe~hs|K3*b zG%4s<;EvmG+_9#X+Kk7axAb}_K@z|q0+5kO2G3&CarnaI?9|}t$QWgERlmF~;={ ziXeJvntTQ0w6L|cLLxz}3+9cN)5DuG-|C>|Iid6Bn=2@jKv0tldc^C44@x9kYaV!j z`W(wj2+k}H!`P2={P@rOT=+9T7yeB6N5JQa6A(-^;P#OkiE>eVdD-LjX_bPgZw^4V z@rlvsXz#%Aq+7yBbq18dQ>w^HH0pvTSaFQyWsc$kVoe?DacClV$DSz0w!3JG(U(>= zt=_bC$Cf6i3B@Flpf)9Txk|CSt4myZ zvqrai^@@rDfLsEh7^5nzZROfs7MUDVUnCCBE+*kKRWkm`$>~M6Nh|Qr^<%Lfe(!i{ z{>ZVDql{9nHkksUq{+a9rx}mB_LzC7bGF?#7+I02RTh^?IB*AIT6}79kUImD9OO@VY zaNc&)RVynCj0PmOQCiE_U(L1GC6)%sBA95D&P_lioA-$Zbap)|D-Bz`urd4tabU?B(s3UUa)*;4^xo>E;%KSZ^*0X-Q5d;Dzehc1dNq9hj(S zd@*Ho*bFME6yk_UXHc*dOg1Q$8y$9|LMk^H6@Gsp6w+%-N=h^+b{>p)qRDtf9|*?A zCl*5Jv$;^3j0VCXKQCkM;pfOd@^j>I%#p`iE>16ekZLu8s27<}&klQ{0;vrDMTs?L zlC4)GrcmY%V9*6$g8O$(MR73%sujTtvuIX-U#B7aP5x}Hh>GKE4rm7wU6p;M=<s z6$q2+Bk?divH^urPX}gBVws(s4hZB*{1=j_)?p`J=TK0gi5~1-dnQ7hICq20Bcj}g zA8FRMt^}r_T21+T!Q2iV>@*xd-ZLJeL9|2q$DeEj` z?+o|_IjD?4BoCz|T4UAKcinZ@)m27$A|RJwsj9OlswGS&D&?=Hq^#BL_QL2bM1e@~ zXP9@BL9aV|pA1)(iXYzh8gVNuW=yMr?QCBQxIHdFqz9wS#ylv2g$j8|rgUhX|HzL7 z3jAa%tbdQJR+K7*gFXem4WJ}ZV&J)wn&3z_N$I!;l=sAKs)S4;i2{ZrNJTv`(|QDQ zXxa*aCj>iONtSCP@&N}th47{)u=#aIDX9^vyHQF--BVpsd?}#tO@fs#gNdYt3KERP zb!c$`4x;D~@_;q5waP4zQwd_il{FDI>z927gCD{#6!gciKL@THG*!`I54;vAT10M; z*;7DX)4++01~N*Lan+^FpztOoOn2!sq$mNCp}e>nS=E4-adI2z@FaA#(S;ZdjSil2 zn@&PYN$8AON=Ig(rOZSG0(;~9d`gU6f+$shS92-|eiTSqbzFI0-(-lASxN}=v7npt z$femo6`~Y&BEaDGo9w6DzAkYx7J?Hg+$D~OeZ;K9uZwzqG*A5+(Jq;F$DoiNU2m)~o7_0OV7|&pYv?>%mgK5FRgET$WD~xq_mzR6J*^>tW zvIQav&1XdwWm>Hr#x~qz1xu~q=+@RvFdu&78#isHo}`|n@BT9WRN>EWem@eq_F9Fa zwH5xHefh=wpC-wAdI2D5xt+- z0ya@UCE7n(9hdG(NMyRmVwsu2p7T*radB@i6=fe4+U?)}J_z(Lh&Cfv<@ZJTh%{3X zqHYX^i3##cg|H8DI(vG^FXdx@L`*6;n1b&Ye18*)SYcnp*RxaKo0H=To}RG&@+T9V zGA^;s$s?UqrLcTJ?Movfpba(NvR|BB5mI&t+|(bk?fD8nE_syEKcE+4dA8=Sh@~<= zE|N-wkh(@pa}|~J!Rj|YH4jpILow7%l7pfgyD|+`C=Q(*KiMPqVR3PCVsHd;9}E_P zPNz{R5PTC0EP_XjjZViBU2>D21YIhnfNQg;ZY+p-qMb!1XG3da^D3w=MO1M7+{x1? zPoIGZ8+1n*h1LYlmV00v*gW8)V{zbvqswyvd_31XJ~cW#>5a)DZxPw%vTCuI{DV-u z-#vIT9PO$oQUzcam>3xt^6QF7c*2U6E9&i%lrNz-BU32&PgP^v?cdl6i}_EfpHQ8e zZ(&n(=ccBnBBOcZx+<&)R;qB-Raj(*CPI^8qGL;A-kGsjDg**Vf`MhwhN`&hAO7*7 z>np9TcR&2_!(V;iK`PZnQDpS<+L!g-97oM&6wH~z7;*73(ddlglt4Xe3uZG1W(Q2% zJOe#LZ5Jn*g2AfA52O?v+8SyMHI{XVhQlv3x_SG49Y3OZ&mf7}cuWjd(?9M>{8-iB zR|QA4S)8Q8Q-Fm0j9Fi65dWNc;z)q*6!?z(nnPKZOedX5?@`dyK}fA*7nZ102G-Y3 zRCb{0LkHUcH>kHGuK2>CLjabca!U%}M7V%xj(Pa=Erw2%DijemO$oY~fBN%KxKl9y z`Y*T@TUVEZz$J}q+jqi)cm4JE!S?;v_up~-O$a#RkK3+&@IF0&O1k3K^;_hRF13c=KGr8TXdkWzo<}>q#Y78V@+Lw!BKk9T)-j~R^f^TsR#_`oHdl6}wp=JyAN#*TCJ=f1oJ6XDksC%9w9 z%B~IYlVT>Ghrg7Nvllwtp+mj%a;y#ceDA^EKK9sSzdfi_?)M5(}NgkzZCqBuY8e{y!)#c&yM!K`m3Br^-?~`5;qWw?Jdt8^L*ti zJb(H!MyAzfvsi4lv9X1Pu`!ekhs+T`@e-s{l%Tw>SSbjObieoBduJyjjNDobY@$d5 zJC-8lzhFa1kjmP>lw#$?#=#)44F_v1t89jup&3#jJWlFWA3JjnE(bscSFHlrV#?#0 zn$l?$a8Cf_js2rotlYAtwNM)Dc@x1!Z}lu^6pq>^nLw-sT3C^se`j@xOlE67Je}+; zPN$MI0zrgAu}rq@s#`$l>squ)_vu$qN#fb(UrNMMU9EQeh7EQ*a*m_c8&Myih$h9> z%JS0c*0{`3S-#@BFMQ=IU%BUobq%$}CUtw;$_A>CRV;<4=+LXh6Sb-*N}qdH(pEUP)_-oem76g&w-xx>THmNT%}XcVwV-T)aWdt zTBqQ>))v@>l&YcvxYi0(r9dDXI2CJ81CmLUDuKAXx+<%6q;E>h@Z397o(p_eS5cbr6waTj5VMTLes-a&zM+&9nKG0%G_7uzYf4wH+I|m0 z_3z%avbDk}-?(;Fef_Ro_4T*iwtoF>w*f}hX+vZW;fxmNMDHO0F;4r%whh=EU%jT* z?)pm zxA4?^0MvV|ct)Ncr1ahqN?nG4+cGuf8w9Rt&}Xk##Do<#I3U@_Tm|7#rbOq>05%5Q zj9_jE2OhhirG`DO{w4C}Jb9?7h-&t~3!`!qE792A4{oPOJwJT%&x95HasqQD>+`Cvd~sfXdJ-ol)H zFY@kyGAhbOZbvdAIYPoP>PqMJ8#gKyZP5Q47Z$t;vCe`0s8cUacozm#>GzC+6 zA@Y(VleuaIb|e^SI)SX-^K*;K%K*&%&o*x=Ejqeya5`dv|FEn;nMtJKL1WUPg{kqA z$0X9oT;E$rH}&GX=O;!7ddb2bEh*{keJ&n<4#}I@M*qkYaNNCgbT%f^S)COPYa7gn zd?X7uso&L}OTR%yyp#Ps7e*%r77&k|ET9~Zv?)Sk1JlbYk^d|l$*;Zq=9$@%9^ke5 zW&+`qp=Di_Txe{7H)Pw6X0tgPxNld=owR9IxSRmZ*@oam({>WrT3%p4aLCv&N(wAO z#lfm}Rt%kd6$PWFLn)23u4Tol))K9_6X5`q9>GTZ-X}jV^XTk*LH(@nNQ!_X3vvoH zHL)Vh&8Er%PD86purnyt2m-^H9K-%cSriq0oT%5R5gZ0!s0gup@XpT+m#|a`CopNm zon>M`s;gU?uevIgy6P%qYA+HB7Z+(GsStsj)9&}ku6Y4>N+$L&8Cv4!7`>1Yu!f^Y zDP%HPrZhD$&(`WFR1#UoQtLQ@5qGU2yAhKKr44uQmdi^^T?KMEif3etkC-Z3+O9M0_Ce9-shWc`= zBo&?=fMMl)-+)lSO3ZT$7Sr6knJWX39`lT0gb1$3{<5yzB##XqCP2{Pgj{Q{td*ip z2ursBq1n>HaaEaQ1}78gskrVsgw}1YRVBR_-o<)<>4m*P^sIb%w4$hgpqOiDt}qhQ ziCACWy#A_Nzfj>Qax~xa(D%Ogy@zgVb-0R3s&3!4ZJh`q%H)??$Fenu#}Y}EfVHU+ zW%lfgkmYao_(it1TcG;fb=Q3oIzu(8G)?LykA}Kg`Muf386vXo8h>evelK#QUP&mOr z;}ImoAw;Gnn_J3cp_${agG#R+9rqjBZn^vJyKkXsA#6*Cj~Ax5Z9};QXa{wuRgk2K z$|Dq{VlC^hhf;nGbe`E`FN38VSgg1X^A+*$`r@hrG5v#;OvvLWX1SEqXfG91~UsBBWJVK;NK5>Sj-py?bB&SP0u^RvAcR5hLKQ67}bPxr{>-Q9-xspDQR zbe;XcNStPw>Ug}mOYDRSgAbhPokPZ_zW(*z!IzMc&mMVoFHAq9C?QIl-(+{D_t6g8 zf!Cj=7t#y#Pdmg7G3rK%B9s~Q1^o8f z)ey)HHjNx2HMFqgUe;<=fI~tWg9fALar5p|Cm=yi9*>K)#S;_7PK5Qwga&T}cV60xX*0G)_;$Z-VxBVJk1z)qu~`=zeGe?n{h7 zy*XG;h)Y%#96N&Y6orMSPs2pj0k1XK2xLfxm1e9Pp_gy8W`1BJYLq}}E`<_E5!Z%BXF#Xfin_cem@V#SdDhMdwBR<0pKot(X>mILhcOISEGd7rdw0BTXRfXqjEdR% zYE)+j^<`EO8HAf=5Ghd9>c}T-y>phwbv#}2b-&xln8v{iWU^Q&Ye@~opr8wt7NV9a zg{L{jG(T_R3?iipCCD`z3f7D1l*U$%5$0?N*34)$ON-;MYm6^0L8gafM1v}kg!IZ!`_U?5!-g#%(oq@Q?xQASk&%&^8Hpb4(MvMNfP>rw*XctK{r%rR^w4Gs$#m%N zei#3vc!J}8_A`!q;)%x}f8sKoZ%&|fwVFVnuxTcULd+wL=0HGJHW83WrYA`rlm5x+ z=bwLmi7v!$xsYCZo(ke&Plz6P;G5rk;DMdg6ZrWtexAtu4mO)_(H$L|$-D4(zx(yC ze|H(OHSgW~tKWC`YBas4e*5dad;j%!3to+8dhCDw>iOqSkNBX9`$kSX9M(TP`S=fi z_`}Da{DT!yD2n^;yYGu%#LIo(`ObaUW^T>gj-Ph?koQ~ha|?cM{X|+{&C~j7p4Ozk zB$(wzn!bDN7$PKaWHQIzy-3}6k5Q8>=giL>3spEjU#J`(R}PXnl+4YcHm*z{7#lf< zVL3N4_SCb_CLrJ9NWk&zQ*%k;qBSMwo_-eP>p5qBBI&7;k&zPP$&<$8WJ)D+Q|bn; z@HfAC^Y{p))yVNT-;~Su?p?Fy`RBu7@tgnrla4K!Z<8N!$4~zGO))l5oFqTBScCV> z8Snn1NB3tZnL9VhavtwI7s=!Z49JmPDQAd^zYrOg9BJeLnVwcs!fnrS1?TJJ?S7sX;N(6D9 zPiE-u{^mDV-*(frJFx}X+SXioqJQVQfBUzueGQp{N*1;7k9j69>_ezXC^R@2nweZ! zUYwZ*E;ppthXd!&2ly5CV}8_s&X4*J(EE$p$R!GiMwAgmKTaWu2%wJ$nM7V65ic!g z^$`xnU#P2lKBSCTNqVQ8GE)3OWkm52T_mT6OcvUlP(+}KI2}Y){CHJlVBD-yQHiBF zUnm1jB<^$PH4*XDTvij|gz+E(LSU$7*MFQQq7YF*Xd;0KG!X>;VuU}ch(HN(a*W&U zPjs%2`$^3^9F*Q!-quWBq} z8K;vZ9fI$Kjzq+IZP(@1kRO=h;mtd+InE!bRyKmnVL5H`QhU~27{4Z;Z)&jny~BqG zgGYuJ>BB%AoH*G%J2~lzFTDB6>-&$L7#o|Inp;@#{N-R@_jo_`JWC|vH0t#tMMPZO zS#b8iffL7Gd-a*$zSjG~3ulfUeB-&7_rCP@v7YlBZ7J+(nweQTzyFz6UU_R`-*n9Q z+P-%W96HuLKI4rf!~gl@6aV_mJ15Ru=o=Uun*QN`oA6>4{EsJp{kvBV96EI1^zgxd`S<_)!!yr5|0+js*xc20^r%cewXkc~$c)Hx zY+@${16lN}@?=^%UM>(Luc??OUY+oPqE)?7`AW(RXC^R+zK-}xP>UE zfdNXE{|kO%T&&J}wu1!8geY?j5*De5$202zRTbBBvd?XGL7j7L{oF&_sK=<^Wq%%{ zAA-yAIac%Pt0%p}!VQS9+E6I;o_sae9tqzb3Ev(PF~caKsUmQsv~&^S!lKa&>)WAT z=6sf#dvm+zLjHV15yHfB&O~|GK27^Z-;32JteKgqp*E!*9h>M$4hAi< z&lZYAGZk{-WVI;4?~$c^EAmmk@*BvqN&{V}z(GnuK(kIZH> z$=b;zOR5da;B1mV!>(?%t&9Z$>UPk-%eF9Z6Z>J+{w&p!Y1*ZTSZ zoipoTORh7#rK68@WHMODasgZ=m{ZxPu)EK;{qG(-=~&*ocln)nJ{Vt&lrUje))((w zdBjfl-szWqkF&SS(-p3jN3Y*|1RHRD~-%e1h(GZk71h%Njt!|@cD!~ODfIl2 z2!KUg+mMQx?GbRWi`8oJj^BTWxq)l9tOT5%K!|8O$)xA_g$u`_pvn0+90Sv8@u+ld zm(=STnIc?hCt*Y0*3EAe3SC|KJmF2Lgpp5{Ic92VM0+PF8e@0H#ta6ebi}Y&vxgNFpE_zP}rzl`_lgIHjT;p{I!SEp8z6Je4UHXJ?nz@j1Az+dc<{ z@Zsm=1nd=y3I0f>lC8?iaq#3~pbybZwp?{XWpyLzgWYNY$qhsWRW(JWPja9z11RHJ z8c9k{WU4l6DO=_QU~~fmonkq?6ev_cE<+;d4?egV$W+ay-98_}zTyO+jrPutCU7M* zDs7d26Gaq5kW~#mj}H#^c-lNR*cmE0Uq-sfX@4{l%YmM+u9dajgXF{^$l&z$ z44yoG;>>BD*L(U8^zGT((`?Y{t>)*Rd-~Y+&$Uh6dwkxlpARwrc6cAuo;IqrB86b$ z2{mN|BXa%7DOf&d4i2`9?A5DRE`Rjf_kjWY`j@}DmAt40=UNWg5uH%p2v1(!Tw~5i zPwK2Rlb*wqk|T$-d{_%o8<0kaLz#>x@)c;eaT*>{UKtr_bvmgwixEq;(Pm?ST!o{t z^>_-q=X5$JGdW4C98VIUGFRK60qn*!o< zNh%sThJ6uYQ~IEnNBs=_N6(yV16_QR&2wRMW!$1cu<7BaF^e+Uem*DjIF^zw_Aaw@zwiFd}~@9V=Ehx?ihijfl?HYPLJzrXMBb8v}2cet;A{}Z{A z#?`U^6to6T?eDNdKDw;5ckDg#>9*z@w|@cF53i) zOinJOz&=9+61=6Ug-N1Hw94)>)#^p$lmyS=A|kvQ$I;Jy{&PnmbbR@Z*Wb9j2DtSj z{+M(nY+5(31Q%MEG54Q7efj`(z5j}kHoLZp?Mqc_Z|?_e+TU)M2gfJIgL3&arM0ui>kxH3B5X_+u^L;No4SLs zd$EaSKKuo;cfSV-j8q1;N||}~SvUobIoWTUds^hnlV*prxd|Au!O}K(`lUZV$^3=( z)vv!=e|_^mzkD3QL!Mj?kn*4YM=-a({H61NtFgI4Yd(WGIV$IpN9{FBX!*Wj5rwGS;q zZ<82*_cjaI)6o6gAAR9@^k@3~qPH%=;rPS9JX!m1%8`F~&!0$;Aq_l`qjM?nWuZt& zeRiq2(U0GJbJ%tN=3V8U?lvQ%X+MhZA8FSxttUSF@1AX|E#Dt`!ffu->gduY*t+@- zoqd5CeE;Ut-e;ca?zV|Wn=%1wGNEwy9sRCOiSSsO|Lz~3dzmTV z-65rtx%%OUH%~F&Wxh+)e#SkJ<3}$aB|}Ur)rbBTQ}^y!rCHc|Vbf-{dt@pl-ATZE z^!PALJY^H(V-7G6-u(P9^Tx2Uiy35|+rp+>JW>3j*!u*NB?c(ccR?- ziFI#l@qVqg5>_gw?@`T1`EMEZlfyEP$2lyUTUr{?->sfFre3Jk?%hlim=o(fxi0lpCeW``uy_^-fu(axk)O6 z2W7x{3t_o(SXKz$A{SXTxI6pzKQW?g^4y$Pa>KIB%?}9t?u_-K9Lv6mD2=%<9rp2c za8%Lv%Gcp;RxGr%eEH95DtRNWAlC@cls=fi*oJbU+Ecf=W-V=T=>G7!EW6KCi9nG zlI2x}Vy(dKdFt60FF@8p2a#%~=}Cw~AM=T2z&H9=}CcFZrm{bb>uzX&uiw}!=|3@HredK3S z!~K;?xmd;;xq&E;@Vd(0b@=SFPeCMR|H6CGJAF3@J(0ep;J4~KnUMoEeJ>TuF*5N<$jVQ~>C>V^{K5Z?eUwCLW|JUgUYSaQ zeEnDYYuBcejDcov=+QID>1&%ex_+I$+kY0ORP=vK0kxu_{fUw8<|A@K5{F?a@^ZokIkC?ac_ie_{MCw0F%q{%=4raa|)_>l> z@fBti%*{akXOvbMQ{pUK4OH6{9m;Rn-)|nEkV(qM_{$pbiti&YIlQypxz;OwZaYoir|1q#~;BB^H z(po5#8AxHmD-PYuYNG)3y4b`pIqWe+LfG{s*dTFh={|fi0hFY5zQM z0EDG_|J?js>VG>%j$<^|*iL2+G3lU?-)0BogsZ>zH2W68=D$|`KkS!Tq8U&PTo?=; z{Bx)Rarapt`yZIUYiKt6q<-y_<{lsV^^gIQ%-Iy;nsh>RJy+7RO9VmqOfDWqvBU8k z1BK+fDTD`Uo84iMyfjXme>s(JZn{T|4u>iir5l=HG^cW;?)^&u=j8)_tpETnn|8No z6bV%eL72Nzs}-?KiCV3)YG^&NPpawfQ6jlVmZBvpN0(8cU~oBF7K`a=7>L_T#P5x+ z(GsyyKMj<-?~k&MOyEsyC%2Z!jUc>=iIxZ?Diulu?iEut?LW~fmFQ8gzy;byz1!MI zsi9%qyaqC-3h==ox+;^GAQFp2V{kD7Q|jAZ+Q^E3VSeV`z4?UzB85XC#L3>cF^-_i zr9d#SvWA-UZfjeE72*(`ZB$g;s#c4<*`QF;bUCpIex=fB(zm^q!G+1&Q{!VdCujZG z*RRJfU!uFm@u`{V*%`FN9In6RnYei*<;dnT>F|0y9t#KO?p(hSD9N#@x9XsiEW)Jf z+ul07M${X%BIs#QQPzv%0NwNKZ!u{>`-WJ)D7D;+QtxUo3139Z`Ji)Z&LqnkRG3P8 zhf5^B?G2>WLN^9eJE!7l(EFi-1Mq(y?BCmEhfGx+&DcqENU*jxA)mNbTOV_XMUKUa z$Ws)Xzqv+)_M?NPl-OzrsFhcUperpemvn7y(TShU6JcR2R&fd0Y`d=W2oa(Njx$7q zL6!AT=Wcg1x7ce%5PH&vl%G7fTRb$1E86;f>nn^|ku*(=J-l0N?v2|-SiPH7c9<&_ zr?O>$2ob$XrH4Vnbq-pjyPcPw`*~?rIgjV=ZSCn0lzKZ*TVP$uL>x~tjGQa}<(0M2 zBHj8=-CtN(n4c%!M!k!fL@ctlx{9P6G`uiBKMT3I#kC0fK`NQaWr^3auR9v78fD2G zw&w5`V2#R!La|6DvAi;kJ~Da(zknrL_BD4<~D+4Zp{SNiG8(%*|oSj0Z#Otrd}8z zdz+MS2XVx1waSx=utXM;ROb5OF|l`AVO!Zc4}#7%Fh7cKj?G6AP#YokU@*to02MTG z1*{+skEI@bR4VmRsnm7Wk3x@-DxCtOGFB=>R?DO;C-CKDPRPs?S0b@8Hvts|j% zldJQTj6N~HlDzuX>z9dZYl*kkq`qo`!&F$g17VTL70?d19Dn@Nzj%wd=4d$d=v)Lq zR=C50S;g8xWiSqC*2^y9x_vv4k;6Zx$}EFR`0$vsKG_)k+=Wf#R4LU)<&lBn3cdi7 zdu@n`5*!aP1D`xE4e>Ol7Xj2*OmYPBwDILR+-r6j;1e`+LElxusU_@+ z7E>}CK8s*FWFG_r{*zo1AtQZE;N4Q%$JMkdlm#y@z< z7T0084P2sAYCVce2vIgYVW-5cHoHi5LiOdy9A>nr{~l%P`y)A`pDM5a z%5xCG7Xuy)j6n@uO)*>n1YNH|)XdW|@DxYTXFcUK_X%#63`&X}*! zFB(W=zf`k+T-9o8a@na2J*H~AT~md!>uRE+BUXn>6qE>Y#zsJ~ftj+R;PiGEv3Bh9 zw!j7J!cM)r8~IHDP6SI1RKd#-m9Zj~1zLPTLr1g;~SFaS*N19&aBI>R#b>u;|lAT&qCaMv=D=TCOS4&4GCL-w?;aXg5 zQC(Z6T1>^|@$uy%!nO*(o*$NVJcX9en)W*!`%PJ?oV`*xd!=&rqMY@s>Tp$N>nJie z?%?-NkJ3o1%cFPw#N4GILbZt=D&J zqFr5w&VKflS6=!2*~h!2(s`uPd8E>LP`V*;nXoU)74l){f z0`1gfXnE-#B6996Er*l2v9bB(1iqVCo*%<^L1@~HU#E#@wMr1f@vZt5)bzV$xkgWu z4m*%)sho4U3>qpAg8VTqsWy*tLZ3uCI<=y_Bv&wnWKz^?n3@8fI$qRkGpT}tI6<^9 z(qxI8T2{s+8bbPbght<6SS`qiQ!lbLcrtSFbVr+*&eUXCxrWz^bMtEz;xw5sxKKB% z!&rrG(7ovZmj3CPrHI@_oGtAZm0GcBkuI(*#Y*wQrbXKBCeBPImZ6y=vK3^^b-6ka zBiYsEGV9bEjhXFLsXx3b^@mqckAV_RzoCF|aUhV8>u__eynyB^?pD8nPg=HjtM|ax zb#UwYXwb@-GPX^LOlP|`lV#*NIvS3nSU>sfaFNLwbOKs#o+bV?+}h&QAng)2uH8j^Y|a1lUnMG)COmzHlRuz&bs=G$w)~}0%Tp}D)>3zSgl%hrBo{yautPu)!gogtzkf?vF&CNosAc1EhCTw>4P8)UoMx@;ibu` zw3cQ#>F{)5x^THjYZ_T@Af_sZIy&$T4cFTX4*PyL5(Z&HEEe*cw%Lv?7c5NQwf3N> z9JSBtHX3&){oXsBr}fk}ft^;j)wpQJ*S&O4i6?WX(>FHL-2P@4ZE8mU9#-AIk6P1Vy)8EFm=^*4w_fIjc6@?>LYA%M-%v; zfv#2ckX1pbqJgW@op-c~R7xN)sze~X8eGGI1E2)6c!^k9wvt?%nYc3_UtLS2kO48e znk*w?h!xS2=FI$k$U(t^0fs8gGd_FZ3 z*FZlHPX~&;Sbzj#4F(IMv3bvvPwnsBi{$KW%@#S62udZjNn_>#JI@23iIQUV*u6pj zH<7F1t_NT3Xi<^;swvtJRkNv*f|K{`q^YnwSz^jFa8=&C%Q7E;UO% z7u-N*`#wMckBmjQD2MzMvO;g)2Anx_pjC%{rET4R2A_ps6o(i)Hi&j2K(J0h^K4iZ z*`>`M)QI}|{q~5`ef9LdUN4fufqbPgH+y&6B5p0u*5lo_h>MF5i-1jQm1nT_kxAHrqKbH#ThN|NG9RcR%>;^_#cv2BK9=8O6oP%fEbG>Lrb+qQuMo3|M2&fda|^*} z5}VS6>2d74uTKP)RwBfqM7}?>*=EpL*g){$h$a?G6QI~q1e>=w|Xkb(r-W7P5f@EBN3830l#IEGEoSo1;fmj;?Sz}i4|kmIZr1&2IT z;($g!JSO%wr1X&4+V(;HqIYouknNqt80G;WJ4hq#>;ne1&&k0+e0VIi+K$MM)?SEg zE$!A?5LaaSYJ6*nw;mIhzMWmzTI#K}A+Du&eiYqW@~y|jH9uNbZ!P`SS`pWoZ~WP_ zTWhfOSgK9K5>rUyMzLv$vG7;1@RhR6x!q75Ei4c%L-W<9iLk9!L%bE^-O7Z4>O_bD z&7D#V8~boc1*SY71FEymn1Ozn2=vJ{&b<(Z+3VCGljJsAPIUo(xXCGoqB?a0E?NKW zheda8bM)+p%w+BA5Rog?egwOwJ8JidTw}Qfd`2IPH{+e6ud$!q@!O&;AI7(nel@;< zXM=Aq-?9)WM;co2?Ji$YDrJY%e|N`qRJm0E#rYWYo9+c-Id&&pM@UU>Xf*ldN%X^s z<*a5WT!+;kc4HGMg5}_`iHgEz{dcsT44qGC7t$R3dR*a7lKvye_58Fjo#n0r! z(K}+Y+i*vNv7kl&z}*Uk8t?IN`Cyd@orimCDXvAoET}(zc(+R6y%;tn zv1Y)|wi-DZm@(DHy}5P}OBc6w?B%Xfu^&@of< z^|*DUz0sTqYotpRUi!UYYn(lG5|Sh5&V2erPa~J+d8yv#rP-tIr&02nYDI?OCjf6p zv>p~yIQ2A0Nv_r)ygZ9e1SF+YBHl*jttNpc8DQipnlDqQ%YcQGEMw~eDIq~?FcPnI zPfH?D&@oxi^{ax4s_B-K>&bW_6OL0;Vf@xKCYtGK;%zj8QdY?3vdMTVTYwo^W2b2L z3J`FRmlVn9k&fQGcrC~}m8rA=x=cvk1kGH9tX51y?W&-6K*X@O!`IdZRxbvUCW@pr(?YpU+k_KnC|1 zit5A^kU?!Bc>8v+pamwkkRFz4+pzE1Q1rI8_9_}N4UfhpQ51Pdr_`A(*$m{KMFD|u zB?9FGd8L|Pq(tgGWjG-&iLwiNSVz^b`utWYy&)`^kls{q=tiUV}3@~SdM z^pHVlb;s-4p+>(yqwi0~h*1y5*fk8rece79pvB*%A z&4TGdlcvC~-N>ps4w|Lb{^Sxtw?rzDfe-(y5@nXkQi)<{8VfB^#%7wJB`Sv&>LFYU zp|X&g`UN%_^%ChY@zqPDjLDp|L=g3TSR(Vm4yi;td98=Mw2dB=Xtz1Rhaiq>K8mJ` z=BpUqyUYwjUfQA$%fHL~;1dKk9SWkMgP}Bw$OjBTIxs5v6?n)#2BdZE+DBK%?j^vG zbkp{KP+OTsw{@;4F^a}qArN0SD}(KY$AaIoEHr&x&9HBsP5M4Kn9iO$aq85mvu8ei z-0PIu=7Kb1T##mr3$z#aZfhIJjqtp|pa){0U?`6v%|4ib1+`?mKjr3~`t zm@u=266Td^HRwl3ZUjmG;9jRvEZ{0^Yb7JZAe`QInw8cj@>&6QGEX7n^(f*N()9Y< zdq6s|0#e1o{9<4Qh7Pz8?@~K+W^s8r6a_jO!S!i-iRc{}+F$eOWD?8@c%?(Df%&Pi zD_7<-72MLO*1{!&Oz3^vdk#zKKca?eQp-w-OPWU#`dH|n@Gd~=(~ zH`F&O#Y_}6jb^B9Inq5BWhj@th;+{`R?=W)B?(5Bl2pnphsBGd$ahV&xa;}l-4?Ny z17pyl#lzHF9LTCwx9lE8zMsJJca}HU8uXc%a@pyWAw&ew)ka0GSXl|Bh!Yc$o+g>r ziDC_SQz}kHJ7ei|mKBIIRT0Z7L=dIZd-ibDrC-ZuOT0KWHM2sT$boDHd&glh8cV>g z=I8Fh1e<|&3u7QoFszYBPzUx9o?|5+-(d2z7a;_YC&P9u7}y>#ENjCA_~ZZ$COH6y zgdpu)9`%QEp1OSse`pe>sh|2oaeS^`<3~M|^jw^jq#nx6GsBOZ$!)QE>u1u-!5YW0 zWc7a1&dt8YCUvZPiCwU;YYw(wUN3=M8gp`K%x&8EC;|#Vi@Et^K4B-2$4(%N^X!kF zxBY4;U;T28x}1^j`G?__JVLrQiqK`O$}m*a>UBE6lEn@9z~qpTQa!*eY37Y>xMk=8 zZpq2=nPL`njA9Kq7%wc&V&Acv$W_Y76pq*LgIh+z>uIok!S|(5CtK@;DZ9^$Socyf z0lO`}i|rlBP0l+ySRNk0{9JSes32Tg+-q8w z`ApIX*=e2EXDw#PB$ptYECBbYAhwv7E34R^R+VzT4f57)L?3py)b+Uiej5!Yr-UOGj*zCh+U_gtA^^!H%MU5DM1~N#ah{0#E zdA$gRVTt+#<-2NI4xS)tM9(5(bvZ2%^$TWrht$nSUqB!+E(X~uzu#@hDtt%xn>Tye zAB1}8u%1D>vkKwwQVP>kx>QkWjdhRlj;NQH*CKX;in($!N;N2{b*`>GkDy+^ugCaz zqh9&C@^_8@MAXabaCf6^dl3_?3oV9GqTNuhOd?G4_=ZaPc-SNYeKq|~)N3c)6RQS` zKqLinkp^aA8ixyVi-Uy^(H@C}0lY2y11k*DxGvrWzhv~*;vygq1aV{iHrp(^)%#T9 zERa<=Tq&3W8t7dC@d|~43&X-g#B25e;6>%@)1~_SFPBv|ETTy4fWg+&8RT+y~DkZfSPw#`TOQ zBh}ldkpYMpU_}!|3G`qftDx$})ND3EQ3dDG*bF7Kj*fPZyV(F!$k5ER4a4dH5tpj1 z`Fs{tX=Q~NJr0`j-PGJ(*P!n4Fx6o_tdWXLjs0XMQ<7;+jj_99Spdp`-CKjZ1JYC3 zd;!ttdQCcARfskl0)ya^QEP}Xmy=_ulI60Xwj~m&45G^Q+Le`(%Ifn$n;BTHfJC10 zI8BYPf;>8ynjj=uFN?{fk(FV*LOW1~1On1L@~Gl@J=3P$zP5&-HmZ0&HHBMzTUjjb h+sAmJ9Y7H~PHIa|YD;-j)7lz^_qss&{5Hcd{~zpp%;f+8 literal 0 HcmV?d00001 diff --git a/pubspec.yaml b/pubspec.yaml index 67201afc..e25f89da 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,10 +34,6 @@ dependencies: sdk: flutter intl: any - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.6 - auto_route: ^9.2.0 hive: ^2.2.3 hive_flutter: ^1.1.0 @@ -107,25 +103,15 @@ flutter: # For details regarding adding assets from package dependencies, see # https://flutter.dev/assets-and-images/#from-packages - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages + fonts: + - family: Lexend + fonts: + - asset: assets/fonts/Lexend-VariableFont_wght.ttf + - family: Inter + fonts: + - asset: assets/fonts/Inter-VariableFont_slnt,wght.ttf sentry: upload_debug_symbols: true From f314c57356fbf090e149b880abf06f751ddc9423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 26 Sep 2024 19:27:19 +0200 Subject: [PATCH 04/57] rework theme logic --- lib/src/_conf/hive.dart | 13 ++-- lib/src/_global/app.dart | 3 +- lib/src/_global/providers/theme.provider.dart | 57 ++++++++++++++ lib/src/types/all.dart | 17 ----- lib/src/types/theme.dart | 25 +++++++ lib/src/ui/material_app.dart | 14 ++-- lib/src/ui/theme/app_themes.dart | 75 +++++++++++++++++++ 7 files changed, 174 insertions(+), 30 deletions(-) create mode 100644 lib/src/_global/providers/theme.provider.dart create mode 100644 lib/src/types/theme.dart create mode 100644 lib/src/ui/theme/app_themes.dart diff --git a/lib/src/_conf/hive.dart b/lib/src/_conf/hive.dart index d223043a..e04cb194 100644 --- a/lib/src/_conf/hive.dart +++ b/lib/src/_conf/hive.dart @@ -1,7 +1,8 @@ /// Hive boxes. Use these values to open a box. class Boxes { - static const String settings = 'settings'; static const String appState = 'appState'; + static const String theme = 'theme'; + static const String settings = 'settings'; static const String cache = 'cache'; static const String statistics = 'statistics'; static const String notifications = 'notifications'; @@ -18,14 +19,16 @@ class HiveKeys { static const String hideBurzaAlertDialog = 'hideBurzaAlertDialog'; static String location(String userName, String url) => 'location_${userName}_$url'; - //settings box - static const String shouldAskForNotificationPermission = 'shouldAskForNotificationPermission'; - static const String webNotificationsAccepted = 'webNotificationsAccepted'; + // theme box static const String themeMode = 'themeMode'; static const String themeStyle = 'themeStyle'; + static const String amoledMode = 'amoledMode'; + + // settings box + static const String shouldAskForNotificationPermission = 'shouldAskForNotificationPermission'; + static const String webNotificationsAccepted = 'webNotificationsAccepted'; static const String tabletUi = 'tabletUi'; static const String listUi = 'listUi'; - static const String pureBlack = 'amoledMode'; static const String bigCalendarMarkers = 'bigCalendarMarkers'; static const String dateFormat = 'dateFormat'; static const String relTimeStamps = 'relativeTimeStamps'; diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index 1875e396..e5cf6f0c 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -147,6 +147,7 @@ class App { if (_initHiveExecuted) return; await Hive.initFlutter(); + await Hive.openBox(Boxes.theme); await Hive.openBox(Boxes.settings); await Hive.openBox(Boxes.cache); await Hive.openBox(Boxes.appState); @@ -174,7 +175,7 @@ class App { static final remoteConfigProvider = Rmc(); - static const defaultLocale = Locale('en'); + static const defaultLocale = Locale('cs'); static const defaultRotations = [ DeviceOrientation.portraitUp, diff --git a/lib/src/_global/providers/theme.provider.dart b/lib/src/_global/providers/theme.provider.dart new file mode 100644 index 00000000..8aa66d9e --- /dev/null +++ b/lib/src/_global/providers/theme.provider.dart @@ -0,0 +1,57 @@ +import 'dart:async'; + +import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/types/theme.dart'; +import 'package:autojidelna/src/ui/theme/app_themes.dart'; +import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; + +class ThemeProvider extends ChangeNotifier { + static Box box = Hive.box(Boxes.settings); + + ThemeStyle _themeStyle = box.get(HiveKeys.themeStyle, defaultValue: ThemeStyle.defaultStyle); + ThemeMode _themeMode = box.get(HiveKeys.themeMode, defaultValue: ThemeMode.system); + bool _amoledMode = box.get(HiveKeys.amoledMode, defaultValue: false); + + /// Theme style getter + ThemeStyle get themeStyle => _themeStyle; + + /// Theme mode getter + ThemeMode get themeMode => _themeMode; + + /// Pure black getter + bool get amoledMode => _amoledMode; + + /// Setter for theme style + void setThemeStyle(ThemeStyle themeStyle) { + if (_themeStyle == themeStyle) return; + _themeStyle = themeStyle; + unawaited(box.put(HiveKeys.themeStyle, _themeStyle)); + notifyListeners(); + } + + /// Setter for theme mode + void setThemeMode(ThemeMode themeMode) { + _themeMode = themeMode; + unawaited(box.put(HiveKeys.themeMode, _themeMode)); + notifyListeners(); + } + + /// Setter for pure black + void setAmoledMode(bool isPureBlack) { + _amoledMode = isPureBlack; + unawaited(box.put(HiveKeys.amoledMode, _amoledMode)); + notifyListeners(); + } + + ColorScheme get colorScheme { + ColorStyle colorStyle = AppThemes.colorStyles[_themeStyle]!; + bool lightThemeMode = _themeMode == ThemeMode.light; + return ColorScheme.fromSeed( + seedColor: lightThemeMode ? colorStyle.primaryLight : colorStyle.primaryDark, + primary: lightThemeMode ? colorStyle.secondaryLight : colorStyle.secondaryDark, + brightness: lightThemeMode ? Brightness.light : Brightness.dark, + surface: _amoledMode && !lightThemeMode ? Colors.black : null, + ); + } +} diff --git a/lib/src/types/all.dart b/lib/src/types/all.dart index 834ff297..7154484e 100644 --- a/lib/src/types/all.dart +++ b/lib/src/types/all.dart @@ -199,16 +199,6 @@ enum TypStatistiky { burzaCatcher } -/// Describes what colors will be used by the app -enum ThemeStyle { - defaultStyle, - plumBrown, - blueMauve, - rustOlive, - evergreenSlate, - crimsonEarth, -} - /// Describes what time format will be used by the app enum DateFormatOptions { dMy, @@ -224,10 +214,3 @@ class Fonts { static const String body = 'Inter'; static const String headings = 'Lexend'; } - -enum TabletUi { - auto, - always, - landscape, - never, -} diff --git a/lib/src/types/theme.dart b/lib/src/types/theme.dart new file mode 100644 index 00000000..d00d56f6 --- /dev/null +++ b/lib/src/types/theme.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +class ColorStyle { + Color primaryLight; + Color secondaryLight; + Color primaryDark; + Color secondaryDark; + + ColorStyle({ + required this.primaryLight, + required this.secondaryLight, + required this.primaryDark, + required this.secondaryDark, + }); +} + +/// Describes what ColorStyle will be used by the app +enum ThemeStyle { + defaultStyle, + plumBrown, + blueMauve, + rustOlive, + evergreenSlate, + crimsonEarth, +} diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index a9af699c..2920b8b8 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -2,10 +2,12 @@ import 'dart:async'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_global/app.dart'; +import 'package:autojidelna/src/_global/providers/theme.provider.dart'; import 'package:autojidelna/src/_sentry/sentry.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/_routing/app_router.dart'; import 'package:autojidelna/src/logic/deep_link_transformer_logic.dart'; +import 'package:autojidelna/src/ui/theme/app_themes.dart'; import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; @@ -52,19 +54,16 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp.router( + debugShowCheckedModeBanner: false, + theme: AppThemes.theme.copyWith(colorScheme: context.watch().colorScheme), + locale: _locale, supportedLocales: Texts.supportedLocales, localizationsDelegates: Texts.localizationsDelegates, - locale: _locale, - debugShowCheckedModeBanner: false, routerConfig: _appRouter.config( - navigatorObservers: () => [SentryNavigatorObserver(), SentryTabObserver()], includePrefixMatches: true, + navigatorObservers: () => [SentryNavigatorObserver(), SentryTabObserver()], deepLinkTransformer: (uri) async => deepLinkTransformer(uri), ), - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - useMaterial3: true, - ), ); } } @@ -77,6 +76,7 @@ class MyAppWrapper extends StatelessWidget { return MultiProvider( providers: [ ChangeNotifierProvider.value(value: App.remoteConfigProvider), + ChangeNotifierProvider(create: (_) => ThemeProvider()), ], child: const MyApp(), ); diff --git a/lib/src/ui/theme/app_themes.dart b/lib/src/ui/theme/app_themes.dart new file mode 100644 index 00000000..541a3ddd --- /dev/null +++ b/lib/src/ui/theme/app_themes.dart @@ -0,0 +1,75 @@ +import 'package:autojidelna/src/types/all.dart'; +import 'package:autojidelna/src/types/theme.dart'; +import 'package:flutter/material.dart'; + +class AppThemes { + static TextTheme get textTheme => const TextTheme( + bodySmall: TextStyle(fontFamily: Fonts.body), + bodyMedium: TextStyle(fontFamily: Fonts.body), + bodyLarge: TextStyle(fontFamily: Fonts.body), + labelSmall: TextStyle(fontFamily: Fonts.headings), + labelMedium: TextStyle(fontFamily: Fonts.headings), + labelLarge: TextStyle(fontFamily: Fonts.headings), + titleSmall: TextStyle(fontFamily: Fonts.headings), + titleMedium: TextStyle(fontFamily: Fonts.headings), + titleLarge: TextStyle(fontFamily: Fonts.headings), + headlineSmall: TextStyle(fontFamily: Fonts.headings), + headlineMedium: TextStyle(fontFamily: Fonts.headings), + headlineLarge: TextStyle(fontFamily: Fonts.headings), + displaySmall: TextStyle(fontFamily: Fonts.headings), + displayMedium: TextStyle(fontFamily: Fonts.headings), + displayLarge: TextStyle(fontFamily: Fonts.headings), + ); + + static Map get colorStyles => { + ThemeStyle.defaultStyle: ColorStyle( + primaryLight: const Color(0xFFE040FB), + secondaryLight: const Color(0x7B009687), + primaryDark: const Color(0xffbb86fc), + secondaryDark: const Color(0xff018786), + ), + ThemeStyle.plumBrown: ColorStyle( + primaryLight: const Color(0xFFAC009E), + secondaryLight: const Color(0xFF815342), + primaryDark: const Color(0xFFA03998), + secondaryDark: const Color(0xFF7F2A0B), + ), + ThemeStyle.blueMauve: ColorStyle( + primaryLight: const Color(0xFF3741F7), + secondaryLight: const Color(0xFFA3385F), + primaryDark: const Color(0xFF6264D7), + secondaryDark: const Color(0xFF6F354E), + ), + ThemeStyle.rustOlive: ColorStyle( + primaryLight: const Color(0xFFAB4D00), + secondaryLight: const Color(0xFF6D692B), + primaryDark: const Color(0xFFC54F00), + secondaryDark: const Color(0xFF53500C), + ), + ThemeStyle.evergreenSlate: ColorStyle( + primaryLight: const Color(0xFF306b1e), + secondaryLight: const Color(0xFF54624d), + primaryDark: const Color(0xBC19A400), + secondaryDark: const Color(0xFF273421), + ), + ThemeStyle.crimsonEarth: ColorStyle( + primaryLight: const Color(0xFFbe0f00), + secondaryLight: const Color(0xFF775651), + primaryDark: const Color(0xFFC8423D), + secondaryDark: const Color(0xFF442925), + ), + }; + + static ThemeData get theme => ThemeData( + useMaterial3: true, + applyElevationOverlayColor: true, + + // COLOR + // colorScheme: ColorSheme is gotten from ThemeProvider + + // TYPOGRAPHY & ICONOGRAPHY + textTheme: textTheme, + + // TODO: COMPONENT THEMES + ); +} From 2e81671936781edb90f1c8071e92c284f045f9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 26 Sep 2024 19:39:59 +0200 Subject: [PATCH 05/57] move Locales class --- lib/src/_conf/notifications.dart | 6 ------ lib/src/_global/app.dart | 3 ++- lib/src/lang/supported_locales.dart | 7 +++++++ lib/src/logic/notifications.dart | 3 ++- .../ui/pages/settings/localization/localizations_page.dart | 5 +++-- 5 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 lib/src/lang/supported_locales.dart diff --git a/lib/src/_conf/notifications.dart b/lib/src/_conf/notifications.dart index dc724e0c..881cc2ef 100644 --- a/lib/src/_conf/notifications.dart +++ b/lib/src/_conf/notifications.dart @@ -1,11 +1,5 @@ // Purpose: stores constants used throughout the app. -import 'package:flutter/material.dart'; - -class Locales { - static Locale get csCZ => const Locale('cs', 'CZ'); -} - class NotificationIds { static String kreditChannel(String userName, String url) => 'kredit_channel_${userName}_$url'; static String objednanoChannel(String userName, String url) => 'objednano_channel_${userName}_$url'; diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index e5cf6f0c..ccfffda1 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -1,6 +1,7 @@ import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_global/providers/remote_config.dart'; +import 'package:autojidelna/src/lang/supported_locales.dart'; import 'package:autojidelna/src/logic/canteenwrapper.dart'; import 'package:autojidelna/src/logic/notifications.dart'; import 'package:autojidelna/src/types/all.dart'; @@ -175,7 +176,7 @@ class App { static final remoteConfigProvider = Rmc(); - static const defaultLocale = Locale('cs'); + static final defaultLocale = Locales.cs; static const defaultRotations = [ DeviceOrientation.portraitUp, diff --git a/lib/src/lang/supported_locales.dart b/lib/src/lang/supported_locales.dart new file mode 100644 index 00000000..df10d098 --- /dev/null +++ b/lib/src/lang/supported_locales.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +/// Class for supported Locales +class Locales { + static Locale get cs => const Locale('cs', 'CZ'); + static Locale get en => const Locale('en', 'US'); +} diff --git a/lib/src/logic/notifications.dart b/lib/src/logic/notifications.dart index c0fd8fca..ce1a54b1 100644 --- a/lib/src/logic/notifications.dart +++ b/lib/src/logic/notifications.dart @@ -4,6 +4,7 @@ import 'package:autojidelna/src/_conf/dates.dart'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/lang/supported_locales.dart'; import 'package:autojidelna/src/logic/canteenwrapper.dart'; import 'package:autojidelna/src/types/all.dart'; import 'package:awesome_notifications/awesome_notifications.dart'; @@ -152,7 +153,7 @@ Future initAwesome() async { Future doNotifications({bool force = false}) async { //TODO: add more langueages - final lang = lookupTexts(const Locale('cs')); + final lang = lookupTexts(Locales.cs); LoggedInCanteen loggedInCanteen = LoggedInCanteen(); LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); AwesomeNotifications().createNotification( diff --git a/lib/src/ui/pages/settings/localization/localizations_page.dart b/lib/src/ui/pages/settings/localization/localizations_page.dart index 32810071..891ff33d 100644 --- a/lib/src/ui/pages/settings/localization/localizations_page.dart +++ b/lib/src/ui/pages/settings/localization/localizations_page.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_global/app.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/lang/supported_locales.dart'; import 'package:flutter/material.dart'; @RoutePage() @@ -18,11 +19,11 @@ class LocalizationsPage extends StatelessWidget { child: Column( children: [ ElevatedButton( - onPressed: () => App.translate(const Locale('en')), + onPressed: () => App.translate(Locales.en), child: Text(lang.languageEnglish), ), ElevatedButton( - onPressed: () => App.translate(const Locale('cs')), + onPressed: () => App.translate(Locales.cs), child: Text(lang.languageCzech), ), ], From a5da6b579d20e0afbef28ce27bd202d93b5d4b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 27 Sep 2024 10:01:17 +0200 Subject: [PATCH 06/57] wrap MaterialApp in Consumer --- lib/src/ui/material_app.dart | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index 2920b8b8..06757540 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -53,17 +53,23 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - return MaterialApp.router( - debugShowCheckedModeBanner: false, - theme: AppThemes.theme.copyWith(colorScheme: context.watch().colorScheme), - locale: _locale, - supportedLocales: Texts.supportedLocales, - localizationsDelegates: Texts.localizationsDelegates, - routerConfig: _appRouter.config( - includePrefixMatches: true, - navigatorObservers: () => [SentryNavigatorObserver(), SentryTabObserver()], - deepLinkTransformer: (uri) async => deepLinkTransformer(uri), - ), + return Consumer( + builder: (context, theme, ___) { + return MaterialApp.router( + debugShowCheckedModeBanner: false, + themeMode: theme.themeMode, + theme: AppThemes.theme.copyWith(colorScheme: theme.colorScheme), + darkTheme: AppThemes.theme.copyWith(colorScheme: theme.colorScheme), + locale: _locale, + supportedLocales: Texts.supportedLocales, + localizationsDelegates: Texts.localizationsDelegates, + routerConfig: _appRouter.config( + includePrefixMatches: true, + navigatorObservers: () => [SentryNavigatorObserver(), SentryTabObserver()], + deepLinkTransformer: (uri) async => deepLinkTransformer(uri), + ), + ); + }, ); } } From e671525df3e35ec904ce3ea4564094d03ac5ff4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 27 Sep 2024 10:42:15 +0200 Subject: [PATCH 07/57] add Hive Adapters --- lib/src/_conf/adapters.hive.dart | 37 ++++++++++++++++++++++++++++++++ lib/src/_global/app.dart | 4 ++++ 2 files changed, 41 insertions(+) create mode 100644 lib/src/_conf/adapters.hive.dart diff --git a/lib/src/_conf/adapters.hive.dart b/lib/src/_conf/adapters.hive.dart new file mode 100644 index 00000000..1f69121a --- /dev/null +++ b/lib/src/_conf/adapters.hive.dart @@ -0,0 +1,37 @@ +import 'package:autojidelna/src/types/all.dart'; +import 'package:autojidelna/src/types/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; + +class ThemeModeAdapter extends TypeAdapter { + @override + final typeId = 0; // Put an ID you didn't use yet. + + @override + ThemeMode read(BinaryReader reader) => ThemeMode.values[reader.readInt()]; + + @override + void write(BinaryWriter writer, ThemeMode obj) => writer.writeInt(obj.index); +} + +class ThemeStyleAdapter extends TypeAdapter { + @override + final typeId = 1; // Put an ID you didn't use yet. + + @override + ThemeStyle read(BinaryReader reader) => ThemeStyle.values[reader.readInt()]; + + @override + void write(BinaryWriter writer, ThemeStyle obj) => writer.writeInt(obj.index); +} + +class DateFormatOptionsAdapter extends TypeAdapter { + @override + final typeId = 2; // Put an ID you didn't use yet. + + @override + DateFormatOptions read(BinaryReader reader) => DateFormatOptions.values[reader.readInt()]; + + @override + void write(BinaryWriter writer, DateFormatOptions obj) => writer.writeInt(obj.index); +} diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index ccfffda1..345c88df 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -1,3 +1,4 @@ +import 'package:autojidelna/src/_conf/adapters.hive.dart'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_global/providers/remote_config.dart'; @@ -148,6 +149,9 @@ class App { if (_initHiveExecuted) return; await Hive.initFlutter(); + Hive.registerAdapter(ThemeModeAdapter()); + Hive.registerAdapter(ThemeStyleAdapter()); + Hive.registerAdapter(DateFormatOptionsAdapter()); await Hive.openBox(Boxes.theme); await Hive.openBox(Boxes.settings); await Hive.openBox(Boxes.cache); From 714b2811f6ce961bcbb16f4cc040e5686bbdcf2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 17:27:26 +0200 Subject: [PATCH 08/57] fix theme switching --- lib/src/_global/providers/theme.provider.dart | 25 ++++++---- lib/src/ui/material_app.dart | 4 +- lib/src/ui/theme/app_themes.dart | 46 ++++++++++++++++++- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/lib/src/_global/providers/theme.provider.dart b/lib/src/_global/providers/theme.provider.dart index 8aa66d9e..f12db21d 100644 --- a/lib/src/_global/providers/theme.provider.dart +++ b/lib/src/_global/providers/theme.provider.dart @@ -44,14 +44,23 @@ class ThemeProvider extends ChangeNotifier { notifyListeners(); } - ColorScheme get colorScheme { - ColorStyle colorStyle = AppThemes.colorStyles[_themeStyle]!; - bool lightThemeMode = _themeMode == ThemeMode.light; - return ColorScheme.fromSeed( - seedColor: lightThemeMode ? colorStyle.primaryLight : colorStyle.primaryDark, - primary: lightThemeMode ? colorStyle.secondaryLight : colorStyle.secondaryDark, - brightness: lightThemeMode ? Brightness.light : Brightness.dark, - surface: _amoledMode && !lightThemeMode ? Colors.black : null, + ColorScheme colorSchemeLight(ThemeStyle themeStyle) { + ColorStyle colorStyle = AppThemes.colorStyles[themeStyle]!; + + return AppThemes.colorSchemeLight.copyWith( + primary: colorStyle.primaryLight, + secondary: colorStyle.secondaryLight, + ); + } + + ColorScheme colorSchemeDark(ThemeStyle themeStyle) { + ColorStyle colorStyle = AppThemes.colorStyles[themeStyle]!; + + return AppThemes.colorSchemeDark.copyWith( + primary: colorStyle.primaryDark, + secondary: colorStyle.secondaryDark, + surface: amoledMode ? Colors.black : const Color(0xff121212), + scrim: amoledMode ? Colors.black87 : Colors.black54, ); } } diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index 06757540..72199b52 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -58,8 +58,8 @@ class _MyAppState extends State { return MaterialApp.router( debugShowCheckedModeBanner: false, themeMode: theme.themeMode, - theme: AppThemes.theme.copyWith(colorScheme: theme.colorScheme), - darkTheme: AppThemes.theme.copyWith(colorScheme: theme.colorScheme), + theme: AppThemes.theme(theme.colorSchemeLight(theme.themeStyle), theme.amoledMode), + darkTheme: AppThemes.theme(theme.colorSchemeDark(theme.themeStyle), theme.amoledMode), locale: _locale, supportedLocales: Texts.supportedLocales, localizationsDelegates: Texts.localizationsDelegates, diff --git a/lib/src/ui/theme/app_themes.dart b/lib/src/ui/theme/app_themes.dart index 541a3ddd..fbfdb40f 100644 --- a/lib/src/ui/theme/app_themes.dart +++ b/lib/src/ui/theme/app_themes.dart @@ -60,12 +60,54 @@ class AppThemes { ), }; - static ThemeData get theme => ThemeData( + static ColorScheme get colorSchemeLight => const ColorScheme( + brightness: Brightness.light, + primary: Colors.purpleAccent, + onPrimary: Colors.white, + secondary: Color(0x7B009687), + onSecondary: Colors.white, + error: Colors.red, + onError: Colors.black, + surface: Colors.white, + onSurface: Colors.black, + surfaceContainerHighest: Colors.black12, + onSurfaceVariant: Colors.black54, + scrim: Colors.black54, + surfaceTint: Colors.black, + inverseSurface: Color(0xFF121212), + onInverseSurface: Colors.white, + ); + + static ColorScheme get colorSchemeDark => const ColorScheme( + brightness: Brightness.dark, + primary: Color(0xffbb86fc), + onPrimary: Colors.white, + secondary: Color(0xff018786), + onSecondary: Colors.white, + error: Color(0xFFCF6679), + onError: Colors.white, + surface: Color(0xff121212), + onSurface: Colors.white, + surfaceContainerHighest: Colors.white12, + onSurfaceVariant: Colors.white54, + scrim: Colors.black54, + surfaceTint: Colors.white, + inverseSurface: Color(0xFFdddddd), + onInverseSurface: Colors.black, + ); + + static ThemeData theme(ColorScheme colorScheme, bool amoledMode) => ThemeData( useMaterial3: true, applyElevationOverlayColor: true, // COLOR - // colorScheme: ColorSheme is gotten from ThemeProvider + colorScheme: colorScheme, + canvasColor: colorScheme.surface, + disabledColor: colorScheme.surfaceContainerHighest, + scaffoldBackgroundColor: colorScheme.surface, + shadowColor: Colors.transparent, + splashColor: Colors.transparent, + splashFactory: NoSplash.splashFactory, // TYPOGRAPHY & ICONOGRAPHY textTheme: textTheme, From 982b0d9eaac6c00cd7bef2d5ffaee077e4d69e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 17:28:26 +0200 Subject: [PATCH 09/57] add ThemeModePicker() --- lib/src/ui/widgets/theme_mode_picker.dart | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/src/ui/widgets/theme_mode_picker.dart diff --git a/lib/src/ui/widgets/theme_mode_picker.dart b/lib/src/ui/widgets/theme_mode_picker.dart new file mode 100644 index 00000000..ec90eaff --- /dev/null +++ b/lib/src/ui/widgets/theme_mode_picker.dart @@ -0,0 +1,29 @@ +import 'package:autojidelna/src/_global/providers/theme.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ThemeModePicker extends StatelessWidget { + const ThemeModePicker({super.key}); + + @override + Widget build(BuildContext context) { + final lang = context.l10n; + return SizedBox( + width: MediaQuery.sizeOf(context).width * .9, + child: Selector( + selector: (_, p1) => (read: p1.themeMode, set: p1.setThemeMode), + builder: (_, themeMode, __) => SegmentedButton( + showSelectedIcon: false, + selected: {themeMode.read}, + onSelectionChanged: (Set selected) => themeMode.set(selected.first), + segments: [ + ButtonSegment(value: ThemeMode.system, label: Text(lang.systemThemeMode)), + ButtonSegment(value: ThemeMode.light, label: Text(lang.lightThemeMode)), + ButtonSegment(value: ThemeMode.dark, label: Text(lang.darkThemeMode)), + ], + ), + ), + ); + } +} From 8599f556b5012fcabe584b033140479981d3e4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 17:30:33 +0200 Subject: [PATCH 10/57] add ThemeStylePicker() --- lib/src/ui/widgets/theme_style_picker.dart | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lib/src/ui/widgets/theme_style_picker.dart diff --git a/lib/src/ui/widgets/theme_style_picker.dart b/lib/src/ui/widgets/theme_style_picker.dart new file mode 100644 index 00000000..7a03aa6e --- /dev/null +++ b/lib/src/ui/widgets/theme_style_picker.dart @@ -0,0 +1,74 @@ +import 'package:autojidelna/src/_global/providers/theme.provider.dart'; +import 'package:autojidelna/src/types/theme.dart'; +import 'package:autojidelna/src/ui/theme/app_themes.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class ThemeStylePicker extends StatelessWidget { + const ThemeStylePicker({super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 225, + child: Consumer( + builder: (context, prov, _) => ListView.builder( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 16), + itemCount: ThemeStyle.values.length, + itemBuilder: (context, index) { + ThemeStyle themeStyle = ThemeStyle.values[index]; + final bool isBright = MediaQuery.platformBrightnessOf(context) == Brightness.light || prov.themeMode == ThemeMode.light; + + ThemeData theme = AppThemes.theme(isBright ? prov.colorSchemeLight(themeStyle) : prov.colorSchemeDark(themeStyle), prov.amoledMode); + + ButtonStyle style = OutlinedButton.styleFrom( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + fixedSize: const Size.fromWidth(125), + padding: EdgeInsets.zero, + side: BorderSide( + width: 3, + strokeAlign: BorderSide.strokeAlignInside, + color: ThemeStyle.values[index] == prov.themeStyle ? theme.colorScheme.primary : Colors.grey, + ), + ); + + return Theme( + data: theme, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: OutlinedButton( + style: style, + onPressed: () => prov.setThemeStyle(ThemeStyle.values[index]), + child: Column( + children: [ + SizedBox(height: 35, child: AppBar(automaticallyImplyLeading: false)), + const Divider(color: Colors.transparent), + foodTileColorSchemePreview(context, theme.colorScheme.primary), + foodTileColorSchemePreview(context, theme.colorScheme.secondary), + ], + ), + ), + ), + ); + }, + ), + ), + ); + } + + Widget foodTileColorSchemePreview(BuildContext context, Color color) { + return Card.filled( + margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Container( + height: 20, + width: 100, + margin: const EdgeInsets.fromLTRB(5, 30, 5, 5), + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(12.5), + ), + ), + ); + } +} From 7655abad380c55324333344bc4dc1ac4ceb82582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 17:38:53 +0200 Subject: [PATCH 11/57] move rest of app theme --- lib/src/ui/theme/app_themes.dart | 166 ++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/lib/src/ui/theme/app_themes.dart b/lib/src/ui/theme/app_themes.dart index fbfdb40f..5873174c 100644 --- a/lib/src/ui/theme/app_themes.dart +++ b/lib/src/ui/theme/app_themes.dart @@ -99,6 +99,8 @@ class AppThemes { static ThemeData theme(ColorScheme colorScheme, bool amoledMode) => ThemeData( useMaterial3: true, applyElevationOverlayColor: true, + materialTapTargetSize: MaterialTapTargetSize.padded, + visualDensity: VisualDensity.adaptivePlatformDensity, // COLOR colorScheme: colorScheme, @@ -111,7 +113,169 @@ class AppThemes { // TYPOGRAPHY & ICONOGRAPHY textTheme: textTheme, + typography: Typography.material2021(), - // TODO: COMPONENT THEMES + // COMPONENT THEMES + iconTheme: IconThemeData(size: 30, color: colorScheme.onSurface), + appBarTheme: AppBarTheme( + scrolledUnderElevation: amoledMode ? 0 : 2, + elevation: amoledMode ? 0 : 2, + actionsIconTheme: IconThemeData(color: colorScheme.onSurfaceVariant), + ), + cardTheme: CardTheme( + elevation: 2, + clipBehavior: Clip.hardEdge, + surfaceTintColor: colorScheme.surfaceTint, + ), + dividerTheme: DividerThemeData(color: colorScheme.surfaceContainerHighest), + drawerTheme: DrawerThemeData( + surfaceTintColor: colorScheme.surfaceTint, + backgroundColor: colorScheme.surface, + scrimColor: colorScheme.scrim, + elevation: 2, + width: 275, + ), + navigationBarTheme: NavigationBarThemeData( + indicatorColor: colorScheme.secondary, + surfaceTintColor: colorScheme.surfaceTint, + elevation: amoledMode ? 0 : null, + ), + + // Popups + snackBarTheme: SnackBarThemeData( + backgroundColor: colorScheme.inverseSurface, + elevation: amoledMode ? 0 : 2, + contentTextStyle: TextStyle(fontFamily: Fonts.body, color: colorScheme.onInverseSurface), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + behavior: SnackBarBehavior.floating, + insetPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + showCloseIcon: true, + closeIconColor: colorScheme.onInverseSurface, + ), + dialogTheme: DialogTheme( + backgroundColor: colorScheme.surface, + elevation: 3, + surfaceTintColor: colorScheme.surfaceTint, + alignment: Alignment.center, + iconColor: colorScheme.onSurface, + titleTextStyle: TextStyle( + fontFamily: Fonts.headings, + color: colorScheme.onSurface, + fontSize: 20, + fontWeight: FontWeight.bold, + ), + contentTextStyle: const TextStyle(fontFamily: Fonts.body, fontSize: 15), + actionsPadding: const EdgeInsets.fromLTRB(12, 0, 16, 7), + ), + + // Inputs + inputDecorationTheme: const InputDecorationTheme( + alignLabelWithHint: true, + isDense: true, + errorMaxLines: 1, + labelStyle: TextStyle(fontFamily: Fonts.body), + floatingLabelAlignment: FloatingLabelAlignment.start, + hintStyle: TextStyle(fontFamily: Fonts.body), + helperStyle: TextStyle(fontFamily: Fonts.body), + border: OutlineInputBorder(), + ), + + // List tiles + listTileTheme: ListTileThemeData( + //shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + dense: false, + selectedColor: colorScheme.primary, + iconColor: colorScheme.primary.withOpacity(.75), + titleTextStyle: TextStyle( + fontSize: 19, + fontFamily: Fonts.body, + fontWeight: FontWeight.w400, + color: colorScheme.onSurface, + ), + subtitleTextStyle: TextStyle( + fontSize: 13, + fontFamily: Fonts.body, + color: colorScheme.onSurfaceVariant, + ), + visualDensity: VisualDensity.comfortable, + ), + expansionTileTheme: ExpansionTileThemeData( + collapsedTextColor: colorScheme.primary, + textColor: colorScheme.onSurface, + childrenPadding: const EdgeInsets.only(bottom: 8), + ), + bottomSheetTheme: BottomSheetThemeData( + modalElevation: 1, + clipBehavior: Clip.hardEdge, + surfaceTintColor: colorScheme.surfaceTint, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + side: BorderSide(color: amoledMode ? colorScheme.surfaceContainerHighest : Colors.transparent, strokeAlign: 1), + ), + ), + + // Buttons + switchTheme: const SwitchThemeData(splashRadius: 0), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ButtonStyle( + textStyle: const WidgetStatePropertyAll( + TextStyle( + fontFamily: Fonts.headings, + fontSize: 18, + fontWeight: FontWeight.w500, + height: 1.25, + ), + ), + backgroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) return colorScheme.surfaceContainerHighest; // Disabled color + return colorScheme.surface; // Regular color + }), + foregroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) return colorScheme.onSurfaceVariant; + return colorScheme.onSurface; + }), + fixedSize: const WidgetStatePropertyAll(Size.fromHeight(50)), + splashFactory: InkRipple.splashFactory, + alignment: Alignment.center, + shadowColor: const WidgetStatePropertyAll(Colors.transparent), + elevation: const WidgetStatePropertyAll(4), + ), + ), + iconButtonTheme: const IconButtonThemeData( + style: ButtonStyle(splashFactory: NoSplash.splashFactory), + ), + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + foregroundColor: WidgetStatePropertyAll(colorScheme.onSurface), + textStyle: const WidgetStatePropertyAll( + TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.25, + ), + ), + splashFactory: NoSplash.splashFactory, + overlayColor: const WidgetStatePropertyAll(Colors.transparent), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: ButtonStyle( + side: WidgetStatePropertyAll(BorderSide(width: 1.75, color: colorScheme.onSurfaceVariant)), + ), + ), + segmentedButtonTheme: SegmentedButtonThemeData( + style: ButtonStyle( + backgroundColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.selected)) { + return colorScheme.primary; + } + return Colors.transparent; + }, + ), + ), + ), ); } From cef3127218525ea03508a3620509e4bac4b962b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 20:04:09 +0200 Subject: [PATCH 12/57] delete unused pages --- lib/src/_routing/app_router.dart | 11 +- lib/src/_routing/app_router.gr.dart | 253 ++---------------- lib/src/ui/pages/crashlytics_page.dart | 23 -- lib/src/ui/pages/demo_page.dart | 47 ---- lib/src/ui/pages/router_page.dart | 26 +- .../localization/localizations_page.dart | 34 --- .../settings/routing/routing_param_page.dart | 39 --- .../routing_path_param_detail_page.dart | 29 -- .../routing_query_param_detail_page.dart | 32 --- lib/src/ui/pages/settings/settings_page.dart | 32 --- .../crashlytics_page_appbar.dart | 18 -- .../router_page_appbars/demo_page_appbar.dart | 24 -- .../login_page_appbar.dart | 21 -- pubspec.lock | 8 - 14 files changed, 29 insertions(+), 568 deletions(-) delete mode 100644 lib/src/ui/pages/crashlytics_page.dart delete mode 100644 lib/src/ui/pages/demo_page.dart delete mode 100644 lib/src/ui/pages/settings/localization/localizations_page.dart delete mode 100644 lib/src/ui/pages/settings/routing/routing_param_page.dart delete mode 100644 lib/src/ui/pages/settings/routing/routing_path_param_detail_page.dart delete mode 100644 lib/src/ui/pages/settings/routing/routing_query_param_detail_page.dart delete mode 100644 lib/src/ui/pages/settings/settings_page.dart delete mode 100644 lib/src/ui/widgets/router_page_appbars/crashlytics_page_appbar.dart delete mode 100644 lib/src/ui/widgets/router_page_appbars/demo_page_appbar.dart delete mode 100644 lib/src/ui/widgets/router_page_appbars/login_page_appbar.dart diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index 34327e00..b3d4a73a 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -11,20 +11,11 @@ class AppRouter extends RootStackRouter { initial: true, path: '/', children: [ - AutoRoute(page: DemoPage.page, path: 'demo'), - AutoRoute(page: CrashlyticsPage.page, path: '', initial: true), - AutoRoute( - page: SettingsPage.page, - path: 'settings', - ), + // TODO ], ), AutoRoute(page: RequestPermissionPage.page, path: '/request-permission'), AutoRoute(page: DebugPage.page, path: '/demo/debug'), - AutoRoute(page: RoutingParamPage.page, path: '/settings/param'), - AutoRoute(page: LocalizationsPage.page, path: '/settings/localizations'), - AutoRoute(page: RoutingQueryParamDetailPage.page, path: '/settings/param/detail'), - AutoRoute(page: RoutingPathParamDetailPage.page, path: '/settings/param/:filmid'), RedirectRoute(path: '*', redirectTo: '/'), ]; } diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index d26154f1..96acd089 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -8,47 +8,16 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i11; -import 'package:autojidelna/src/ui/pages/crashlytics_page.dart' as _i1; -import 'package:autojidelna/src/ui/pages/debug_page.dart' as _i2; -import 'package:autojidelna/src/ui/pages/demo_page.dart' as _i3; -import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i5; -import 'package:autojidelna/src/ui/pages/router_page.dart' as _i6; -import 'package:autojidelna/src/ui/pages/settings/localization/localizations_page.dart' - as _i4; -import 'package:autojidelna/src/ui/pages/settings/routing/routing_param_page.dart' - as _i7; -import 'package:autojidelna/src/ui/pages/settings/routing/routing_path_param_detail_page.dart' - as _i8; -import 'package:autojidelna/src/ui/pages/settings/routing/routing_query_param_detail_page.dart' - as _i9; -import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i10; -import 'package:flutter/foundation.dart' as _i12; -import 'package:flutter/material.dart' as _i13; +import 'package:auto_route/auto_route.dart' as _i4; +import 'package:autojidelna/src/ui/pages/debug_page.dart' as _i1; +import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i2; +import 'package:autojidelna/src/ui/pages/router_page.dart' as _i3; +import 'package:flutter/foundation.dart' as _i5; /// generated route for -/// [_i1.CrashlyticsPage] -class CrashlyticsPage extends _i11.PageRouteInfo { - const CrashlyticsPage({List<_i11.PageRouteInfo>? children}) - : super( - CrashlyticsPage.name, - initialChildren: children, - ); - - static const String name = 'CrashlyticsPage'; - - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - return const _i1.CrashlyticsPage(); - }, - ); -} - -/// generated route for -/// [_i2.DebugPage] -class DebugPage extends _i11.PageRouteInfo { - const DebugPage({List<_i11.PageRouteInfo>? children}) +/// [_i1.DebugPage] +class DebugPage extends _i4.PageRouteInfo { + const DebugPage({List<_i4.PageRouteInfo>? children}) : super( DebugPage.name, initialChildren: children, @@ -56,60 +25,22 @@ class DebugPage extends _i11.PageRouteInfo { static const String name = 'DebugPage'; - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - return const _i2.DebugPage(); - }, - ); -} - -/// generated route for -/// [_i3.DemoPage] -class DemoPage extends _i11.PageRouteInfo { - const DemoPage({List<_i11.PageRouteInfo>? children}) - : super( - DemoPage.name, - initialChildren: children, - ); - - static const String name = 'DemoPage'; - - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - return const _i3.DemoPage(); - }, - ); -} - -/// generated route for -/// [_i4.LocalizationsPage] -class LocalizationsPage extends _i11.PageRouteInfo { - const LocalizationsPage({List<_i11.PageRouteInfo>? children}) - : super( - LocalizationsPage.name, - initialChildren: children, - ); - - static const String name = 'LocalizationsPage'; - - static _i11.PageInfo page = _i11.PageInfo( + static _i4.PageInfo page = _i4.PageInfo( name, builder: (data) { - return const _i4.LocalizationsPage(); + return const _i1.DebugPage(); }, ); } /// generated route for -/// [_i5.RequestPermissionPage] +/// [_i2.RequestPermissionPage] class RequestPermissionPage - extends _i11.PageRouteInfo { + extends _i4.PageRouteInfo { RequestPermissionPage({ - _i12.Key? key, + _i5.Key? key, void Function(bool)? onResult, - List<_i11.PageRouteInfo>? children, + List<_i4.PageRouteInfo>? children, }) : super( RequestPermissionPage.name, args: RequestPermissionPageArgs( @@ -121,12 +52,12 @@ class RequestPermissionPage static const String name = 'RequestPermissionPage'; - static _i11.PageInfo page = _i11.PageInfo( + static _i4.PageInfo page = _i4.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const RequestPermissionPageArgs()); - return _i5.RequestPermissionPage( + return _i2.RequestPermissionPage( key: args.key, onResult: args.onResult, ); @@ -140,7 +71,7 @@ class RequestPermissionPageArgs { this.onResult, }); - final _i12.Key? key; + final _i5.Key? key; final void Function(bool)? onResult; @@ -151,9 +82,9 @@ class RequestPermissionPageArgs { } /// generated route for -/// [_i6.RouterPage] -class RouterPage extends _i11.PageRouteInfo { - const RouterPage({List<_i11.PageRouteInfo>? children}) +/// [_i3.RouterPage] +class RouterPage extends _i4.PageRouteInfo { + const RouterPage({List<_i4.PageRouteInfo>? children}) : super( RouterPage.name, initialChildren: children, @@ -161,150 +92,10 @@ class RouterPage extends _i11.PageRouteInfo { static const String name = 'RouterPage'; - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - return const _i6.RouterPage(); - }, - ); -} - -/// generated route for -/// [_i7.RoutingParamPage] -class RoutingParamPage extends _i11.PageRouteInfo { - const RoutingParamPage({List<_i11.PageRouteInfo>? children}) - : super( - RoutingParamPage.name, - initialChildren: children, - ); - - static const String name = 'RoutingParamPage'; - - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - return const _i7.RoutingParamPage(); - }, - ); -} - -/// generated route for -/// [_i8.RoutingPathParamDetailPage] -class RoutingPathParamDetailPage - extends _i11.PageRouteInfo { - RoutingPathParamDetailPage({ - _i13.Key? key, - required String filmid, - List<_i11.PageRouteInfo>? children, - }) : super( - RoutingPathParamDetailPage.name, - args: RoutingPathParamDetailPageArgs( - key: key, - filmid: filmid, - ), - rawPathParams: {'filmid': filmid}, - initialChildren: children, - ); - - static const String name = 'RoutingPathParamDetailPage'; - - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - final pathParams = data.inheritedPathParams; - final args = data.argsAs( - orElse: () => RoutingPathParamDetailPageArgs( - filmid: pathParams.getString('filmid'))); - return _i8.RoutingPathParamDetailPage( - key: args.key, - filmid: args.filmid, - ); - }, - ); -} - -class RoutingPathParamDetailPageArgs { - const RoutingPathParamDetailPageArgs({ - this.key, - required this.filmid, - }); - - final _i13.Key? key; - - final String filmid; - - @override - String toString() { - return 'RoutingPathParamDetailPageArgs{key: $key, filmid: $filmid}'; - } -} - -/// generated route for -/// [_i9.RoutingQueryParamDetailPage] -class RoutingQueryParamDetailPage - extends _i11.PageRouteInfo { - RoutingQueryParamDetailPage({ - _i13.Key? key, - int? filmid, - List<_i11.PageRouteInfo>? children, - }) : super( - RoutingQueryParamDetailPage.name, - args: RoutingQueryParamDetailPageArgs( - key: key, - filmid: filmid, - ), - rawQueryParams: {'key': filmid}, - initialChildren: children, - ); - - static const String name = 'RoutingQueryParamDetailPage'; - - static _i11.PageInfo page = _i11.PageInfo( - name, - builder: (data) { - final queryParams = data.queryParams; - final args = data.argsAs( - orElse: () => RoutingQueryParamDetailPageArgs( - filmid: queryParams.optInt('key'))); - return _i9.RoutingQueryParamDetailPage( - key: args.key, - filmid: args.filmid, - ); - }, - ); -} - -class RoutingQueryParamDetailPageArgs { - const RoutingQueryParamDetailPageArgs({ - this.key, - this.filmid, - }); - - final _i13.Key? key; - - final int? filmid; - - @override - String toString() { - return 'RoutingQueryParamDetailPageArgs{key: $key, filmid: $filmid}'; - } -} - -/// generated route for -/// [_i10.SettingsPage] -class SettingsPage extends _i11.PageRouteInfo { - const SettingsPage({List<_i11.PageRouteInfo>? children}) - : super( - SettingsPage.name, - initialChildren: children, - ); - - static const String name = 'SettingsPage'; - - static _i11.PageInfo page = _i11.PageInfo( + static _i4.PageInfo page = _i4.PageInfo( name, builder: (data) { - return const _i10.SettingsPage(); + return const _i3.RouterPage(); }, ); } diff --git a/lib/src/ui/pages/crashlytics_page.dart b/lib/src/ui/pages/crashlytics_page.dart deleted file mode 100644 index f397454e..00000000 --- a/lib/src/ui/pages/crashlytics_page.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/logic/crash_logic.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class CrashlyticsPage extends StatelessWidget { - const CrashlyticsPage({super.key}); - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(lang.crashlyticsPage), - TextButton(onPressed: crashTestFunction, child: Text(lang.crashlyticsTestCrash)), - ], - ), - ); - } -} diff --git a/lib/src/ui/pages/demo_page.dart b/lib/src/ui/pages/demo_page.dart deleted file mode 100644 index 5a1d8ea5..00000000 --- a/lib/src/ui/pages/demo_page.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class DemoPage extends StatefulWidget { - const DemoPage({ - super.key, - }); - - @override - State createState() => _DemoPageState(); -} - -class _DemoPageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - - return Scaffold( - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(lang.buttonPushed), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - child: const Icon(Icons.add), - ), - ); - } -} diff --git a/lib/src/ui/pages/router_page.dart b/lib/src/ui/pages/router_page.dart index a4f01b8e..38bfbbce 100644 --- a/lib/src/ui/pages/router_page.dart +++ b/lib/src/ui/pages/router_page.dart @@ -1,9 +1,6 @@ import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/_routing/app_router.gr.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/widgets/router_page_appbars/default_appbar.dart'; -import 'package:autojidelna/src/ui/widgets/router_page_appbars/demo_page_appbar.dart'; -import 'package:autojidelna/src/ui/widgets/router_page_appbars/login_page_appbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; @@ -37,9 +34,7 @@ class _RouterPageState extends State { } final List routes = [ - const DemoPage(), - const CrashlyticsPage(), - const SettingsPage(), + // TODO ]; @override @@ -57,29 +52,20 @@ class _RouterPageState extends State { ) : null; - final defaultAppBar = DefaultAppbar( - leading: leading, - leadingWidth: leadingWidth, - ); + final defaultAppBar = DefaultAppbar(leading: leading, leadingWidth: leadingWidth); // use null to not show an appbar for a specific page. Use the defaultAppBar for a default appbar // note: using null will not show the appbar at all. This includes the navigation drawer button. Use with caution. final List appBars = [ - (context) => DemoPageAppBar(leading: leading, leadingWidth: leadingWidth), - (context) => defaultAppBar, - (context) => SettingsPageAppBar(leading: leading, leadingWidth: leadingWidth), + // TODO ]; final List destinations = [ - NavigationDestination(label: lang.counting, icon: const Icon(Icons.numbers)), - NavigationDestination(label: lang.crashlytics, icon: const Icon(Icons.bug_report)), - NavigationDestination(label: lang.settings, icon: const Icon(Icons.settings)), + // TODO ]; final List secondaryBodies = [ - null, - Container(color: Colors.red), - Container(color: Colors.green), + // TODO ]; assert( @@ -97,7 +83,7 @@ class _RouterPageState extends State { contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(128)), leading: const Icon(Icons.menu), - title: const Text('Menu'), + title: const Text('Menu'), // TODO: add to localizations onTap: () => changeExtention(context), ), ), diff --git a/lib/src/ui/pages/settings/localization/localizations_page.dart b/lib/src/ui/pages/settings/localization/localizations_page.dart deleted file mode 100644 index 891ff33d..00000000 --- a/lib/src/ui/pages/settings/localization/localizations_page.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/_global/app.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/lang/supported_locales.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class LocalizationsPage extends StatelessWidget { - const LocalizationsPage({super.key}); - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return Scaffold( - appBar: AppBar( - title: Text(lang.localization), - ), - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () => App.translate(Locales.en), - child: Text(lang.languageEnglish), - ), - ElevatedButton( - onPressed: () => App.translate(Locales.cs), - child: Text(lang.languageCzech), - ), - ], - ), - ), - ); - } -} diff --git a/lib/src/ui/pages/settings/routing/routing_param_page.dart b/lib/src/ui/pages/settings/routing/routing_param_page.dart deleted file mode 100644 index 15af5d67..00000000 --- a/lib/src/ui/pages/settings/routing/routing_param_page.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/_routing/app_router.gr.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class RoutingParamPage extends StatelessWidget { - const RoutingParamPage({super.key}); - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return Scaffold( - appBar: AppBar( - title: Text(lang.routingParamPage), - ), - body: Center( - child: Column( - children: [ - Text(lang.routingParamPageDetail), - Text(lang.routingParamPageDetail2), - Form( - child: TextFormField( - decoration: InputDecoration(labelText: lang.routingParamQueryFilmId), - onFieldSubmitted: (String value) async => context.router.push(RoutingQueryParamDetailPage(filmid: int.tryParse(value))), - ), - ), - Form( - child: TextFormField( - decoration: InputDecoration(labelText: lang.routingParamFilmId), - onFieldSubmitted: (String value) async => context.router.push(RoutingPathParamDetailPage(filmid: value)), - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/src/ui/pages/settings/routing/routing_path_param_detail_page.dart b/lib/src/ui/pages/settings/routing/routing_path_param_detail_page.dart deleted file mode 100644 index 2b388c8e..00000000 --- a/lib/src/ui/pages/settings/routing/routing_path_param_detail_page.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class RoutingPathParamDetailPage extends StatelessWidget { - const RoutingPathParamDetailPage({super.key, @PathParam() required this.filmid}); - final String filmid; - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - final int? filmId = int.tryParse(filmid); - return Scaffold( - appBar: AppBar( - title: Text(lang.routingParamDetailPageDetail), - ), - body: Center( - child: Column( - children: [ - Text(lang.routingParamDetailPageDetail1), - Text(lang.routingParamDetailPageDetail2), - Text(lang.routingParamDetailPageDetail3(filmId.toString())), - ], - ), - ), - ); - } -} diff --git a/lib/src/ui/pages/settings/routing/routing_query_param_detail_page.dart b/lib/src/ui/pages/settings/routing/routing_query_param_detail_page.dart deleted file mode 100644 index 2f5b0344..00000000 --- a/lib/src/ui/pages/settings/routing/routing_query_param_detail_page.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class RoutingQueryParamDetailPage extends StatelessWidget { - const RoutingQueryParamDetailPage({ - super.key, - @QueryParam('key') this.filmid, - }); - - final int? filmid; - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return Scaffold( - appBar: AppBar( - title: Text(lang.routingParamDetailPageDetail), - ), - body: Center( - child: Column( - children: [ - Text(lang.routingParamDetailPageDetail1), - Text(lang.routingParamDetailPageDetail2), - Text(lang.routingParamDetailPageDetail3(filmid.toString())), - ], - ), - ), - ); - } -} diff --git a/lib/src/ui/pages/settings/settings_page.dart b/lib/src/ui/pages/settings/settings_page.dart deleted file mode 100644 index 2731894f..00000000 --- a/lib/src/ui/pages/settings/settings_page.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/_routing/app_router.gr.dart'; -import 'package:autojidelna/src/ui/widgets/buttons/test_notifications.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return Scaffold( - body: Center( - child: Column( - children: [ - ElevatedButton( - onPressed: () async => context.router.push(const RoutingParamPage()), - child: Text(lang.routingGoToParamDetailPage), - ), - ElevatedButton( - onPressed: () async => context.router.push(const LocalizationsPage()), - child: Text(lang.language), - ), - const NotificationActionButton(), - ], - ), - ), - ); - } -} diff --git a/lib/src/ui/widgets/router_page_appbars/crashlytics_page_appbar.dart b/lib/src/ui/widgets/router_page_appbars/crashlytics_page_appbar.dart deleted file mode 100644 index ec358be6..00000000 --- a/lib/src/ui/widgets/router_page_appbars/crashlytics_page_appbar.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; - -class CrashliticsPageAppBar extends StatelessWidget implements PreferredSizeWidget { - const CrashliticsPageAppBar({super.key, this.leading, this.leadingWidth}); - final Widget? leading; - final double? leadingWidth; - - @override - Widget build(BuildContext context) { - return AppBar( - leading: leading, - leadingWidth: leadingWidth, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); -} diff --git a/lib/src/ui/widgets/router_page_appbars/demo_page_appbar.dart b/lib/src/ui/widgets/router_page_appbars/demo_page_appbar.dart deleted file mode 100644 index 9ee22173..00000000 --- a/lib/src/ui/widgets/router_page_appbars/demo_page_appbar.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/ui/widgets/buttons/about_app_button_widget.dart'; -import 'package:flutter/material.dart'; - -class DemoPageAppBar extends StatelessWidget implements PreferredSizeWidget { - const DemoPageAppBar({super.key, this.leading, this.leadingWidth}); - final Widget? leading; - final double? leadingWidth; - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - actions: const [AboutAppButton()], - title: Text(lang.demoPageTitle), - leading: leading, - leadingWidth: leadingWidth, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); -} diff --git a/lib/src/ui/widgets/router_page_appbars/login_page_appbar.dart b/lib/src/ui/widgets/router_page_appbars/login_page_appbar.dart deleted file mode 100644 index 6e97ce2b..00000000 --- a/lib/src/ui/widgets/router_page_appbars/login_page_appbar.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:flutter/material.dart'; - -class SettingsPageAppBar extends StatelessWidget implements PreferredSizeWidget { - const SettingsPageAppBar({super.key, this.leading, this.leadingWidth}); - final Widget? leading; - final double? leadingWidth; - - @override - Widget build(BuildContext context) { - final lang = context.l10n; - return AppBar( - title: Text(lang.routingTestPage), - leading: leading, - leadingWidth: leadingWidth, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); -} diff --git a/pubspec.lock b/pubspec.lock index e0332639..e5d77e2e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -273,14 +273,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" dart_console: dependency: transitive description: From 3cfe04304ea19af19abfd900eb13bc2881123dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 20:08:28 +0200 Subject: [PATCH 13/57] update default appbar --- .../ui/widgets/router_page_appbars/default_appbar.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/src/ui/widgets/router_page_appbars/default_appbar.dart b/lib/src/ui/widgets/router_page_appbars/default_appbar.dart index a5b7a103..ae3efae6 100644 --- a/lib/src/ui/widgets/router_page_appbars/default_appbar.dart +++ b/lib/src/ui/widgets/router_page_appbars/default_appbar.dart @@ -1,15 +1,21 @@ import 'package:flutter/material.dart'; class DefaultAppbar extends StatelessWidget implements PreferredSizeWidget { - const DefaultAppbar({super.key, this.leading, this.leadingWidth}); + const DefaultAppbar({super.key, this.leading, this.leadingWidth, this.title, this.actions}); final Widget? leading; final double? leadingWidth; + final Widget? title; + final List? actions; @override Widget build(BuildContext context) { + actions?.add(const VerticalDivider(color: Colors.transparent)); + return AppBar( leading: leading, leadingWidth: leadingWidth, + title: title, + actions: actions, ); } From b3807cad621e29157a56ea15133d284ccafcf3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 20:46:35 +0200 Subject: [PATCH 14/57] remove unused localized messages --- lib/src/lang/app_cs.arb | 344 +----- lib/src/lang/output/texts.dart | 1292 +-------------------- lib/src/lang/output/texts_cs.dart | 718 +----------- lib/src/ui/widgets/theme_mode_picker.dart | 6 +- 4 files changed, 69 insertions(+), 2291 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index f291a826..595b4e6f 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -1,354 +1,32 @@ { "@@locale": "cs", - "about": "O aplikaci", - "aboutCheckForUpdates": "Zkontrolovat aktualizace", - "aboutCopyRight": "© 2023 - {time} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3", - "@aboutCopyRight": { - "placeholders": { - "time": { - "type": "DateTime", - "format": "y" - } - } - }, - "aboutLatestVersion": "Aktuálně jste na nejnovější verzi aplikace 👍", - "aboutSourceCode": "Zdrojový kód", - "aboutVersionSubtitle": "{arg, select, true{Debug} other{Stable}} {version}", - "@aboutVersionSubtitle": { - "description": "aboutVersionSubtitle", + "appName": "Autojídelna", + "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", + "gettingDataNotifications": "Získávám data pro oznámení", + "internetConnectionState": "{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}", + "@internetConnectionState": { + "description": "internetConnectionState", "placeholders": { "arg": { "type": "String", "example": "true" - }, - "version": { - "type": "String" } } }, - "account": "Účet", - "accountStatus": "Stav účtu", - "accountcreationTime": "Čas vytvoření účtu: {date}", - "addAccount": "Přidat účet", - "allergens": "Alergeny", - "allowPermission": "Udělit oprávnění", - "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", - "appName": "Autojídelna", - "burzaAlertDialogContent": "Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.", - "buttonPushed": "Tlačítko jste stiskli tolikrát:", - "cancel": "Zrušit", - "category": "Kategorie", - "changeAccount": "Změnit účet", - "connectedToANetwork": "Připojeno k síti", - "connectedToTheInternet": "Připojeno k internetu", - "convenience": "Pohodlí", - "counting": "Počítání", - "crashlytics": "Crashlytics", - "crashlyticsPage": "Stránka Crashlytics", - "crashlyticsTestCrash": "Testovací pád Crashlytics yohooo!", - "createAccount": "Vytvořit účet s e-mailem a heslem", - "credit": "Kredit: {ammount} Kč", - "@credit": { - "placeholders": { - "ammount": { - "type": "double", - "format": "decimalPattern" - } - } - }, - "currency": "Kč", - "darkThemeMode": "Tmavý", - "dataCollectionAgreement": "Používáním aplikace souhlasíte se zasíláním anonymních dat. ", - "dateFormat": "Formát dat", "debug": "Debug", - "deleteAccount": "Smazat účet", - "deleteAccountConfirm": "Smazat účet", - "deleteAccountDialog": "Opravdu chcete smazat svůj účet?", - "demoPageTitle": "Demo stránka", - "disconnectedFromANetwork": "Odpojeno od sítě", - "disconnectedFromTheInternet": "Odpojeno od internetu", - "dochazejiciKreditChannelDescription": "Oznámení o tom, zda vám dochází kredit týden dopředu pro {username}", - "@dochazejiciKreditChannelDescription": { - "placeholders": { - "username": { - "type": "String" - } - } - }, - "dochazejiciKreditChannelName": "Docházející kredit", - "dontShowAgain": "Příště nezobrazovat", - "drinks": "Pití", - "email": "E-mail", - "enterAValidEmailAddress": "Zadejte platnou e-mailovou adresu", - "enterYourEmail": "Zadejte svůj e-mail", - "enterYourPassword": "Zadejte své heslo", - "errorsBadConnection": "Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později", - "errorsBadLogin": "Nesprávné přihlašovací údaje", - "errorsBadPassword": "Špatné heslo nebo uživatelské jméno", - "errorsBadUrl": "Nesprávné Url", - "errorsChangelog": "Nepodařilo se získat změny :/", - "errorsChybaPriDavaniNaBurzu": "Nastala chyba při dávání jídla na burzu", - "errorsChybaPriRuseni": "Nastala chyba při rušení objednávky", - "errorsDownloadingApp": "Aktualizace aplikace selhala", - "errorsDownloadingAppDetail": "Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.", - "errorsJidloNeniNaBurze": "Jídlo není na burze", - "errorsLoad": "Selhalo načítání jídelníčku", - "errorsLoadingData": "Nastala chyba při načítání dat", - "errorsLoginFailed": "Přihlášení se nezdařilo", - "errorsLoginFailedDetail": "Při přihlašování došlo k chybě: {error}", - "@errorsLoginFailedDetail": { - "placeholders": { - "error": { - "type": "String" - } - } - }, - "errorsNelzeObjednat": "Oběd nelze objednat", - "errorsNelzeObjednatKredit": "Oběd nelze objednat - Nedostatečný kredit.", - "errorsNoInternet": "Nemáte připojení k internetu", - "errorsObedNelzeZrusit": "Oběd nelze zrušit. Platnost objednávky vypršela.", - "errorsObjednavaniJidla": "Nastala chyba při objednávání jídla", - "errorsUndefined": "Nastala Chyba", - "errorsUpdatingData": "Nastala chyba při aktualizaci dat", - "gettingDataNotifications": "Získávám data pro oznámení", - "goBack": "Jít zpět", - "goToSettings": "Jít na nastavení", - "jidloChannelDescription": "Oznámení každý den o tom jaké je dnes jídlo pro {username}", - "@jidloChannelDescription": { - "placeholders": { - "username": { - "type": "String" - } - } - }, - "jidloChannelName": "Dnešní jídlo", "language": "Jazyk", "languageCzech": "Čeština", "languageEnglish": "Angličtina", - "languageName": "Čeština", - "lastSignInTime": "Čas posledního přihlášení: {date}", - "licenses": "Licence", - "lightThemeMode": "Světlý", - "listUi": "List UI", - "localization": "Lokalizace", - "location": "Výdejna", - "locationsUnknown": "Neznámá výdejna", - "loggedIn": "Přihlášen: {bool}", - "login": "přihlásit se", - "loginButton": "Přihlásit se", - "loginPasswordFieldHint": "Zadejte prosím své heslo", - "loginPasswordFieldLabel": "Heslo", - "loginUrlFieldHint": "Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz", - "loginUrlFieldLabel": "Url stránky icanteen - např. jidelna.trebesin.cz", - "loginUserFieldHint": "Zadejte prosím své uživatelské jméno", - "loginUserFieldLabel": "Uživatelské jméno", - "logoutConfirm": "Odhlásit se", - "logoutUSure": "Opravdu se chcete odhlásit?", - "mainCourse": "Hlavní chod", - "menu": "Jídelníček", - "more": "Více", - "moreInfo": "Více informací.", - "name": "Jméno", - "nedostatekKreditu": "Nedostatek kreditu", - "neededPermission": "Potřebné oprávnění", - "neededPermissionDescription_1": "Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.", - "neededPermissionDescription_2": "Ta může vypadat takto:", - "neededPermissionDescription_3": "Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.", - "nelzeObjednat": "Nelze objednat", - "nelzeZrusit": "Nelze zrušit", + "login": "Přihlásit se", "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", - "notificationDochaziVamKredit": "Dochází vám kredit!", - "notificationKreditPro": "Kredit pro {first} {last}: {ammount} Kč", - "@notificationKreditPro": { - "placeholders": { - "first": { - "type": "String" - }, - "last": { - "type": "String" - }, - "ammount": { - "type": "String" - } - } - }, - "notificationObjednejteSi": "Objednejte si na příští týden", - "notificationObjednejteSiDetail": "Uživatel {fist} {last} si stále ještě neobjenal na příští týden", - "@notificationObjednejteSiDetail": { - "placeholders": { - "first": { - "type": "String" - }, - "last": { - "type": "String" - } - } - }, - "notificationZtlumit": "Ztlumit na týden", - "notifications": "Oznámení", - "notificationsFor": "Oznámení pro {username}", - "@notificationsFor": { - "placeholders": { - "username": { - "type": "String" - } - } - }, - "objednanoChannelDescription": "Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro {username}", - "@objednanoChannelDescription": { - "placeholders": { - "username": { - "type": "String" - } - } - }, - "objednanoChannelName": "Objednáno?", - "objednat": "Objednat", - "objednatAction": "Objednat náhodně", - "objednatZBurzy": "Objednat z burzy", - "odebratZBurzy": "Odebrat z burzy", - "ok": "OK", - "orders": "Objednávky", - "ordersWithAutojidelna": "Objednávky s Autojídelnou: {ammount}", - "@ordersWithAutojidelna": { - "placeholders": { - "ammount": { - "type": "int" - } - } - }, - "other": "Ostatní", - "otherDescription": "Ostatní oznámení, např. chybové hlášky", "password": "Heslo", - "passwordMustBeAtLeast6CharactersLong": "Heslo musí mít alespoň 6 znaků", "patch": "patch", - "paymentAccountNumber": "Číslo účtu", - "paymentInfo": "Platební Údaje", - "personalInfo": "Osobní Údaje", - "pickLocation": "Vyberte výdejnu ", - "popupChangelogNotAvailable": "Changelog není k dispozici", - "popupNewUpdateInfo": "Nová verze přináší: ", - "popupNewVersionAvailable": "Nová verze aplikace - {version}", - "@popupNewVersionAvailable": { - "placeholders": { - "version": { - "type": "String" - } - } - }, - "popupNotNow": "Teď ne", - "popupShowOnGithub": "Zobrazit na Githubu", - "popupUpdate": "Aktualizovat", - "privacyPolicy": "Zásady ochrany osobních údajů", - "providerId": "ID poskytovatele: {id}", - "remoteConfig": "Vzdálená konfigurace", "requestNotificationPermission": "Požádat o povolení notifikací", - "resetPassword": "Obnovit heslo", - "routingGoToDetailDetail": "Jít na podrobnosti podrobností", - "routingGoToDetailPage": "Jít na podrobnosti stránky", - "routingGoToParamDetailPage": "Jít na podrobnosti stránky s parametry", - "routingParamDetailPageDetail": "Stránka s podrobnostmi o parametrech směrování", - "routingParamDetailPageDetail1": "Toto je stránka s podrobnostmi o parametrech směrování.", - "routingParamDetailPageDetail2": "Slouží k testování směrování s parametry.", - "routingParamDetailPageDetail3": "Film ID: {filmId}", - "routingParamFilmId": "Cesta param Film ID", - "routingParamPage": "Stránka s parametry směrování", - "routingParamPageDetail": "Toto je stránka s parametry směrování.", - "routingParamPageDetail2": "Slouží k testování směrování s parametry.", - "routingParamQueryFilmId": "Dotaz param Film ID", - "routingTestDetailDetail": "Podrobnosti o testování směrování", - "routingTestDetailDetailText": "Toto je podostránka s podrobnostmi o testování směrování.", - "routingTestPage": "Nastavení", - "routingTestPageDetail": "Toto je stránka s testováním směrování.", - "routingTestPageDetail1": "Slouží k testování směrování.", - "secret": "tajemství", - "secretPage": "Tajná stránka", "settings": "Nastavení", - "settingsAmoled": "AMOLED mód", - "settingsAmoledSub": "Přidej se k temné straně síly!", - "settingsAnotherOptions": "Další možnosti v nastavení systému...", - "settingsAppearence": "Vzhled", - "settingsCalendarBigMarkers": "Velké ukazatele v kalendáři", - "settingsDataCollection": "Shromažďování údajů", - "settingsDataCollectionDescription_1": "Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve ", - "settingsDataCollectionDescription_2": "Zdrojovém kódu", - "settingsDataCollectionDescription_3": " nebo v ", - "settingsDataCollectionDescription_4": "Zásadách ochrany osobních údajů.", - "settingsDebugForceNotifications": "Force send notifications", - "settingsDebugNotifications": "Send Notifications", - "settingsDebugOptions": "Debug Options", - "settingsDisplay": "Zobrazení", - "settingsNemateObjednano": "Nemáte objednáno na příští týden", - "settingsNotificationFor": "Oznámení pro {username}", - "@settingsNotificationFor": { - "placeholders": { - "username": { - "type": "String" - } - } - }, - "settingsNotificationTime": "Čas oznámení: ", - "settingsRelativeTimestamps": "Relativní časové značky", - "settingsRelativeTimestampsSub": "„Dnes“ místo „{date}“", - "@settingsRelativeTimestampsSub": { - "placeholders": { - "date": { - "type": "String" - } - } - }, - "settingsSkipWeekends": "Přeskakovat víkendy", - "settingsStopDataCollection": "Zastavit sledování analytických služeb", - "settingsTheme": "Schéma", - "settingsTitleCredit": "Nízký credit", - "settingsTitleTodaysFood": "Dnešní jídlo", - "shareApp": "Sdílet aplikaci", - "shareDescription": "Autojídelna (aplikace na objednávání jídla)", - "showLocale": "Zobrazit lokalizaci", - "sideDish": "Přílohy", - "signInAnonymously": "Přihlásit se anonymně", - "signInWithApple": "Přihlásit se pomocí Apple", - "signInWithEmailAndPassword": "Přihlásit se pomocí e-mailu a hesla", - "signInWithGoogle": "Přihlásit se pomocí Google", "signOut": "Odhlásit se", - "soup": "Polévka", - "specificSymbol": "Specifický symbol", - "stable": "Stable", - "statistics": "Statistiky", - "switchAccountPanelTitle": "Účty", - "systemThemeMode": "Systém", - "tabletUi": "Tablet UI", - "tabletUiOptions": "{arg, select, other{error} auto{Automaticky} always{Vždy} landscape{Na šířku} never{Nikdy}}", - "@tabletUiOptions": { - "description": "tabletUiOptions", - "placeholders": { - "arg": { - "type": "String", - "example": "always" - } - } - }, - "toastExit": "Zmáčkněte tlačítko zpět pro ukončení aplikace", - "tryAgain": "Zkusit znovu", - "typeCrash": "Napište \"crash\" pro pád aplikace", - "updateSnackbarDownloaded": "Aktualizace byla stažena, instalování", - "updateSnackbarDownloading": "Nová Aktualizace se stahuje - {value}%", - "@updateSnackbarDownloading": { - "placeholders": { - "value": { - "type": "int" - } - } - }, - "updateSnackbarError": "Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu", - "updateSnackbarWaiting": "Aktualizace - Čeká se na oprávnění", - "userDisplayName": "Zobrazované jméno uživatele: {name}", - "userEmail": "E-mail uživatele: {email}", - "userEmailVerified": "E-mail uživatele ověřen: {bool}", - "userId": "ID uživatele: {id}", - "variableSymbol": "Variabilní symbol", - "verifyEmail": "Ověřit e-mail", - "version": "Verze", - "vlozitNaBurzu": "Vložit na burzu" + "themeModeSystem": "Systém", + "themeModeLight": "Světlý", + "themeModeDark": "Tmavý", + "typeCrash": "Napište \"crash\" pro pád aplikace" } \ No newline at end of file diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index cd0bcd38..4dee81d1 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -91,413 +91,17 @@ abstract class Texts { /// A list of this localizations delegate's supported locales. static const List supportedLocales = [Locale('cs')]; - /// No description provided for @about. - /// - /// In cs, this message translates to: - /// **'O aplikaci'** - String get about; - - /// No description provided for @aboutCheckForUpdates. - /// - /// In cs, this message translates to: - /// **'Zkontrolovat aktualizace'** - String get aboutCheckForUpdates; - - /// No description provided for @aboutCopyRight. - /// - /// In cs, this message translates to: - /// **'© 2023 - {time} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'** - String aboutCopyRight(DateTime time); - - /// No description provided for @aboutLatestVersion. - /// - /// In cs, this message translates to: - /// **'Aktuálně jste na nejnovější verzi aplikace 👍'** - String get aboutLatestVersion; - - /// No description provided for @aboutSourceCode. - /// - /// In cs, this message translates to: - /// **'Zdrojový kód'** - String get aboutSourceCode; - - /// aboutVersionSubtitle - /// - /// In cs, this message translates to: - /// **'{arg, select, true{Debug} other{Stable}} {version}'** - String aboutVersionSubtitle(String arg, String version); - - /// No description provided for @account. - /// - /// In cs, this message translates to: - /// **'Účet'** - String get account; - - /// No description provided for @accountStatus. - /// - /// In cs, this message translates to: - /// **'Stav účtu'** - String get accountStatus; - - /// No description provided for @accountcreationTime. - /// - /// In cs, this message translates to: - /// **'Čas vytvoření účtu: {date}'** - String accountcreationTime(Object date); - - /// No description provided for @addAccount. - /// - /// In cs, this message translates to: - /// **'Přidat účet'** - String get addAccount; - - /// No description provided for @allergens. - /// - /// In cs, this message translates to: - /// **'Alergeny'** - String get allergens; - - /// No description provided for @allowPermission. - /// - /// In cs, this message translates to: - /// **'Udělit oprávnění'** - String get allowPermission; - - /// No description provided for @appDescription. - /// - /// In cs, this message translates to: - /// **'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'** - String get appDescription; - /// No description provided for @appName. /// /// In cs, this message translates to: /// **'Autojídelna'** String get appName; - /// No description provided for @burzaAlertDialogContent. - /// - /// In cs, this message translates to: - /// **'Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.'** - String get burzaAlertDialogContent; - - /// No description provided for @buttonPushed. - /// - /// In cs, this message translates to: - /// **'Tlačítko jste stiskli tolikrát:'** - String get buttonPushed; - - /// No description provided for @cancel. - /// - /// In cs, this message translates to: - /// **'Zrušit'** - String get cancel; - - /// No description provided for @category. - /// - /// In cs, this message translates to: - /// **'Kategorie'** - String get category; - - /// No description provided for @changeAccount. - /// - /// In cs, this message translates to: - /// **'Změnit účet'** - String get changeAccount; - - /// No description provided for @connectedToANetwork. - /// - /// In cs, this message translates to: - /// **'Připojeno k síti'** - String get connectedToANetwork; - - /// No description provided for @connectedToTheInternet. - /// - /// In cs, this message translates to: - /// **'Připojeno k internetu'** - String get connectedToTheInternet; - - /// No description provided for @convenience. - /// - /// In cs, this message translates to: - /// **'Pohodlí'** - String get convenience; - - /// No description provided for @counting. - /// - /// In cs, this message translates to: - /// **'Počítání'** - String get counting; - - /// No description provided for @crashlytics. - /// - /// In cs, this message translates to: - /// **'Crashlytics'** - String get crashlytics; - - /// No description provided for @crashlyticsPage. - /// - /// In cs, this message translates to: - /// **'Stránka Crashlytics'** - String get crashlyticsPage; - - /// No description provided for @crashlyticsTestCrash. - /// - /// In cs, this message translates to: - /// **'Testovací pád Crashlytics yohooo!'** - String get crashlyticsTestCrash; - - /// No description provided for @createAccount. - /// - /// In cs, this message translates to: - /// **'Vytvořit účet s e-mailem a heslem'** - String get createAccount; - - /// No description provided for @credit. - /// - /// In cs, this message translates to: - /// **'Kredit: {ammount} Kč'** - String credit(double ammount); - - /// No description provided for @currency. - /// - /// In cs, this message translates to: - /// **'Kč'** - String get currency; - - /// No description provided for @darkThemeMode. - /// - /// In cs, this message translates to: - /// **'Tmavý'** - String get darkThemeMode; - - /// No description provided for @dataCollectionAgreement. - /// - /// In cs, this message translates to: - /// **'Používáním aplikace souhlasíte se zasíláním anonymních dat. '** - String get dataCollectionAgreement; - - /// No description provided for @dateFormat. - /// - /// In cs, this message translates to: - /// **'Formát dat'** - String get dateFormat; - - /// No description provided for @debug. - /// - /// In cs, this message translates to: - /// **'Debug'** - String get debug; - - /// No description provided for @deleteAccount. - /// - /// In cs, this message translates to: - /// **'Smazat účet'** - String get deleteAccount; - - /// No description provided for @deleteAccountConfirm. - /// - /// In cs, this message translates to: - /// **'Smazat účet'** - String get deleteAccountConfirm; - - /// No description provided for @deleteAccountDialog. - /// - /// In cs, this message translates to: - /// **'Opravdu chcete smazat svůj účet?'** - String get deleteAccountDialog; - - /// No description provided for @demoPageTitle. - /// - /// In cs, this message translates to: - /// **'Demo stránka'** - String get demoPageTitle; - - /// No description provided for @disconnectedFromANetwork. - /// - /// In cs, this message translates to: - /// **'Odpojeno od sítě'** - String get disconnectedFromANetwork; - - /// No description provided for @disconnectedFromTheInternet. - /// - /// In cs, this message translates to: - /// **'Odpojeno od internetu'** - String get disconnectedFromTheInternet; - - /// No description provided for @dochazejiciKreditChannelDescription. - /// - /// In cs, this message translates to: - /// **'Oznámení o tom, zda vám dochází kredit týden dopředu pro {username}'** - String dochazejiciKreditChannelDescription(String username); - - /// No description provided for @dochazejiciKreditChannelName. - /// - /// In cs, this message translates to: - /// **'Docházející kredit'** - String get dochazejiciKreditChannelName; - - /// No description provided for @dontShowAgain. - /// - /// In cs, this message translates to: - /// **'Příště nezobrazovat'** - String get dontShowAgain; - - /// No description provided for @drinks. - /// - /// In cs, this message translates to: - /// **'Pití'** - String get drinks; - - /// No description provided for @email. - /// - /// In cs, this message translates to: - /// **'E-mail'** - String get email; - - /// No description provided for @enterAValidEmailAddress. - /// - /// In cs, this message translates to: - /// **'Zadejte platnou e-mailovou adresu'** - String get enterAValidEmailAddress; - - /// No description provided for @enterYourEmail. - /// - /// In cs, this message translates to: - /// **'Zadejte svůj e-mail'** - String get enterYourEmail; - - /// No description provided for @enterYourPassword. - /// - /// In cs, this message translates to: - /// **'Zadejte své heslo'** - String get enterYourPassword; - - /// No description provided for @errorsBadConnection. - /// - /// In cs, this message translates to: - /// **'Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později'** - String get errorsBadConnection; - - /// No description provided for @errorsBadLogin. - /// - /// In cs, this message translates to: - /// **'Nesprávné přihlašovací údaje'** - String get errorsBadLogin; - - /// No description provided for @errorsBadPassword. - /// - /// In cs, this message translates to: - /// **'Špatné heslo nebo uživatelské jméno'** - String get errorsBadPassword; - - /// No description provided for @errorsBadUrl. - /// - /// In cs, this message translates to: - /// **'Nesprávné Url'** - String get errorsBadUrl; - - /// No description provided for @errorsChangelog. - /// - /// In cs, this message translates to: - /// **'Nepodařilo se získat změny :/'** - String get errorsChangelog; - - /// No description provided for @errorsChybaPriDavaniNaBurzu. - /// - /// In cs, this message translates to: - /// **'Nastala chyba při dávání jídla na burzu'** - String get errorsChybaPriDavaniNaBurzu; - - /// No description provided for @errorsChybaPriRuseni. - /// - /// In cs, this message translates to: - /// **'Nastala chyba při rušení objednávky'** - String get errorsChybaPriRuseni; - - /// No description provided for @errorsDownloadingApp. - /// - /// In cs, this message translates to: - /// **'Aktualizace aplikace selhala'** - String get errorsDownloadingApp; - - /// No description provided for @errorsDownloadingAppDetail. - /// - /// In cs, this message translates to: - /// **'Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.'** - String get errorsDownloadingAppDetail; - - /// No description provided for @errorsJidloNeniNaBurze. - /// - /// In cs, this message translates to: - /// **'Jídlo není na burze'** - String get errorsJidloNeniNaBurze; - - /// No description provided for @errorsLoad. - /// - /// In cs, this message translates to: - /// **'Selhalo načítání jídelníčku'** - String get errorsLoad; - - /// No description provided for @errorsLoadingData. - /// - /// In cs, this message translates to: - /// **'Nastala chyba při načítání dat'** - String get errorsLoadingData; - - /// No description provided for @errorsLoginFailed. - /// - /// In cs, this message translates to: - /// **'Přihlášení se nezdařilo'** - String get errorsLoginFailed; - - /// No description provided for @errorsLoginFailedDetail. - /// - /// In cs, this message translates to: - /// **'Při přihlašování došlo k chybě: {error}'** - String errorsLoginFailedDetail(String error); - - /// No description provided for @errorsNelzeObjednat. - /// - /// In cs, this message translates to: - /// **'Oběd nelze objednat'** - String get errorsNelzeObjednat; - - /// No description provided for @errorsNelzeObjednatKredit. - /// - /// In cs, this message translates to: - /// **'Oběd nelze objednat - Nedostatečný kredit.'** - String get errorsNelzeObjednatKredit; - - /// No description provided for @errorsNoInternet. - /// - /// In cs, this message translates to: - /// **'Nemáte připojení k internetu'** - String get errorsNoInternet; - - /// No description provided for @errorsObedNelzeZrusit. - /// - /// In cs, this message translates to: - /// **'Oběd nelze zrušit. Platnost objednávky vypršela.'** - String get errorsObedNelzeZrusit; - - /// No description provided for @errorsObjednavaniJidla. - /// - /// In cs, this message translates to: - /// **'Nastala chyba při objednávání jídla'** - String get errorsObjednavaniJidla; - - /// No description provided for @errorsUndefined. - /// - /// In cs, this message translates to: - /// **'Nastala Chyba'** - String get errorsUndefined; - - /// No description provided for @errorsUpdatingData. + /// No description provided for @appDescription. /// /// In cs, this message translates to: - /// **'Nastala chyba při aktualizaci dat'** - String get errorsUpdatingData; + /// **'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'** + String get appDescription; /// No description provided for @gettingDataNotifications. /// @@ -505,29 +109,17 @@ abstract class Texts { /// **'Získávám data pro oznámení'** String get gettingDataNotifications; - /// No description provided for @goBack. + /// internetConnectionState /// /// In cs, this message translates to: - /// **'Jít zpět'** - String get goBack; + /// **'{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}'** + String internetConnectionState(String arg); - /// No description provided for @goToSettings. - /// - /// In cs, this message translates to: - /// **'Jít na nastavení'** - String get goToSettings; - - /// No description provided for @jidloChannelDescription. - /// - /// In cs, this message translates to: - /// **'Oznámení každý den o tom jaké je dnes jídlo pro {username}'** - String jidloChannelDescription(String username); - - /// No description provided for @jidloChannelName. + /// No description provided for @debug. /// /// In cs, this message translates to: - /// **'Dnešní jídlo'** - String get jidloChannelName; + /// **'Debug'** + String get debug; /// No description provided for @language. /// @@ -547,875 +139,77 @@ abstract class Texts { /// **'Angličtina'** String get languageEnglish; - /// No description provided for @languageName. - /// - /// In cs, this message translates to: - /// **'Čeština'** - String get languageName; - - /// No description provided for @lastSignInTime. + /// No description provided for @login. /// /// In cs, this message translates to: - /// **'Čas posledního přihlášení: {date}'** - String lastSignInTime(Object date); + /// **'Přihlásit se'** + String get login; - /// No description provided for @licenses. + /// No description provided for @noFood. /// /// In cs, this message translates to: - /// **'Licence'** - String get licenses; + /// **'Žádná jídla pro tento den.'** + String get noFood; - /// No description provided for @lightThemeMode. + /// No description provided for @noThankYou. /// /// In cs, this message translates to: - /// **'Světlý'** - String get lightThemeMode; + /// **'Ne, děkuji'** + String get noThankYou; - /// No description provided for @listUi. + /// No description provided for @password. /// /// In cs, this message translates to: - /// **'List UI'** - String get listUi; + /// **'Heslo'** + String get password; - /// No description provided for @localization. + /// No description provided for @patch. /// /// In cs, this message translates to: - /// **'Lokalizace'** - String get localization; + /// **'patch'** + String get patch; - /// No description provided for @location. + /// No description provided for @requestNotificationPermission. /// /// In cs, this message translates to: - /// **'Výdejna'** - String get location; + /// **'Požádat o povolení notifikací'** + String get requestNotificationPermission; - /// No description provided for @locationsUnknown. + /// No description provided for @settings. /// /// In cs, this message translates to: - /// **'Neznámá výdejna'** - String get locationsUnknown; + /// **'Nastavení'** + String get settings; - /// No description provided for @loggedIn. + /// No description provided for @signOut. /// /// In cs, this message translates to: - /// **'Přihlášen: {bool}'** - String loggedIn(Object bool); + /// **'Odhlásit se'** + String get signOut; - /// No description provided for @login. + /// No description provided for @themeModeSystem. /// /// In cs, this message translates to: - /// **'přihlásit se'** - String get login; + /// **'Systém'** + String get themeModeSystem; - /// No description provided for @loginButton. + /// No description provided for @themeModeLight. /// /// In cs, this message translates to: - /// **'Přihlásit se'** - String get loginButton; + /// **'Světlý'** + String get themeModeLight; - /// No description provided for @loginPasswordFieldHint. + /// No description provided for @themeModeDark. /// /// In cs, this message translates to: - /// **'Zadejte prosím své heslo'** - String get loginPasswordFieldHint; + /// **'Tmavý'** + String get themeModeDark; - /// No description provided for @loginPasswordFieldLabel. - /// - /// In cs, this message translates to: - /// **'Heslo'** - String get loginPasswordFieldLabel; - - /// No description provided for @loginUrlFieldHint. - /// - /// In cs, this message translates to: - /// **'Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz'** - String get loginUrlFieldHint; - - /// No description provided for @loginUrlFieldLabel. - /// - /// In cs, this message translates to: - /// **'Url stránky icanteen - např. jidelna.trebesin.cz'** - String get loginUrlFieldLabel; - - /// No description provided for @loginUserFieldHint. - /// - /// In cs, this message translates to: - /// **'Zadejte prosím své uživatelské jméno'** - String get loginUserFieldHint; - - /// No description provided for @loginUserFieldLabel. - /// - /// In cs, this message translates to: - /// **'Uživatelské jméno'** - String get loginUserFieldLabel; - - /// No description provided for @logoutConfirm. - /// - /// In cs, this message translates to: - /// **'Odhlásit se'** - String get logoutConfirm; - - /// No description provided for @logoutUSure. - /// - /// In cs, this message translates to: - /// **'Opravdu se chcete odhlásit?'** - String get logoutUSure; - - /// No description provided for @mainCourse. - /// - /// In cs, this message translates to: - /// **'Hlavní chod'** - String get mainCourse; - - /// No description provided for @menu. - /// - /// In cs, this message translates to: - /// **'Jídelníček'** - String get menu; - - /// No description provided for @more. - /// - /// In cs, this message translates to: - /// **'Více'** - String get more; - - /// No description provided for @moreInfo. - /// - /// In cs, this message translates to: - /// **'Více informací.'** - String get moreInfo; - - /// No description provided for @name. - /// - /// In cs, this message translates to: - /// **'Jméno'** - String get name; - - /// No description provided for @nedostatekKreditu. - /// - /// In cs, this message translates to: - /// **'Nedostatek kreditu'** - String get nedostatekKreditu; - - /// No description provided for @neededPermission. - /// - /// In cs, this message translates to: - /// **'Potřebné oprávnění'** - String get neededPermission; - - /// No description provided for @neededPermissionDescription_1. - /// - /// In cs, this message translates to: - /// **'Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.'** - String get neededPermissionDescription_1; - - /// No description provided for @neededPermissionDescription_2. - /// - /// In cs, this message translates to: - /// **'Ta může vypadat takto:'** - String get neededPermissionDescription_2; - - /// No description provided for @neededPermissionDescription_3. - /// - /// In cs, this message translates to: - /// **'Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.'** - String get neededPermissionDescription_3; - - /// No description provided for @nelzeObjednat. - /// - /// In cs, this message translates to: - /// **'Nelze objednat'** - String get nelzeObjednat; - - /// No description provided for @nelzeZrusit. - /// - /// In cs, this message translates to: - /// **'Nelze zrušit'** - String get nelzeZrusit; - - /// No description provided for @noFood. - /// - /// In cs, this message translates to: - /// **'Žádná jídla pro tento den.'** - String get noFood; - - /// No description provided for @noThankYou. - /// - /// In cs, this message translates to: - /// **'Ne, děkuji'** - String get noThankYou; - - /// No description provided for @notificationDochaziVamKredit. - /// - /// In cs, this message translates to: - /// **'Dochází vám kredit!'** - String get notificationDochaziVamKredit; - - /// No description provided for @notificationKreditPro. - /// - /// In cs, this message translates to: - /// **'Kredit pro {first} {last}: {ammount} Kč'** - String notificationKreditPro(String first, String last, String ammount); - - /// No description provided for @notificationObjednejteSi. - /// - /// In cs, this message translates to: - /// **'Objednejte si na příští týden'** - String get notificationObjednejteSi; - - /// No description provided for @notificationObjednejteSiDetail. - /// - /// In cs, this message translates to: - /// **'Uživatel {fist} {last} si stále ještě neobjenal na příští týden'** - String notificationObjednejteSiDetail(String first, String last, Object fist); - - /// No description provided for @notificationZtlumit. - /// - /// In cs, this message translates to: - /// **'Ztlumit na týden'** - String get notificationZtlumit; - - /// No description provided for @notifications. - /// - /// In cs, this message translates to: - /// **'Oznámení'** - String get notifications; - - /// No description provided for @notificationsFor. - /// - /// In cs, this message translates to: - /// **'Oznámení pro {username}'** - String notificationsFor(String username); - - /// No description provided for @objednanoChannelDescription. - /// - /// In cs, this message translates to: - /// **'Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro {username}'** - String objednanoChannelDescription(String username); - - /// No description provided for @objednanoChannelName. - /// - /// In cs, this message translates to: - /// **'Objednáno?'** - String get objednanoChannelName; - - /// No description provided for @objednat. - /// - /// In cs, this message translates to: - /// **'Objednat'** - String get objednat; - - /// No description provided for @objednatAction. - /// - /// In cs, this message translates to: - /// **'Objednat náhodně'** - String get objednatAction; - - /// No description provided for @objednatZBurzy. - /// - /// In cs, this message translates to: - /// **'Objednat z burzy'** - String get objednatZBurzy; - - /// No description provided for @odebratZBurzy. - /// - /// In cs, this message translates to: - /// **'Odebrat z burzy'** - String get odebratZBurzy; - - /// No description provided for @ok. - /// - /// In cs, this message translates to: - /// **'OK'** - String get ok; - - /// No description provided for @orders. - /// - /// In cs, this message translates to: - /// **'Objednávky'** - String get orders; - - /// No description provided for @ordersWithAutojidelna. - /// - /// In cs, this message translates to: - /// **'Objednávky s Autojídelnou: {ammount}'** - String ordersWithAutojidelna(int ammount); - - /// No description provided for @other. - /// - /// In cs, this message translates to: - /// **'Ostatní'** - String get other; - - /// No description provided for @otherDescription. - /// - /// In cs, this message translates to: - /// **'Ostatní oznámení, např. chybové hlášky'** - String get otherDescription; - - /// No description provided for @password. - /// - /// In cs, this message translates to: - /// **'Heslo'** - String get password; - - /// No description provided for @passwordMustBeAtLeast6CharactersLong. - /// - /// In cs, this message translates to: - /// **'Heslo musí mít alespoň 6 znaků'** - String get passwordMustBeAtLeast6CharactersLong; - - /// No description provided for @patch. - /// - /// In cs, this message translates to: - /// **'patch'** - String get patch; - - /// No description provided for @paymentAccountNumber. - /// - /// In cs, this message translates to: - /// **'Číslo účtu'** - String get paymentAccountNumber; - - /// No description provided for @paymentInfo. - /// - /// In cs, this message translates to: - /// **'Platební Údaje'** - String get paymentInfo; - - /// No description provided for @personalInfo. - /// - /// In cs, this message translates to: - /// **'Osobní Údaje'** - String get personalInfo; - - /// No description provided for @pickLocation. - /// - /// In cs, this message translates to: - /// **'Vyberte výdejnu '** - String get pickLocation; - - /// No description provided for @popupChangelogNotAvailable. - /// - /// In cs, this message translates to: - /// **'Changelog není k dispozici'** - String get popupChangelogNotAvailable; - - /// No description provided for @popupNewUpdateInfo. - /// - /// In cs, this message translates to: - /// **'Nová verze přináší: '** - String get popupNewUpdateInfo; - - /// No description provided for @popupNewVersionAvailable. - /// - /// In cs, this message translates to: - /// **'Nová verze aplikace - {version}'** - String popupNewVersionAvailable(String version); - - /// No description provided for @popupNotNow. - /// - /// In cs, this message translates to: - /// **'Teď ne'** - String get popupNotNow; - - /// No description provided for @popupShowOnGithub. - /// - /// In cs, this message translates to: - /// **'Zobrazit na Githubu'** - String get popupShowOnGithub; - - /// No description provided for @popupUpdate. - /// - /// In cs, this message translates to: - /// **'Aktualizovat'** - String get popupUpdate; - - /// No description provided for @privacyPolicy. - /// - /// In cs, this message translates to: - /// **'Zásady ochrany osobních údajů'** - String get privacyPolicy; - - /// No description provided for @providerId. - /// - /// In cs, this message translates to: - /// **'ID poskytovatele: {id}'** - String providerId(Object id); - - /// No description provided for @remoteConfig. - /// - /// In cs, this message translates to: - /// **'Vzdálená konfigurace'** - String get remoteConfig; - - /// No description provided for @requestNotificationPermission. - /// - /// In cs, this message translates to: - /// **'Požádat o povolení notifikací'** - String get requestNotificationPermission; - - /// No description provided for @resetPassword. - /// - /// In cs, this message translates to: - /// **'Obnovit heslo'** - String get resetPassword; - - /// No description provided for @routingGoToDetailDetail. - /// - /// In cs, this message translates to: - /// **'Jít na podrobnosti podrobností'** - String get routingGoToDetailDetail; - - /// No description provided for @routingGoToDetailPage. - /// - /// In cs, this message translates to: - /// **'Jít na podrobnosti stránky'** - String get routingGoToDetailPage; - - /// No description provided for @routingGoToParamDetailPage. - /// - /// In cs, this message translates to: - /// **'Jít na podrobnosti stránky s parametry'** - String get routingGoToParamDetailPage; - - /// No description provided for @routingParamDetailPageDetail. - /// - /// In cs, this message translates to: - /// **'Stránka s podrobnostmi o parametrech směrování'** - String get routingParamDetailPageDetail; - - /// No description provided for @routingParamDetailPageDetail1. - /// - /// In cs, this message translates to: - /// **'Toto je stránka s podrobnostmi o parametrech směrování.'** - String get routingParamDetailPageDetail1; - - /// No description provided for @routingParamDetailPageDetail2. - /// - /// In cs, this message translates to: - /// **'Slouží k testování směrování s parametry.'** - String get routingParamDetailPageDetail2; - - /// No description provided for @routingParamDetailPageDetail3. - /// - /// In cs, this message translates to: - /// **'Film ID: {filmId}'** - String routingParamDetailPageDetail3(Object filmId); - - /// No description provided for @routingParamFilmId. - /// - /// In cs, this message translates to: - /// **'Cesta param Film ID'** - String get routingParamFilmId; - - /// No description provided for @routingParamPage. - /// - /// In cs, this message translates to: - /// **'Stránka s parametry směrování'** - String get routingParamPage; - - /// No description provided for @routingParamPageDetail. - /// - /// In cs, this message translates to: - /// **'Toto je stránka s parametry směrování.'** - String get routingParamPageDetail; - - /// No description provided for @routingParamPageDetail2. - /// - /// In cs, this message translates to: - /// **'Slouží k testování směrování s parametry.'** - String get routingParamPageDetail2; - - /// No description provided for @routingParamQueryFilmId. - /// - /// In cs, this message translates to: - /// **'Dotaz param Film ID'** - String get routingParamQueryFilmId; - - /// No description provided for @routingTestDetailDetail. - /// - /// In cs, this message translates to: - /// **'Podrobnosti o testování směrování'** - String get routingTestDetailDetail; - - /// No description provided for @routingTestDetailDetailText. - /// - /// In cs, this message translates to: - /// **'Toto je podostránka s podrobnostmi o testování směrování.'** - String get routingTestDetailDetailText; - - /// No description provided for @routingTestPage. - /// - /// In cs, this message translates to: - /// **'Nastavení'** - String get routingTestPage; - - /// No description provided for @routingTestPageDetail. - /// - /// In cs, this message translates to: - /// **'Toto je stránka s testováním směrování.'** - String get routingTestPageDetail; - - /// No description provided for @routingTestPageDetail1. - /// - /// In cs, this message translates to: - /// **'Slouží k testování směrování.'** - String get routingTestPageDetail1; - - /// No description provided for @secret. - /// - /// In cs, this message translates to: - /// **'tajemství'** - String get secret; - - /// No description provided for @secretPage. - /// - /// In cs, this message translates to: - /// **'Tajná stránka'** - String get secretPage; - - /// No description provided for @settings. - /// - /// In cs, this message translates to: - /// **'Nastavení'** - String get settings; - - /// No description provided for @settingsAmoled. - /// - /// In cs, this message translates to: - /// **'AMOLED mód'** - String get settingsAmoled; - - /// No description provided for @settingsAmoledSub. - /// - /// In cs, this message translates to: - /// **'Přidej se k temné straně síly!'** - String get settingsAmoledSub; - - /// No description provided for @settingsAnotherOptions. - /// - /// In cs, this message translates to: - /// **'Další možnosti v nastavení systému...'** - String get settingsAnotherOptions; - - /// No description provided for @settingsAppearence. - /// - /// In cs, this message translates to: - /// **'Vzhled'** - String get settingsAppearence; - - /// No description provided for @settingsCalendarBigMarkers. - /// - /// In cs, this message translates to: - /// **'Velké ukazatele v kalendáři'** - String get settingsCalendarBigMarkers; - - /// No description provided for @settingsDataCollection. - /// - /// In cs, this message translates to: - /// **'Shromažďování údajů'** - String get settingsDataCollection; - - /// No description provided for @settingsDataCollectionDescription_1. - /// - /// In cs, this message translates to: - /// **'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '** - String get settingsDataCollectionDescription_1; - - /// No description provided for @settingsDataCollectionDescription_2. - /// - /// In cs, this message translates to: - /// **'Zdrojovém kódu'** - String get settingsDataCollectionDescription_2; - - /// No description provided for @settingsDataCollectionDescription_3. - /// - /// In cs, this message translates to: - /// **' nebo v '** - String get settingsDataCollectionDescription_3; - - /// No description provided for @settingsDataCollectionDescription_4. - /// - /// In cs, this message translates to: - /// **'Zásadách ochrany osobních údajů.'** - String get settingsDataCollectionDescription_4; - - /// No description provided for @settingsDebugForceNotifications. - /// - /// In cs, this message translates to: - /// **'Force send notifications'** - String get settingsDebugForceNotifications; - - /// No description provided for @settingsDebugNotifications. - /// - /// In cs, this message translates to: - /// **'Send Notifications'** - String get settingsDebugNotifications; - - /// No description provided for @settingsDebugOptions. - /// - /// In cs, this message translates to: - /// **'Debug Options'** - String get settingsDebugOptions; - - /// No description provided for @settingsDisplay. - /// - /// In cs, this message translates to: - /// **'Zobrazení'** - String get settingsDisplay; - - /// No description provided for @settingsNemateObjednano. - /// - /// In cs, this message translates to: - /// **'Nemáte objednáno na příští týden'** - String get settingsNemateObjednano; - - /// No description provided for @settingsNotificationFor. - /// - /// In cs, this message translates to: - /// **'Oznámení pro {username}'** - String settingsNotificationFor(String username); - - /// No description provided for @settingsNotificationTime. - /// - /// In cs, this message translates to: - /// **'Čas oznámení: '** - String get settingsNotificationTime; - - /// No description provided for @settingsRelativeTimestamps. - /// - /// In cs, this message translates to: - /// **'Relativní časové značky'** - String get settingsRelativeTimestamps; - - /// No description provided for @settingsRelativeTimestampsSub. - /// - /// In cs, this message translates to: - /// **'„Dnes“ místo „{date}“'** - String settingsRelativeTimestampsSub(String date); - - /// No description provided for @settingsSkipWeekends. - /// - /// In cs, this message translates to: - /// **'Přeskakovat víkendy'** - String get settingsSkipWeekends; - - /// No description provided for @settingsStopDataCollection. - /// - /// In cs, this message translates to: - /// **'Zastavit sledování analytických služeb'** - String get settingsStopDataCollection; - - /// No description provided for @settingsTheme. - /// - /// In cs, this message translates to: - /// **'Schéma'** - String get settingsTheme; - - /// No description provided for @settingsTitleCredit. - /// - /// In cs, this message translates to: - /// **'Nízký credit'** - String get settingsTitleCredit; - - /// No description provided for @settingsTitleTodaysFood. - /// - /// In cs, this message translates to: - /// **'Dnešní jídlo'** - String get settingsTitleTodaysFood; - - /// No description provided for @shareApp. - /// - /// In cs, this message translates to: - /// **'Sdílet aplikaci'** - String get shareApp; - - /// No description provided for @shareDescription. - /// - /// In cs, this message translates to: - /// **'Autojídelna (aplikace na objednávání jídla)'** - String get shareDescription; - - /// No description provided for @showLocale. - /// - /// In cs, this message translates to: - /// **'Zobrazit lokalizaci'** - String get showLocale; - - /// No description provided for @sideDish. - /// - /// In cs, this message translates to: - /// **'Přílohy'** - String get sideDish; - - /// No description provided for @signInAnonymously. - /// - /// In cs, this message translates to: - /// **'Přihlásit se anonymně'** - String get signInAnonymously; - - /// No description provided for @signInWithApple. - /// - /// In cs, this message translates to: - /// **'Přihlásit se pomocí Apple'** - String get signInWithApple; - - /// No description provided for @signInWithEmailAndPassword. - /// - /// In cs, this message translates to: - /// **'Přihlásit se pomocí e-mailu a hesla'** - String get signInWithEmailAndPassword; - - /// No description provided for @signInWithGoogle. - /// - /// In cs, this message translates to: - /// **'Přihlásit se pomocí Google'** - String get signInWithGoogle; - - /// No description provided for @signOut. - /// - /// In cs, this message translates to: - /// **'Odhlásit se'** - String get signOut; - - /// No description provided for @soup. - /// - /// In cs, this message translates to: - /// **'Polévka'** - String get soup; - - /// No description provided for @specificSymbol. - /// - /// In cs, this message translates to: - /// **'Specifický symbol'** - String get specificSymbol; - - /// No description provided for @stable. - /// - /// In cs, this message translates to: - /// **'Stable'** - String get stable; - - /// No description provided for @statistics. - /// - /// In cs, this message translates to: - /// **'Statistiky'** - String get statistics; - - /// No description provided for @switchAccountPanelTitle. - /// - /// In cs, this message translates to: - /// **'Účty'** - String get switchAccountPanelTitle; - - /// No description provided for @systemThemeMode. - /// - /// In cs, this message translates to: - /// **'Systém'** - String get systemThemeMode; - - /// No description provided for @tabletUi. - /// - /// In cs, this message translates to: - /// **'Tablet UI'** - String get tabletUi; - - /// tabletUiOptions - /// - /// In cs, this message translates to: - /// **'{arg, select, other{error} auto{Automaticky} always{Vždy} landscape{Na šířku} never{Nikdy}}'** - String tabletUiOptions(String arg); - - /// No description provided for @toastExit. - /// - /// In cs, this message translates to: - /// **'Zmáčkněte tlačítko zpět pro ukončení aplikace'** - String get toastExit; - - /// No description provided for @tryAgain. - /// - /// In cs, this message translates to: - /// **'Zkusit znovu'** - String get tryAgain; - - /// No description provided for @typeCrash. + /// No description provided for @typeCrash. /// /// In cs, this message translates to: /// **'Napište \"crash\" pro pád aplikace'** String get typeCrash; - - /// No description provided for @updateSnackbarDownloaded. - /// - /// In cs, this message translates to: - /// **'Aktualizace byla stažena, instalování'** - String get updateSnackbarDownloaded; - - /// No description provided for @updateSnackbarDownloading. - /// - /// In cs, this message translates to: - /// **'Nová Aktualizace se stahuje - {value}%'** - String updateSnackbarDownloading(int value); - - /// No description provided for @updateSnackbarError. - /// - /// In cs, this message translates to: - /// **'Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu'** - String get updateSnackbarError; - - /// No description provided for @updateSnackbarWaiting. - /// - /// In cs, this message translates to: - /// **'Aktualizace - Čeká se na oprávnění'** - String get updateSnackbarWaiting; - - /// No description provided for @userDisplayName. - /// - /// In cs, this message translates to: - /// **'Zobrazované jméno uživatele: {name}'** - String userDisplayName(Object name); - - /// No description provided for @userEmail. - /// - /// In cs, this message translates to: - /// **'E-mail uživatele: {email}'** - String userEmail(Object email); - - /// No description provided for @userEmailVerified. - /// - /// In cs, this message translates to: - /// **'E-mail uživatele ověřen: {bool}'** - String userEmailVerified(Object bool); - - /// No description provided for @userId. - /// - /// In cs, this message translates to: - /// **'ID uživatele: {id}'** - String userId(Object id); - - /// No description provided for @variableSymbol. - /// - /// In cs, this message translates to: - /// **'Variabilní symbol'** - String get variableSymbol; - - /// No description provided for @verifyEmail. - /// - /// In cs, this message translates to: - /// **'Ověřit e-mail'** - String get verifyEmail; - - /// No description provided for @version. - /// - /// In cs, this message translates to: - /// **'Verze'** - String get version; - - /// No description provided for @vlozitNaBurzu. - /// - /// In cs, this message translates to: - /// **'Vložit na burzu'** - String get vlozitNaBurzu; } class _TextsDelegate extends LocalizationsDelegate { diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 9a9e684f..2efc6678 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -7,261 +7,30 @@ class TextsCs extends Texts { TextsCs([String locale = 'cs']) : super(locale); @override - String get about => 'O aplikaci'; - - @override - String get aboutCheckForUpdates => 'Zkontrolovat aktualizace'; - - @override - String aboutCopyRight(DateTime time) { - final intl.DateFormat timeDateFormat = intl.DateFormat.y(localeName); - final String timeString = timeDateFormat.format(time); - - return '© 2023 - $timeString Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'; - } + String get appName => 'Autojídelna'; @override - String get aboutLatestVersion => - 'Aktuálně jste na nejnovější verzi aplikace 👍'; + String get appDescription => + 'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'; @override - String get aboutSourceCode => 'Zdrojový kód'; + String get gettingDataNotifications => 'Získávám data pro oznámení'; @override - String aboutVersionSubtitle(String arg, String version) { + String internetConnectionState(String arg) { String _temp0 = intl.Intl.selectLogic( arg, { - 'true': 'Debug', - 'other': 'Stable', + 'other': 'Odpojeno od internetu', + 'true': 'Připojeno k internetu', }, ); - return '$_temp0 $version'; - } - - @override - String get account => 'Účet'; - - @override - String get accountStatus => 'Stav účtu'; - - @override - String accountcreationTime(Object date) { - return 'Čas vytvoření účtu: $date'; - } - - @override - String get addAccount => 'Přidat účet'; - - @override - String get allergens => 'Alergeny'; - - @override - String get allowPermission => 'Udělit oprávnění'; - - @override - String get appDescription => - 'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'; - - @override - String get appName => 'Autojídelna'; - - @override - String get burzaAlertDialogContent => - 'Přidáváte jídlo na burzu. Peníze se Vám vrátí pouze v případě, že si jídlo objedná někdo jiný.'; - - @override - String get buttonPushed => 'Tlačítko jste stiskli tolikrát:'; - - @override - String get cancel => 'Zrušit'; - - @override - String get category => 'Kategorie'; - - @override - String get changeAccount => 'Změnit účet'; - - @override - String get connectedToANetwork => 'Připojeno k síti'; - - @override - String get connectedToTheInternet => 'Připojeno k internetu'; - - @override - String get convenience => 'Pohodlí'; - - @override - String get counting => 'Počítání'; - - @override - String get crashlytics => 'Crashlytics'; - - @override - String get crashlyticsPage => 'Stránka Crashlytics'; - - @override - String get crashlyticsTestCrash => 'Testovací pád Crashlytics yohooo!'; - - @override - String get createAccount => 'Vytvořit účet s e-mailem a heslem'; - - @override - String credit(double ammount) { - final intl.NumberFormat ammountNumberFormat = - intl.NumberFormat.decimalPattern(localeName); - final String ammountString = ammountNumberFormat.format(ammount); - - return 'Kredit: $ammountString Kč'; + return '$_temp0'; } - @override - String get currency => 'Kč'; - - @override - String get darkThemeMode => 'Tmavý'; - - @override - String get dataCollectionAgreement => - 'Používáním aplikace souhlasíte se zasíláním anonymních dat. '; - - @override - String get dateFormat => 'Formát dat'; - @override String get debug => 'Debug'; - @override - String get deleteAccount => 'Smazat účet'; - - @override - String get deleteAccountConfirm => 'Smazat účet'; - - @override - String get deleteAccountDialog => 'Opravdu chcete smazat svůj účet?'; - - @override - String get demoPageTitle => 'Demo stránka'; - - @override - String get disconnectedFromANetwork => 'Odpojeno od sítě'; - - @override - String get disconnectedFromTheInternet => 'Odpojeno od internetu'; - - @override - String dochazejiciKreditChannelDescription(String username) { - return 'Oznámení o tom, zda vám dochází kredit týden dopředu pro $username'; - } - - @override - String get dochazejiciKreditChannelName => 'Docházející kredit'; - - @override - String get dontShowAgain => 'Příště nezobrazovat'; - - @override - String get drinks => 'Pití'; - - @override - String get email => 'E-mail'; - - @override - String get enterAValidEmailAddress => 'Zadejte platnou e-mailovou adresu'; - - @override - String get enterYourEmail => 'Zadejte svůj e-mail'; - - @override - String get enterYourPassword => 'Zadejte své heslo'; - - @override - String get errorsBadConnection => - 'Nepodařilo se připojit k serveru icanteen. Zkuste to znovu později'; - - @override - String get errorsBadLogin => 'Nesprávné přihlašovací údaje'; - - @override - String get errorsBadPassword => 'Špatné heslo nebo uživatelské jméno'; - - @override - String get errorsBadUrl => 'Nesprávné Url'; - - @override - String get errorsChangelog => 'Nepodařilo se získat změny :/'; - - @override - String get errorsChybaPriDavaniNaBurzu => - 'Nastala chyba při dávání jídla na burzu'; - - @override - String get errorsChybaPriRuseni => 'Nastala chyba při rušení objednávky'; - - @override - String get errorsDownloadingApp => 'Aktualizace aplikace selhala'; - - @override - String get errorsDownloadingAppDetail => - 'Při Stahování aplikace došlo k chybě. Ověřte vaše připojení a zkuste znovu.'; - - @override - String get errorsJidloNeniNaBurze => 'Jídlo není na burze'; - - @override - String get errorsLoad => 'Selhalo načítání jídelníčku'; - - @override - String get errorsLoadingData => 'Nastala chyba při načítání dat'; - - @override - String get errorsLoginFailed => 'Přihlášení se nezdařilo'; - - @override - String errorsLoginFailedDetail(String error) { - return 'Při přihlašování došlo k chybě: $error'; - } - - @override - String get errorsNelzeObjednat => 'Oběd nelze objednat'; - - @override - String get errorsNelzeObjednatKredit => - 'Oběd nelze objednat - Nedostatečný kredit.'; - - @override - String get errorsNoInternet => 'Nemáte připojení k internetu'; - - @override - String get errorsObedNelzeZrusit => - 'Oběd nelze zrušit. Platnost objednávky vypršela.'; - - @override - String get errorsObjednavaniJidla => 'Nastala chyba při objednávání jídla'; - - @override - String get errorsUndefined => 'Nastala Chyba'; - - @override - String get errorsUpdatingData => 'Nastala chyba při aktualizaci dat'; - - @override - String get gettingDataNotifications => 'Získávám data pro oznámení'; - - @override - String get goBack => 'Jít zpět'; - - @override - String get goToSettings => 'Jít na nastavení'; - - @override - String jidloChannelDescription(String username) { - return 'Oznámení každý den o tom jaké je dnes jídlo pro $username'; - } - - @override - String get jidloChannelName => 'Dnešní jídlo'; - @override String get language => 'Jazyk'; @@ -272,105 +41,7 @@ class TextsCs extends Texts { String get languageEnglish => 'Angličtina'; @override - String get languageName => 'Čeština'; - - @override - String lastSignInTime(Object date) { - return 'Čas posledního přihlášení: $date'; - } - - @override - String get licenses => 'Licence'; - - @override - String get lightThemeMode => 'Světlý'; - - @override - String get listUi => 'List UI'; - - @override - String get localization => 'Lokalizace'; - - @override - String get location => 'Výdejna'; - - @override - String get locationsUnknown => 'Neznámá výdejna'; - - @override - String loggedIn(Object bool) { - return 'Přihlášen: $bool'; - } - - @override - String get login => 'přihlásit se'; - - @override - String get loginButton => 'Přihlásit se'; - - @override - String get loginPasswordFieldHint => 'Zadejte prosím své heslo'; - - @override - String get loginPasswordFieldLabel => 'Heslo'; - - @override - String get loginUrlFieldHint => - 'Zadejte prosím url stránky icanteen - např. jidelna.trebesin.cz'; - - @override - String get loginUrlFieldLabel => - 'Url stránky icanteen - např. jidelna.trebesin.cz'; - - @override - String get loginUserFieldHint => 'Zadejte prosím své uživatelské jméno'; - - @override - String get loginUserFieldLabel => 'Uživatelské jméno'; - - @override - String get logoutConfirm => 'Odhlásit se'; - - @override - String get logoutUSure => 'Opravdu se chcete odhlásit?'; - - @override - String get mainCourse => 'Hlavní chod'; - - @override - String get menu => 'Jídelníček'; - - @override - String get more => 'Více'; - - @override - String get moreInfo => 'Více informací.'; - - @override - String get name => 'Jméno'; - - @override - String get nedostatekKreditu => 'Nedostatek kreditu'; - - @override - String get neededPermission => 'Potřebné oprávnění'; - - @override - String get neededPermissionDescription_1 => - 'Pro automatickou instalaci aktualizace je potřeba povolit oprávnění pro instalaci aplikací z neznámých zdrojů.'; - - @override - String get neededPermissionDescription_2 => 'Ta může vypadat takto:'; - - @override - String get neededPermissionDescription_3 => - 'Toto oprávnění používáme pouze k aktualizaci aplikace. Pokud si nepřejete oprávnění povolit můžete stále stáhnout apk z githubu.'; - - @override - String get nelzeObjednat => 'Nelze objednat'; - - @override - String get nelzeZrusit => 'Nelze zrušit'; + String get login => 'Přihlásit se'; @override String get noFood => 'Žádná jídla pro tento den.'; @@ -378,395 +49,30 @@ class TextsCs extends Texts { @override String get noThankYou => 'Ne, děkuji'; - @override - String get notificationDochaziVamKredit => 'Dochází vám kredit!'; - - @override - String notificationKreditPro(String first, String last, String ammount) { - return 'Kredit pro $first $last: $ammount Kč'; - } - - @override - String get notificationObjednejteSi => 'Objednejte si na příští týden'; - - @override - String notificationObjednejteSiDetail( - String first, String last, Object fist) { - return 'Uživatel $fist $last si stále ještě neobjenal na příští týden'; - } - - @override - String get notificationZtlumit => 'Ztlumit na týden'; - - @override - String get notifications => 'Oznámení'; - - @override - String notificationsFor(String username) { - return 'Oznámení pro $username'; - } - - @override - String objednanoChannelDescription(String username) { - return 'Oznámení týden dopředu o tom, zda jste si objednal jídlo na příští týden pro $username'; - } - - @override - String get objednanoChannelName => 'Objednáno?'; - - @override - String get objednat => 'Objednat'; - - @override - String get objednatAction => 'Objednat náhodně'; - - @override - String get objednatZBurzy => 'Objednat z burzy'; - - @override - String get odebratZBurzy => 'Odebrat z burzy'; - - @override - String get ok => 'OK'; - - @override - String get orders => 'Objednávky'; - - @override - String ordersWithAutojidelna(int ammount) { - return 'Objednávky s Autojídelnou: $ammount'; - } - - @override - String get other => 'Ostatní'; - - @override - String get otherDescription => 'Ostatní oznámení, např. chybové hlášky'; - @override String get password => 'Heslo'; - @override - String get passwordMustBeAtLeast6CharactersLong => - 'Heslo musí mít alespoň 6 znaků'; - @override String get patch => 'patch'; - @override - String get paymentAccountNumber => 'Číslo účtu'; - - @override - String get paymentInfo => 'Platební Údaje'; - - @override - String get personalInfo => 'Osobní Údaje'; - - @override - String get pickLocation => 'Vyberte výdejnu '; - - @override - String get popupChangelogNotAvailable => 'Changelog není k dispozici'; - - @override - String get popupNewUpdateInfo => 'Nová verze přináší: '; - - @override - String popupNewVersionAvailable(String version) { - return 'Nová verze aplikace - $version'; - } - - @override - String get popupNotNow => 'Teď ne'; - - @override - String get popupShowOnGithub => 'Zobrazit na Githubu'; - - @override - String get popupUpdate => 'Aktualizovat'; - - @override - String get privacyPolicy => 'Zásady ochrany osobních údajů'; - - @override - String providerId(Object id) { - return 'ID poskytovatele: $id'; - } - - @override - String get remoteConfig => 'Vzdálená konfigurace'; - @override String get requestNotificationPermission => 'Požádat o povolení notifikací'; - @override - String get resetPassword => 'Obnovit heslo'; - - @override - String get routingGoToDetailDetail => 'Jít na podrobnosti podrobností'; - - @override - String get routingGoToDetailPage => 'Jít na podrobnosti stránky'; - - @override - String get routingGoToParamDetailPage => - 'Jít na podrobnosti stránky s parametry'; - - @override - String get routingParamDetailPageDetail => - 'Stránka s podrobnostmi o parametrech směrování'; - - @override - String get routingParamDetailPageDetail1 => - 'Toto je stránka s podrobnostmi o parametrech směrování.'; - - @override - String get routingParamDetailPageDetail2 => - 'Slouží k testování směrování s parametry.'; - - @override - String routingParamDetailPageDetail3(Object filmId) { - return 'Film ID: $filmId'; - } - - @override - String get routingParamFilmId => 'Cesta param Film ID'; - - @override - String get routingParamPage => 'Stránka s parametry směrování'; - - @override - String get routingParamPageDetail => 'Toto je stránka s parametry směrování.'; - - @override - String get routingParamPageDetail2 => - 'Slouží k testování směrování s parametry.'; - - @override - String get routingParamQueryFilmId => 'Dotaz param Film ID'; - - @override - String get routingTestDetailDetail => 'Podrobnosti o testování směrování'; - - @override - String get routingTestDetailDetailText => - 'Toto je podostránka s podrobnostmi o testování směrování.'; - - @override - String get routingTestPage => 'Nastavení'; - - @override - String get routingTestPageDetail => 'Toto je stránka s testováním směrování.'; - - @override - String get routingTestPageDetail1 => 'Slouží k testování směrování.'; - - @override - String get secret => 'tajemství'; - - @override - String get secretPage => 'Tajná stránka'; - @override String get settings => 'Nastavení'; - @override - String get settingsAmoled => 'AMOLED mód'; - - @override - String get settingsAmoledSub => 'Přidej se k temné straně síly!'; - - @override - String get settingsAnotherOptions => 'Další možnosti v nastavení systému...'; - - @override - String get settingsAppearence => 'Vzhled'; - - @override - String get settingsCalendarBigMarkers => 'Velké ukazatele v kalendáři'; - - @override - String get settingsDataCollection => 'Shromažďování údajů'; - - @override - String get settingsDataCollectionDescription_1 => - 'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '; - - @override - String get settingsDataCollectionDescription_2 => 'Zdrojovém kódu'; - - @override - String get settingsDataCollectionDescription_3 => ' nebo v '; - - @override - String get settingsDataCollectionDescription_4 => - 'Zásadách ochrany osobních údajů.'; - - @override - String get settingsDebugForceNotifications => 'Force send notifications'; - - @override - String get settingsDebugNotifications => 'Send Notifications'; - - @override - String get settingsDebugOptions => 'Debug Options'; - - @override - String get settingsDisplay => 'Zobrazení'; - - @override - String get settingsNemateObjednano => 'Nemáte objednáno na příští týden'; - - @override - String settingsNotificationFor(String username) { - return 'Oznámení pro $username'; - } - - @override - String get settingsNotificationTime => 'Čas oznámení: '; - - @override - String get settingsRelativeTimestamps => 'Relativní časové značky'; - - @override - String settingsRelativeTimestampsSub(String date) { - return '„Dnes“ místo „$date“'; - } - - @override - String get settingsSkipWeekends => 'Přeskakovat víkendy'; - - @override - String get settingsStopDataCollection => - 'Zastavit sledování analytických služeb'; - - @override - String get settingsTheme => 'Schéma'; - - @override - String get settingsTitleCredit => 'Nízký credit'; - - @override - String get settingsTitleTodaysFood => 'Dnešní jídlo'; - - @override - String get shareApp => 'Sdílet aplikaci'; - - @override - String get shareDescription => 'Autojídelna (aplikace na objednávání jídla)'; - - @override - String get showLocale => 'Zobrazit lokalizaci'; - - @override - String get sideDish => 'Přílohy'; - - @override - String get signInAnonymously => 'Přihlásit se anonymně'; - - @override - String get signInWithApple => 'Přihlásit se pomocí Apple'; - - @override - String get signInWithEmailAndPassword => - 'Přihlásit se pomocí e-mailu a hesla'; - - @override - String get signInWithGoogle => 'Přihlásit se pomocí Google'; - @override String get signOut => 'Odhlásit se'; @override - String get soup => 'Polévka'; - - @override - String get specificSymbol => 'Specifický symbol'; - - @override - String get stable => 'Stable'; - - @override - String get statistics => 'Statistiky'; - - @override - String get switchAccountPanelTitle => 'Účty'; - - @override - String get systemThemeMode => 'Systém'; - - @override - String get tabletUi => 'Tablet UI'; - - @override - String tabletUiOptions(String arg) { - String _temp0 = intl.Intl.selectLogic( - arg, - { - 'other': 'error', - 'auto': 'Automaticky', - 'always': 'Vždy', - 'landscape': 'Na šířku', - 'never': 'Nikdy', - }, - ); - return '$_temp0'; - } + String get themeModeSystem => 'Systém'; @override - String get toastExit => 'Zmáčkněte tlačítko zpět pro ukončení aplikace'; + String get themeModeLight => 'Světlý'; @override - String get tryAgain => 'Zkusit znovu'; + String get themeModeDark => 'Tmavý'; @override String get typeCrash => 'Napište \"crash\" pro pád aplikace'; - - @override - String get updateSnackbarDownloaded => - 'Aktualizace byla stažena, instalování'; - - @override - String updateSnackbarDownloading(int value) { - return 'Nová Aktualizace se stahuje - $value%'; - } - - @override - String get updateSnackbarError => - 'Došlo k chybě při stahování. Ověřte připojení a zkuste to znovu'; - - @override - String get updateSnackbarWaiting => 'Aktualizace - Čeká se na oprávnění'; - - @override - String userDisplayName(Object name) { - return 'Zobrazované jméno uživatele: $name'; - } - - @override - String userEmail(Object email) { - return 'E-mail uživatele: $email'; - } - - @override - String userEmailVerified(Object bool) { - return 'E-mail uživatele ověřen: $bool'; - } - - @override - String userId(Object id) { - return 'ID uživatele: $id'; - } - - @override - String get variableSymbol => 'Variabilní symbol'; - - @override - String get verifyEmail => 'Ověřit e-mail'; - - @override - String get version => 'Verze'; - - @override - String get vlozitNaBurzu => 'Vložit na burzu'; } diff --git a/lib/src/ui/widgets/theme_mode_picker.dart b/lib/src/ui/widgets/theme_mode_picker.dart index ec90eaff..8c9c4adf 100644 --- a/lib/src/ui/widgets/theme_mode_picker.dart +++ b/lib/src/ui/widgets/theme_mode_picker.dart @@ -18,9 +18,9 @@ class ThemeModePicker extends StatelessWidget { selected: {themeMode.read}, onSelectionChanged: (Set selected) => themeMode.set(selected.first), segments: [ - ButtonSegment(value: ThemeMode.system, label: Text(lang.systemThemeMode)), - ButtonSegment(value: ThemeMode.light, label: Text(lang.lightThemeMode)), - ButtonSegment(value: ThemeMode.dark, label: Text(lang.darkThemeMode)), + ButtonSegment(value: ThemeMode.system, label: Text(lang.themeModeSystem)), + ButtonSegment(value: ThemeMode.light, label: Text(lang.themeModeLight)), + ButtonSegment(value: ThemeMode.dark, label: Text(lang.themeModeDark)), ], ), ), From 9a83b0c57ea64957bf231c5aa644c6c74909a1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 20:55:17 +0200 Subject: [PATCH 15/57] move debug page from /pages/ to /pages/dev/ --- lib/src/_routing/app_router.gr.dart | 2 +- lib/src/ui/pages/{ => dev}/debug_page.dart | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/src/ui/pages/{ => dev}/debug_page.dart (100%) diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index 96acd089..ce013312 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -9,7 +9,7 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:auto_route/auto_route.dart' as _i4; -import 'package:autojidelna/src/ui/pages/debug_page.dart' as _i1; +import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i1; import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i2; import 'package:autojidelna/src/ui/pages/router_page.dart' as _i3; import 'package:flutter/foundation.dart' as _i5; diff --git a/lib/src/ui/pages/debug_page.dart b/lib/src/ui/pages/dev/debug_page.dart similarity index 100% rename from lib/src/ui/pages/debug_page.dart rename to lib/src/ui/pages/dev/debug_page.dart From 341ff40cc39e1f8420e5dd779a2d0b777184df1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 21:54:53 +0200 Subject: [PATCH 16/57] add menu & more pages --- lib/src/_routing/app_router.dart | 3 +- lib/src/_routing/app_router.gr.dart | 78 ++++++++++++++----- lib/src/lang/app_cs.arb | 3 + lib/src/lang/output/texts.dart | 18 +++++ lib/src/lang/output/texts_cs.dart | 9 +++ lib/src/ui/pages/menu_page.dart | 12 +++ lib/src/ui/pages/more_page.dart | 12 +++ lib/src/ui/pages/router_page.dart | 33 +++++--- .../ui/widgets/appbars/default_appbar.dart | 24 ++++++ lib/src/ui/widgets/appbars/menu_page.dart | 11 +++ lib/src/ui/widgets/appbars/more_page.dart | 11 +++ 11 files changed, 185 insertions(+), 29 deletions(-) create mode 100644 lib/src/ui/pages/menu_page.dart create mode 100644 lib/src/ui/pages/more_page.dart create mode 100644 lib/src/ui/widgets/appbars/default_appbar.dart create mode 100644 lib/src/ui/widgets/appbars/menu_page.dart create mode 100644 lib/src/ui/widgets/appbars/more_page.dart diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index b3d4a73a..236d572b 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -11,7 +11,8 @@ class AppRouter extends RootStackRouter { initial: true, path: '/', children: [ - // TODO + AutoRoute(page: MenuPage.page, path: 'menu', initial: true), + AutoRoute(page: MorePage.page, path: 'more'), ], ), AutoRoute(page: RequestPermissionPage.page, path: '/request-permission'), diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index ce013312..efd4347f 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -8,16 +8,18 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i4; +import 'package:auto_route/auto_route.dart' as _i6; import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i1; -import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i2; -import 'package:autojidelna/src/ui/pages/router_page.dart' as _i3; -import 'package:flutter/foundation.dart' as _i5; +import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i2; +import 'package:autojidelna/src/ui/pages/more_page.dart' as _i3; +import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i4; +import 'package:autojidelna/src/ui/pages/router_page.dart' as _i5; +import 'package:flutter/foundation.dart' as _i7; /// generated route for /// [_i1.DebugPage] -class DebugPage extends _i4.PageRouteInfo { - const DebugPage({List<_i4.PageRouteInfo>? children}) +class DebugPage extends _i6.PageRouteInfo { + const DebugPage({List<_i6.PageRouteInfo>? children}) : super( DebugPage.name, initialChildren: children, @@ -25,7 +27,7 @@ class DebugPage extends _i4.PageRouteInfo { static const String name = 'DebugPage'; - static _i4.PageInfo page = _i4.PageInfo( + static _i6.PageInfo page = _i6.PageInfo( name, builder: (data) { return const _i1.DebugPage(); @@ -34,13 +36,51 @@ class DebugPage extends _i4.PageRouteInfo { } /// generated route for -/// [_i2.RequestPermissionPage] +/// [_i2.MenuPage] +class MenuPage extends _i6.PageRouteInfo { + const MenuPage({List<_i6.PageRouteInfo>? children}) + : super( + MenuPage.name, + initialChildren: children, + ); + + static const String name = 'MenuPage'; + + static _i6.PageInfo page = _i6.PageInfo( + name, + builder: (data) { + return const _i2.MenuPage(); + }, + ); +} + +/// generated route for +/// [_i3.MorePage] +class MorePage extends _i6.PageRouteInfo { + const MorePage({List<_i6.PageRouteInfo>? children}) + : super( + MorePage.name, + initialChildren: children, + ); + + static const String name = 'MorePage'; + + static _i6.PageInfo page = _i6.PageInfo( + name, + builder: (data) { + return const _i3.MorePage(); + }, + ); +} + +/// generated route for +/// [_i4.RequestPermissionPage] class RequestPermissionPage - extends _i4.PageRouteInfo { + extends _i6.PageRouteInfo { RequestPermissionPage({ - _i5.Key? key, + _i7.Key? key, void Function(bool)? onResult, - List<_i4.PageRouteInfo>? children, + List<_i6.PageRouteInfo>? children, }) : super( RequestPermissionPage.name, args: RequestPermissionPageArgs( @@ -52,12 +92,12 @@ class RequestPermissionPage static const String name = 'RequestPermissionPage'; - static _i4.PageInfo page = _i4.PageInfo( + static _i6.PageInfo page = _i6.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const RequestPermissionPageArgs()); - return _i2.RequestPermissionPage( + return _i4.RequestPermissionPage( key: args.key, onResult: args.onResult, ); @@ -71,7 +111,7 @@ class RequestPermissionPageArgs { this.onResult, }); - final _i5.Key? key; + final _i7.Key? key; final void Function(bool)? onResult; @@ -82,9 +122,9 @@ class RequestPermissionPageArgs { } /// generated route for -/// [_i3.RouterPage] -class RouterPage extends _i4.PageRouteInfo { - const RouterPage({List<_i4.PageRouteInfo>? children}) +/// [_i5.RouterPage] +class RouterPage extends _i6.PageRouteInfo { + const RouterPage({List<_i6.PageRouteInfo>? children}) : super( RouterPage.name, initialChildren: children, @@ -92,10 +132,10 @@ class RouterPage extends _i4.PageRouteInfo { static const String name = 'RouterPage'; - static _i4.PageInfo page = _i4.PageInfo( + static _i6.PageInfo page = _i6.PageInfo( name, builder: (data) { - return const _i3.RouterPage(); + return const _i5.RouterPage(); }, ); } diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 595b4e6f..583fca46 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -18,8 +18,11 @@ "languageCzech": "Čeština", "languageEnglish": "Angličtina", "login": "Přihlásit se", + "menu": "Jídelníček", + "more": "Více", "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", + "orders": "Objednávky", "password": "Heslo", "patch": "patch", "requestNotificationPermission": "Požádat o povolení notifikací", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 4dee81d1..99c73b4a 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -145,6 +145,18 @@ abstract class Texts { /// **'Přihlásit se'** String get login; + /// No description provided for @menu. + /// + /// In cs, this message translates to: + /// **'Jídelníček'** + String get menu; + + /// No description provided for @more. + /// + /// In cs, this message translates to: + /// **'Více'** + String get more; + /// No description provided for @noFood. /// /// In cs, this message translates to: @@ -157,6 +169,12 @@ abstract class Texts { /// **'Ne, děkuji'** String get noThankYou; + /// No description provided for @orders. + /// + /// In cs, this message translates to: + /// **'Objednávky'** + String get orders; + /// No description provided for @password. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 2efc6678..c0f2f296 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -43,12 +43,21 @@ class TextsCs extends Texts { @override String get login => 'Přihlásit se'; + @override + String get menu => 'Jídelníček'; + + @override + String get more => 'Více'; + @override String get noFood => 'Žádná jídla pro tento den.'; @override String get noThankYou => 'Ne, děkuji'; + @override + String get orders => 'Objednávky'; + @override String get password => 'Heslo'; diff --git a/lib/src/ui/pages/menu_page.dart b/lib/src/ui/pages/menu_page.dart new file mode 100644 index 00000000..9edc987e --- /dev/null +++ b/lib/src/ui/pages/menu_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class MenuPage extends StatelessWidget { + const MenuPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart new file mode 100644 index 00000000..5282c467 --- /dev/null +++ b/lib/src/ui/pages/more_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class MorePage extends StatelessWidget { + const MorePage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/router_page.dart b/lib/src/ui/pages/router_page.dart index 38bfbbce..d103e1c1 100644 --- a/lib/src/ui/pages/router_page.dart +++ b/lib/src/ui/pages/router_page.dart @@ -1,6 +1,9 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_routing/app_router.gr.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/ui/widgets/router_page_appbars/default_appbar.dart'; +import 'package:autojidelna/src/ui/widgets/appbars/default_appbar.dart'; +import 'package:autojidelna/src/ui/widgets/appbars/menu_page.dart'; +import 'package:autojidelna/src/ui/widgets/appbars/more_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; @@ -33,10 +36,6 @@ class _RouterPageState extends State { }); } - final List routes = [ - // TODO - ]; - @override Widget build(BuildContext context) { final lang = context.l10n; @@ -57,15 +56,31 @@ class _RouterPageState extends State { // use null to not show an appbar for a specific page. Use the defaultAppBar for a default appbar // note: using null will not show the appbar at all. This includes the navigation drawer button. Use with caution. final List appBars = [ - // TODO + (context) => const MenuAppBar(), + (context) => const MoreAppBar(), ]; - final List destinations = [ - // TODO + final List routes = [ + const MenuPage(), + const MorePage(), ]; final List secondaryBodies = [ - // TODO + null, + null, + ]; + + final List destinations = [ + NavigationDestination( + icon: const Icon(Icons.menu_book), + selectedIcon: const Icon(Icons.menu_book_outlined), + label: lang.menu, + ), + NavigationDestination( + icon: const Icon(Icons.more_horiz), + selectedIcon: const Icon(Icons.more_horiz_outlined), + label: lang.more, + ), ]; assert( diff --git a/lib/src/ui/widgets/appbars/default_appbar.dart b/lib/src/ui/widgets/appbars/default_appbar.dart new file mode 100644 index 00000000..ae3efae6 --- /dev/null +++ b/lib/src/ui/widgets/appbars/default_appbar.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class DefaultAppbar extends StatelessWidget implements PreferredSizeWidget { + const DefaultAppbar({super.key, this.leading, this.leadingWidth, this.title, this.actions}); + final Widget? leading; + final double? leadingWidth; + final Widget? title; + final List? actions; + + @override + Widget build(BuildContext context) { + actions?.add(const VerticalDivider(color: Colors.transparent)); + + return AppBar( + leading: leading, + leadingWidth: leadingWidth, + title: title, + actions: actions, + ); + } + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); +} diff --git a/lib/src/ui/widgets/appbars/menu_page.dart b/lib/src/ui/widgets/appbars/menu_page.dart new file mode 100644 index 00000000..bdd5a52b --- /dev/null +++ b/lib/src/ui/widgets/appbars/menu_page.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; + +class MenuAppBar extends StatelessWidget implements PreferredSizeWidget { + const MenuAppBar({super.key}); + + @override + Widget build(BuildContext context) => AppBar(); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); +} diff --git a/lib/src/ui/widgets/appbars/more_page.dart b/lib/src/ui/widgets/appbars/more_page.dart new file mode 100644 index 00000000..5fa14d08 --- /dev/null +++ b/lib/src/ui/widgets/appbars/more_page.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; + +class MoreAppBar extends StatelessWidget implements PreferredSizeWidget { + const MoreAppBar({super.key}); + + @override + Widget build(BuildContext context) => AppBar(automaticallyImplyLeading: false, forceMaterialTransparency: true); + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); +} From 39f1c34b3c26a886205d5bfc27dd2f45a3c2fd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 22:01:34 +0200 Subject: [PATCH 17/57] add all settings pages (placeholder only) --- lib/src/_routing/app_router.dart | 4 + lib/src/_routing/app_router.gr.dart | 148 ++++++++++++++---- lib/src/ui/pages/settings/analytics_page.dart | 12 ++ .../ui/pages/settings/appearance_page.dart | 12 ++ .../ui/pages/settings/convenience_page.dart | 12 ++ lib/src/ui/pages/settings/settings_page.dart | 12 ++ 6 files changed, 166 insertions(+), 34 deletions(-) create mode 100644 lib/src/ui/pages/settings/analytics_page.dart create mode 100644 lib/src/ui/pages/settings/appearance_page.dart create mode 100644 lib/src/ui/pages/settings/convenience_page.dart create mode 100644 lib/src/ui/pages/settings/settings_page.dart diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index 236d572b..ce3592c3 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -15,6 +15,10 @@ class AppRouter extends RootStackRouter { AutoRoute(page: MorePage.page, path: 'more'), ], ), + AutoRoute(page: SettingsPage.page, path: '/settings'), + AutoRoute(page: AnalyticsPage.page, path: '/settings/analytics'), + AutoRoute(page: AppearancePage.page, path: '/settings/appearance'), + AutoRoute(page: ConveniencePage.page, path: '/settings/convenience'), AutoRoute(page: RequestPermissionPage.page, path: '/request-permission'), AutoRoute(page: DebugPage.page, path: '/demo/debug'), RedirectRoute(path: '*', redirectTo: '/'), diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index efd4347f..f6804505 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -8,18 +8,79 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i6; -import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i1; -import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i2; -import 'package:autojidelna/src/ui/pages/more_page.dart' as _i3; -import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i4; -import 'package:autojidelna/src/ui/pages/router_page.dart' as _i5; -import 'package:flutter/foundation.dart' as _i7; +import 'package:auto_route/auto_route.dart' as _i10; +import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i4; +import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i5; +import 'package:autojidelna/src/ui/pages/more_page.dart' as _i6; +import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i7; +import 'package:autojidelna/src/ui/pages/router_page.dart' as _i8; +import 'package:autojidelna/src/ui/pages/settings/analytics_page.dart' as _i1; +import 'package:autojidelna/src/ui/pages/settings/appearance_page.dart' as _i2; +import 'package:autojidelna/src/ui/pages/settings/convenience_page.dart' as _i3; +import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i9; +import 'package:flutter/foundation.dart' as _i11; /// generated route for -/// [_i1.DebugPage] -class DebugPage extends _i6.PageRouteInfo { - const DebugPage({List<_i6.PageRouteInfo>? children}) +/// [_i1.AnalyticsPage] +class AnalyticsPage extends _i10.PageRouteInfo { + const AnalyticsPage({List<_i10.PageRouteInfo>? children}) + : super( + AnalyticsPage.name, + initialChildren: children, + ); + + static const String name = 'AnalyticsPage'; + + static _i10.PageInfo page = _i10.PageInfo( + name, + builder: (data) { + return const _i1.AnalyticsPage(); + }, + ); +} + +/// generated route for +/// [_i2.AppearancePage] +class AppearancePage extends _i10.PageRouteInfo { + const AppearancePage({List<_i10.PageRouteInfo>? children}) + : super( + AppearancePage.name, + initialChildren: children, + ); + + static const String name = 'AppearancePage'; + + static _i10.PageInfo page = _i10.PageInfo( + name, + builder: (data) { + return const _i2.AppearancePage(); + }, + ); +} + +/// generated route for +/// [_i3.ConveniencePage] +class ConveniencePage extends _i10.PageRouteInfo { + const ConveniencePage({List<_i10.PageRouteInfo>? children}) + : super( + ConveniencePage.name, + initialChildren: children, + ); + + static const String name = 'ConveniencePage'; + + static _i10.PageInfo page = _i10.PageInfo( + name, + builder: (data) { + return const _i3.ConveniencePage(); + }, + ); +} + +/// generated route for +/// [_i4.DebugPage] +class DebugPage extends _i10.PageRouteInfo { + const DebugPage({List<_i10.PageRouteInfo>? children}) : super( DebugPage.name, initialChildren: children, @@ -27,18 +88,18 @@ class DebugPage extends _i6.PageRouteInfo { static const String name = 'DebugPage'; - static _i6.PageInfo page = _i6.PageInfo( + static _i10.PageInfo page = _i10.PageInfo( name, builder: (data) { - return const _i1.DebugPage(); + return const _i4.DebugPage(); }, ); } /// generated route for -/// [_i2.MenuPage] -class MenuPage extends _i6.PageRouteInfo { - const MenuPage({List<_i6.PageRouteInfo>? children}) +/// [_i5.MenuPage] +class MenuPage extends _i10.PageRouteInfo { + const MenuPage({List<_i10.PageRouteInfo>? children}) : super( MenuPage.name, initialChildren: children, @@ -46,18 +107,18 @@ class MenuPage extends _i6.PageRouteInfo { static const String name = 'MenuPage'; - static _i6.PageInfo page = _i6.PageInfo( + static _i10.PageInfo page = _i10.PageInfo( name, builder: (data) { - return const _i2.MenuPage(); + return const _i5.MenuPage(); }, ); } /// generated route for -/// [_i3.MorePage] -class MorePage extends _i6.PageRouteInfo { - const MorePage({List<_i6.PageRouteInfo>? children}) +/// [_i6.MorePage] +class MorePage extends _i10.PageRouteInfo { + const MorePage({List<_i10.PageRouteInfo>? children}) : super( MorePage.name, initialChildren: children, @@ -65,22 +126,22 @@ class MorePage extends _i6.PageRouteInfo { static const String name = 'MorePage'; - static _i6.PageInfo page = _i6.PageInfo( + static _i10.PageInfo page = _i10.PageInfo( name, builder: (data) { - return const _i3.MorePage(); + return const _i6.MorePage(); }, ); } /// generated route for -/// [_i4.RequestPermissionPage] +/// [_i7.RequestPermissionPage] class RequestPermissionPage - extends _i6.PageRouteInfo { + extends _i10.PageRouteInfo { RequestPermissionPage({ - _i7.Key? key, + _i11.Key? key, void Function(bool)? onResult, - List<_i6.PageRouteInfo>? children, + List<_i10.PageRouteInfo>? children, }) : super( RequestPermissionPage.name, args: RequestPermissionPageArgs( @@ -92,12 +153,12 @@ class RequestPermissionPage static const String name = 'RequestPermissionPage'; - static _i6.PageInfo page = _i6.PageInfo( + static _i10.PageInfo page = _i10.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const RequestPermissionPageArgs()); - return _i4.RequestPermissionPage( + return _i7.RequestPermissionPage( key: args.key, onResult: args.onResult, ); @@ -111,7 +172,7 @@ class RequestPermissionPageArgs { this.onResult, }); - final _i7.Key? key; + final _i11.Key? key; final void Function(bool)? onResult; @@ -122,9 +183,9 @@ class RequestPermissionPageArgs { } /// generated route for -/// [_i5.RouterPage] -class RouterPage extends _i6.PageRouteInfo { - const RouterPage({List<_i6.PageRouteInfo>? children}) +/// [_i8.RouterPage] +class RouterPage extends _i10.PageRouteInfo { + const RouterPage({List<_i10.PageRouteInfo>? children}) : super( RouterPage.name, initialChildren: children, @@ -132,10 +193,29 @@ class RouterPage extends _i6.PageRouteInfo { static const String name = 'RouterPage'; - static _i6.PageInfo page = _i6.PageInfo( + static _i10.PageInfo page = _i10.PageInfo( + name, + builder: (data) { + return const _i8.RouterPage(); + }, + ); +} + +/// generated route for +/// [_i9.SettingsPage] +class SettingsPage extends _i10.PageRouteInfo { + const SettingsPage({List<_i10.PageRouteInfo>? children}) + : super( + SettingsPage.name, + initialChildren: children, + ); + + static const String name = 'SettingsPage'; + + static _i10.PageInfo page = _i10.PageInfo( name, builder: (data) { - return const _i5.RouterPage(); + return const _i9.SettingsPage(); }, ); } diff --git a/lib/src/ui/pages/settings/analytics_page.dart b/lib/src/ui/pages/settings/analytics_page.dart new file mode 100644 index 00000000..ba45867b --- /dev/null +++ b/lib/src/ui/pages/settings/analytics_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class AnalyticsPage extends StatelessWidget { + const AnalyticsPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/settings/appearance_page.dart b/lib/src/ui/pages/settings/appearance_page.dart new file mode 100644 index 00000000..57b94819 --- /dev/null +++ b/lib/src/ui/pages/settings/appearance_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class AppearancePage extends StatelessWidget { + const AppearancePage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/settings/convenience_page.dart b/lib/src/ui/pages/settings/convenience_page.dart new file mode 100644 index 00000000..f94398a3 --- /dev/null +++ b/lib/src/ui/pages/settings/convenience_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class ConveniencePage extends StatelessWidget { + const ConveniencePage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/settings/settings_page.dart b/lib/src/ui/pages/settings/settings_page.dart new file mode 100644 index 00000000..6b484505 --- /dev/null +++ b/lib/src/ui/pages/settings/settings_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class SettingsPage extends StatelessWidget { + const SettingsPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} From 64d377570c198049a1f2f3e2c4634a2cb647db3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 22:08:30 +0200 Subject: [PATCH 18/57] add all 'more' pages (placeholder only) -add about page - account page - statistics page --- lib/src/_routing/app_router.dart | 3 + lib/src/_routing/app_router.gr.dart | 176 ++++++++++++++------- lib/src/ui/pages/more/about_page.dart | 12 ++ lib/src/ui/pages/more/account_page.dart | 12 ++ lib/src/ui/pages/more/statistics_page.dart | 12 ++ 5 files changed, 157 insertions(+), 58 deletions(-) create mode 100644 lib/src/ui/pages/more/about_page.dart create mode 100644 lib/src/ui/pages/more/account_page.dart create mode 100644 lib/src/ui/pages/more/statistics_page.dart diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index ce3592c3..704c9e21 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -15,10 +15,13 @@ class AppRouter extends RootStackRouter { AutoRoute(page: MorePage.page, path: 'more'), ], ), + AutoRoute(page: AccountPage.page, path: '/account'), + AutoRoute(page: StatisticsPage.page, path: '/statistics'), AutoRoute(page: SettingsPage.page, path: '/settings'), AutoRoute(page: AnalyticsPage.page, path: '/settings/analytics'), AutoRoute(page: AppearancePage.page, path: '/settings/appearance'), AutoRoute(page: ConveniencePage.page, path: '/settings/convenience'), + AutoRoute(page: AboutPage.page, path: '/about'), AutoRoute(page: RequestPermissionPage.page, path: '/request-permission'), AutoRoute(page: DebugPage.page, path: '/demo/debug'), RedirectRoute(path: '*', redirectTo: '/'), diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index f6804505..35b073b6 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -8,22 +8,63 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i10; -import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i4; -import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i5; -import 'package:autojidelna/src/ui/pages/more_page.dart' as _i6; -import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i7; -import 'package:autojidelna/src/ui/pages/router_page.dart' as _i8; -import 'package:autojidelna/src/ui/pages/settings/analytics_page.dart' as _i1; -import 'package:autojidelna/src/ui/pages/settings/appearance_page.dart' as _i2; -import 'package:autojidelna/src/ui/pages/settings/convenience_page.dart' as _i3; -import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i9; -import 'package:flutter/foundation.dart' as _i11; +import 'package:auto_route/auto_route.dart' as _i13; +import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i6; +import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i7; +import 'package:autojidelna/src/ui/pages/more/about_page.dart' as _i1; +import 'package:autojidelna/src/ui/pages/more/account_page.dart' as _i2; +import 'package:autojidelna/src/ui/pages/more/statistics_page.dart' as _i12; +import 'package:autojidelna/src/ui/pages/more_page.dart' as _i8; +import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i9; +import 'package:autojidelna/src/ui/pages/router_page.dart' as _i10; +import 'package:autojidelna/src/ui/pages/settings/analytics_page.dart' as _i3; +import 'package:autojidelna/src/ui/pages/settings/appearance_page.dart' as _i4; +import 'package:autojidelna/src/ui/pages/settings/convenience_page.dart' as _i5; +import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i11; +import 'package:flutter/foundation.dart' as _i14; /// generated route for -/// [_i1.AnalyticsPage] -class AnalyticsPage extends _i10.PageRouteInfo { - const AnalyticsPage({List<_i10.PageRouteInfo>? children}) +/// [_i1.AboutPage] +class AboutPage extends _i13.PageRouteInfo { + const AboutPage({List<_i13.PageRouteInfo>? children}) + : super( + AboutPage.name, + initialChildren: children, + ); + + static const String name = 'AboutPage'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i1.AboutPage(); + }, + ); +} + +/// generated route for +/// [_i2.AccountPage] +class AccountPage extends _i13.PageRouteInfo { + const AccountPage({List<_i13.PageRouteInfo>? children}) + : super( + AccountPage.name, + initialChildren: children, + ); + + static const String name = 'AccountPage'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i2.AccountPage(); + }, + ); +} + +/// generated route for +/// [_i3.AnalyticsPage] +class AnalyticsPage extends _i13.PageRouteInfo { + const AnalyticsPage({List<_i13.PageRouteInfo>? children}) : super( AnalyticsPage.name, initialChildren: children, @@ -31,18 +72,18 @@ class AnalyticsPage extends _i10.PageRouteInfo { static const String name = 'AnalyticsPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i1.AnalyticsPage(); + return const _i3.AnalyticsPage(); }, ); } /// generated route for -/// [_i2.AppearancePage] -class AppearancePage extends _i10.PageRouteInfo { - const AppearancePage({List<_i10.PageRouteInfo>? children}) +/// [_i4.AppearancePage] +class AppearancePage extends _i13.PageRouteInfo { + const AppearancePage({List<_i13.PageRouteInfo>? children}) : super( AppearancePage.name, initialChildren: children, @@ -50,18 +91,18 @@ class AppearancePage extends _i10.PageRouteInfo { static const String name = 'AppearancePage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i2.AppearancePage(); + return const _i4.AppearancePage(); }, ); } /// generated route for -/// [_i3.ConveniencePage] -class ConveniencePage extends _i10.PageRouteInfo { - const ConveniencePage({List<_i10.PageRouteInfo>? children}) +/// [_i5.ConveniencePage] +class ConveniencePage extends _i13.PageRouteInfo { + const ConveniencePage({List<_i13.PageRouteInfo>? children}) : super( ConveniencePage.name, initialChildren: children, @@ -69,18 +110,18 @@ class ConveniencePage extends _i10.PageRouteInfo { static const String name = 'ConveniencePage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i3.ConveniencePage(); + return const _i5.ConveniencePage(); }, ); } /// generated route for -/// [_i4.DebugPage] -class DebugPage extends _i10.PageRouteInfo { - const DebugPage({List<_i10.PageRouteInfo>? children}) +/// [_i6.DebugPage] +class DebugPage extends _i13.PageRouteInfo { + const DebugPage({List<_i13.PageRouteInfo>? children}) : super( DebugPage.name, initialChildren: children, @@ -88,18 +129,18 @@ class DebugPage extends _i10.PageRouteInfo { static const String name = 'DebugPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i4.DebugPage(); + return const _i6.DebugPage(); }, ); } /// generated route for -/// [_i5.MenuPage] -class MenuPage extends _i10.PageRouteInfo { - const MenuPage({List<_i10.PageRouteInfo>? children}) +/// [_i7.MenuPage] +class MenuPage extends _i13.PageRouteInfo { + const MenuPage({List<_i13.PageRouteInfo>? children}) : super( MenuPage.name, initialChildren: children, @@ -107,18 +148,18 @@ class MenuPage extends _i10.PageRouteInfo { static const String name = 'MenuPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i5.MenuPage(); + return const _i7.MenuPage(); }, ); } /// generated route for -/// [_i6.MorePage] -class MorePage extends _i10.PageRouteInfo { - const MorePage({List<_i10.PageRouteInfo>? children}) +/// [_i8.MorePage] +class MorePage extends _i13.PageRouteInfo { + const MorePage({List<_i13.PageRouteInfo>? children}) : super( MorePage.name, initialChildren: children, @@ -126,22 +167,22 @@ class MorePage extends _i10.PageRouteInfo { static const String name = 'MorePage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i6.MorePage(); + return const _i8.MorePage(); }, ); } /// generated route for -/// [_i7.RequestPermissionPage] +/// [_i9.RequestPermissionPage] class RequestPermissionPage - extends _i10.PageRouteInfo { + extends _i13.PageRouteInfo { RequestPermissionPage({ - _i11.Key? key, + _i14.Key? key, void Function(bool)? onResult, - List<_i10.PageRouteInfo>? children, + List<_i13.PageRouteInfo>? children, }) : super( RequestPermissionPage.name, args: RequestPermissionPageArgs( @@ -153,12 +194,12 @@ class RequestPermissionPage static const String name = 'RequestPermissionPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const RequestPermissionPageArgs()); - return _i7.RequestPermissionPage( + return _i9.RequestPermissionPage( key: args.key, onResult: args.onResult, ); @@ -172,7 +213,7 @@ class RequestPermissionPageArgs { this.onResult, }); - final _i11.Key? key; + final _i14.Key? key; final void Function(bool)? onResult; @@ -183,9 +224,9 @@ class RequestPermissionPageArgs { } /// generated route for -/// [_i8.RouterPage] -class RouterPage extends _i10.PageRouteInfo { - const RouterPage({List<_i10.PageRouteInfo>? children}) +/// [_i10.RouterPage] +class RouterPage extends _i13.PageRouteInfo { + const RouterPage({List<_i13.PageRouteInfo>? children}) : super( RouterPage.name, initialChildren: children, @@ -193,18 +234,18 @@ class RouterPage extends _i10.PageRouteInfo { static const String name = 'RouterPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i8.RouterPage(); + return const _i10.RouterPage(); }, ); } /// generated route for -/// [_i9.SettingsPage] -class SettingsPage extends _i10.PageRouteInfo { - const SettingsPage({List<_i10.PageRouteInfo>? children}) +/// [_i11.SettingsPage] +class SettingsPage extends _i13.PageRouteInfo { + const SettingsPage({List<_i13.PageRouteInfo>? children}) : super( SettingsPage.name, initialChildren: children, @@ -212,10 +253,29 @@ class SettingsPage extends _i10.PageRouteInfo { static const String name = 'SettingsPage'; - static _i10.PageInfo page = _i10.PageInfo( + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i11.SettingsPage(); + }, + ); +} + +/// generated route for +/// [_i12.StatisticsPage] +class StatisticsPage extends _i13.PageRouteInfo { + const StatisticsPage({List<_i13.PageRouteInfo>? children}) + : super( + StatisticsPage.name, + initialChildren: children, + ); + + static const String name = 'StatisticsPage'; + + static _i13.PageInfo page = _i13.PageInfo( name, builder: (data) { - return const _i9.SettingsPage(); + return const _i12.StatisticsPage(); }, ); } diff --git a/lib/src/ui/pages/more/about_page.dart b/lib/src/ui/pages/more/about_page.dart new file mode 100644 index 00000000..7de0e9f6 --- /dev/null +++ b/lib/src/ui/pages/more/about_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class AboutPage extends StatelessWidget { + const AboutPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/more/account_page.dart b/lib/src/ui/pages/more/account_page.dart new file mode 100644 index 00000000..b7bf348a --- /dev/null +++ b/lib/src/ui/pages/more/account_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class AccountPage extends StatelessWidget { + const AccountPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/more/statistics_page.dart b/lib/src/ui/pages/more/statistics_page.dart new file mode 100644 index 00000000..6234f691 --- /dev/null +++ b/lib/src/ui/pages/more/statistics_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class StatisticsPage extends StatelessWidget { + const StatisticsPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} From 083af9bd6ab858aba771701368df331c415e478a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 22:14:05 +0200 Subject: [PATCH 19/57] add remaining pages (placeholder only) - dish detail page - login page --- lib/src/_routing/app_router.dart | 2 + lib/src/_routing/app_router.gr.dart | 156 ++++++++++++++++--------- lib/src/ui/pages/dish_detail_page.dart | 12 ++ lib/src/ui/pages/login_page.dart | 12 ++ 4 files changed, 124 insertions(+), 58 deletions(-) create mode 100644 lib/src/ui/pages/dish_detail_page.dart create mode 100644 lib/src/ui/pages/login_page.dart diff --git a/lib/src/_routing/app_router.dart b/lib/src/_routing/app_router.dart index 704c9e21..d553c777 100644 --- a/lib/src/_routing/app_router.dart +++ b/lib/src/_routing/app_router.dart @@ -15,6 +15,8 @@ class AppRouter extends RootStackRouter { AutoRoute(page: MorePage.page, path: 'more'), ], ), + AutoRoute(page: DishDetailPage.page, path: '/detail'), + AutoRoute(page: LoginPage.page, path: '/login'), AutoRoute(page: AccountPage.page, path: '/account'), AutoRoute(page: StatisticsPage.page, path: '/statistics'), AutoRoute(page: SettingsPage.page, path: '/settings'), diff --git a/lib/src/_routing/app_router.gr.dart b/lib/src/_routing/app_router.gr.dart index 35b073b6..5e1a7693 100644 --- a/lib/src/_routing/app_router.gr.dart +++ b/lib/src/_routing/app_router.gr.dart @@ -8,25 +8,27 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i13; +import 'package:auto_route/auto_route.dart' as _i15; import 'package:autojidelna/src/ui/pages/dev/debug_page.dart' as _i6; -import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i7; +import 'package:autojidelna/src/ui/pages/dish_detail_page.dart' as _i7; +import 'package:autojidelna/src/ui/pages/login_page.dart' as _i8; +import 'package:autojidelna/src/ui/pages/menu_page.dart' as _i9; import 'package:autojidelna/src/ui/pages/more/about_page.dart' as _i1; import 'package:autojidelna/src/ui/pages/more/account_page.dart' as _i2; -import 'package:autojidelna/src/ui/pages/more/statistics_page.dart' as _i12; -import 'package:autojidelna/src/ui/pages/more_page.dart' as _i8; -import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i9; -import 'package:autojidelna/src/ui/pages/router_page.dart' as _i10; +import 'package:autojidelna/src/ui/pages/more/statistics_page.dart' as _i14; +import 'package:autojidelna/src/ui/pages/more_page.dart' as _i10; +import 'package:autojidelna/src/ui/pages/request_permission_page.dart' as _i11; +import 'package:autojidelna/src/ui/pages/router_page.dart' as _i12; import 'package:autojidelna/src/ui/pages/settings/analytics_page.dart' as _i3; import 'package:autojidelna/src/ui/pages/settings/appearance_page.dart' as _i4; import 'package:autojidelna/src/ui/pages/settings/convenience_page.dart' as _i5; -import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i11; -import 'package:flutter/foundation.dart' as _i14; +import 'package:autojidelna/src/ui/pages/settings/settings_page.dart' as _i13; +import 'package:flutter/foundation.dart' as _i16; /// generated route for /// [_i1.AboutPage] -class AboutPage extends _i13.PageRouteInfo { - const AboutPage({List<_i13.PageRouteInfo>? children}) +class AboutPage extends _i15.PageRouteInfo { + const AboutPage({List<_i15.PageRouteInfo>? children}) : super( AboutPage.name, initialChildren: children, @@ -34,7 +36,7 @@ class AboutPage extends _i13.PageRouteInfo { static const String name = 'AboutPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i1.AboutPage(); @@ -44,8 +46,8 @@ class AboutPage extends _i13.PageRouteInfo { /// generated route for /// [_i2.AccountPage] -class AccountPage extends _i13.PageRouteInfo { - const AccountPage({List<_i13.PageRouteInfo>? children}) +class AccountPage extends _i15.PageRouteInfo { + const AccountPage({List<_i15.PageRouteInfo>? children}) : super( AccountPage.name, initialChildren: children, @@ -53,7 +55,7 @@ class AccountPage extends _i13.PageRouteInfo { static const String name = 'AccountPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i2.AccountPage(); @@ -63,8 +65,8 @@ class AccountPage extends _i13.PageRouteInfo { /// generated route for /// [_i3.AnalyticsPage] -class AnalyticsPage extends _i13.PageRouteInfo { - const AnalyticsPage({List<_i13.PageRouteInfo>? children}) +class AnalyticsPage extends _i15.PageRouteInfo { + const AnalyticsPage({List<_i15.PageRouteInfo>? children}) : super( AnalyticsPage.name, initialChildren: children, @@ -72,7 +74,7 @@ class AnalyticsPage extends _i13.PageRouteInfo { static const String name = 'AnalyticsPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i3.AnalyticsPage(); @@ -82,8 +84,8 @@ class AnalyticsPage extends _i13.PageRouteInfo { /// generated route for /// [_i4.AppearancePage] -class AppearancePage extends _i13.PageRouteInfo { - const AppearancePage({List<_i13.PageRouteInfo>? children}) +class AppearancePage extends _i15.PageRouteInfo { + const AppearancePage({List<_i15.PageRouteInfo>? children}) : super( AppearancePage.name, initialChildren: children, @@ -91,7 +93,7 @@ class AppearancePage extends _i13.PageRouteInfo { static const String name = 'AppearancePage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i4.AppearancePage(); @@ -101,8 +103,8 @@ class AppearancePage extends _i13.PageRouteInfo { /// generated route for /// [_i5.ConveniencePage] -class ConveniencePage extends _i13.PageRouteInfo { - const ConveniencePage({List<_i13.PageRouteInfo>? children}) +class ConveniencePage extends _i15.PageRouteInfo { + const ConveniencePage({List<_i15.PageRouteInfo>? children}) : super( ConveniencePage.name, initialChildren: children, @@ -110,7 +112,7 @@ class ConveniencePage extends _i13.PageRouteInfo { static const String name = 'ConveniencePage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i5.ConveniencePage(); @@ -120,8 +122,8 @@ class ConveniencePage extends _i13.PageRouteInfo { /// generated route for /// [_i6.DebugPage] -class DebugPage extends _i13.PageRouteInfo { - const DebugPage({List<_i13.PageRouteInfo>? children}) +class DebugPage extends _i15.PageRouteInfo { + const DebugPage({List<_i15.PageRouteInfo>? children}) : super( DebugPage.name, initialChildren: children, @@ -129,7 +131,7 @@ class DebugPage extends _i13.PageRouteInfo { static const String name = 'DebugPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { return const _i6.DebugPage(); @@ -138,9 +140,47 @@ class DebugPage extends _i13.PageRouteInfo { } /// generated route for -/// [_i7.MenuPage] -class MenuPage extends _i13.PageRouteInfo { - const MenuPage({List<_i13.PageRouteInfo>? children}) +/// [_i7.DishDetailPage] +class DishDetailPage extends _i15.PageRouteInfo { + const DishDetailPage({List<_i15.PageRouteInfo>? children}) + : super( + DishDetailPage.name, + initialChildren: children, + ); + + static const String name = 'DishDetailPage'; + + static _i15.PageInfo page = _i15.PageInfo( + name, + builder: (data) { + return const _i7.DishDetailPage(); + }, + ); +} + +/// generated route for +/// [_i8.LoginPage] +class LoginPage extends _i15.PageRouteInfo { + const LoginPage({List<_i15.PageRouteInfo>? children}) + : super( + LoginPage.name, + initialChildren: children, + ); + + static const String name = 'LoginPage'; + + static _i15.PageInfo page = _i15.PageInfo( + name, + builder: (data) { + return const _i8.LoginPage(); + }, + ); +} + +/// generated route for +/// [_i9.MenuPage] +class MenuPage extends _i15.PageRouteInfo { + const MenuPage({List<_i15.PageRouteInfo>? children}) : super( MenuPage.name, initialChildren: children, @@ -148,18 +188,18 @@ class MenuPage extends _i13.PageRouteInfo { static const String name = 'MenuPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { - return const _i7.MenuPage(); + return const _i9.MenuPage(); }, ); } /// generated route for -/// [_i8.MorePage] -class MorePage extends _i13.PageRouteInfo { - const MorePage({List<_i13.PageRouteInfo>? children}) +/// [_i10.MorePage] +class MorePage extends _i15.PageRouteInfo { + const MorePage({List<_i15.PageRouteInfo>? children}) : super( MorePage.name, initialChildren: children, @@ -167,22 +207,22 @@ class MorePage extends _i13.PageRouteInfo { static const String name = 'MorePage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { - return const _i8.MorePage(); + return const _i10.MorePage(); }, ); } /// generated route for -/// [_i9.RequestPermissionPage] +/// [_i11.RequestPermissionPage] class RequestPermissionPage - extends _i13.PageRouteInfo { + extends _i15.PageRouteInfo { RequestPermissionPage({ - _i14.Key? key, + _i16.Key? key, void Function(bool)? onResult, - List<_i13.PageRouteInfo>? children, + List<_i15.PageRouteInfo>? children, }) : super( RequestPermissionPage.name, args: RequestPermissionPageArgs( @@ -194,12 +234,12 @@ class RequestPermissionPage static const String name = 'RequestPermissionPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { final args = data.argsAs( orElse: () => const RequestPermissionPageArgs()); - return _i9.RequestPermissionPage( + return _i11.RequestPermissionPage( key: args.key, onResult: args.onResult, ); @@ -213,7 +253,7 @@ class RequestPermissionPageArgs { this.onResult, }); - final _i14.Key? key; + final _i16.Key? key; final void Function(bool)? onResult; @@ -224,9 +264,9 @@ class RequestPermissionPageArgs { } /// generated route for -/// [_i10.RouterPage] -class RouterPage extends _i13.PageRouteInfo { - const RouterPage({List<_i13.PageRouteInfo>? children}) +/// [_i12.RouterPage] +class RouterPage extends _i15.PageRouteInfo { + const RouterPage({List<_i15.PageRouteInfo>? children}) : super( RouterPage.name, initialChildren: children, @@ -234,18 +274,18 @@ class RouterPage extends _i13.PageRouteInfo { static const String name = 'RouterPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { - return const _i10.RouterPage(); + return const _i12.RouterPage(); }, ); } /// generated route for -/// [_i11.SettingsPage] -class SettingsPage extends _i13.PageRouteInfo { - const SettingsPage({List<_i13.PageRouteInfo>? children}) +/// [_i13.SettingsPage] +class SettingsPage extends _i15.PageRouteInfo { + const SettingsPage({List<_i15.PageRouteInfo>? children}) : super( SettingsPage.name, initialChildren: children, @@ -253,18 +293,18 @@ class SettingsPage extends _i13.PageRouteInfo { static const String name = 'SettingsPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { - return const _i11.SettingsPage(); + return const _i13.SettingsPage(); }, ); } /// generated route for -/// [_i12.StatisticsPage] -class StatisticsPage extends _i13.PageRouteInfo { - const StatisticsPage({List<_i13.PageRouteInfo>? children}) +/// [_i14.StatisticsPage] +class StatisticsPage extends _i15.PageRouteInfo { + const StatisticsPage({List<_i15.PageRouteInfo>? children}) : super( StatisticsPage.name, initialChildren: children, @@ -272,10 +312,10 @@ class StatisticsPage extends _i13.PageRouteInfo { static const String name = 'StatisticsPage'; - static _i13.PageInfo page = _i13.PageInfo( + static _i15.PageInfo page = _i15.PageInfo( name, builder: (data) { - return const _i12.StatisticsPage(); + return const _i14.StatisticsPage(); }, ); } diff --git a/lib/src/ui/pages/dish_detail_page.dart b/lib/src/ui/pages/dish_detail_page.dart new file mode 100644 index 00000000..3c8e7c4b --- /dev/null +++ b/lib/src/ui/pages/dish_detail_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class DishDetailPage extends StatelessWidget { + const DishDetailPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/src/ui/pages/login_page.dart b/lib/src/ui/pages/login_page.dart new file mode 100644 index 00000000..08980b23 --- /dev/null +++ b/lib/src/ui/pages/login_page.dart @@ -0,0 +1,12 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class LoginPage extends StatelessWidget { + const LoginPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} From 919b784b31f2032e6722a36c11eb64af3540f31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 22:17:53 +0200 Subject: [PATCH 20/57] add custom divider & ScrollViewColumn --- lib/src/ui/widgets/custom_divider.dart | 26 +++++++++++++++++++ .../router_page_appbars/default_appbar.dart | 24 ----------------- lib/src/ui/widgets/scroll_view_column.dart | 20 ++++++++++++++ 3 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 lib/src/ui/widgets/custom_divider.dart delete mode 100644 lib/src/ui/widgets/router_page_appbars/default_appbar.dart create mode 100644 lib/src/ui/widgets/scroll_view_column.dart diff --git a/lib/src/ui/widgets/custom_divider.dart b/lib/src/ui/widgets/custom_divider.dart new file mode 100644 index 00000000..5885b192 --- /dev/null +++ b/lib/src/ui/widgets/custom_divider.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class CustomDivider extends StatelessWidget { + const CustomDivider({ + super.key, + this.height, + this.isTransparent = true, + this.hasIndent = true, + this.hasEndIndent = true, + }); + final double? height; + final bool isTransparent; + final bool hasIndent; + final bool hasEndIndent; + + @override + Widget build(BuildContext context) { + double indent = MediaQuery.sizeOf(context).width * 0.025; + return Divider( + color: isTransparent ? Colors.transparent : null, + height: height, + indent: hasIndent ? indent : null, + endIndent: hasEndIndent ? indent : null, + ); + } +} diff --git a/lib/src/ui/widgets/router_page_appbars/default_appbar.dart b/lib/src/ui/widgets/router_page_appbars/default_appbar.dart deleted file mode 100644 index ae3efae6..00000000 --- a/lib/src/ui/widgets/router_page_appbars/default_appbar.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; - -class DefaultAppbar extends StatelessWidget implements PreferredSizeWidget { - const DefaultAppbar({super.key, this.leading, this.leadingWidth, this.title, this.actions}); - final Widget? leading; - final double? leadingWidth; - final Widget? title; - final List? actions; - - @override - Widget build(BuildContext context) { - actions?.add(const VerticalDivider(color: Colors.transparent)); - - return AppBar( - leading: leading, - leadingWidth: leadingWidth, - title: title, - actions: actions, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); -} diff --git a/lib/src/ui/widgets/scroll_view_column.dart b/lib/src/ui/widgets/scroll_view_column.dart new file mode 100644 index 00000000..7f723a4c --- /dev/null +++ b/lib/src/ui/widgets/scroll_view_column.dart @@ -0,0 +1,20 @@ +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:flutter/material.dart'; + +class ScrollViewColumn extends StatelessWidget { + const ScrollViewColumn({ + super.key, + this.children = const [], + }); + final List children; + + @override + Widget build(BuildContext context) { + children.add(const CustomDivider()); + return SingleChildScrollView( + child: Column( + children: children, + ), + ); + } +} From 25dfa4b1ad28d500c0eb8b4cf0e844ecd54d43b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Tue, 1 Oct 2024 22:31:41 +0200 Subject: [PATCH 21/57] complete settings page migration --- lib/src/lang/app_cs.arb | 5 +++ lib/src/lang/output/texts.dart | 30 ++++++++++++++ lib/src/lang/output/texts_cs.dart | 15 +++++++ lib/src/ui/pages/settings/settings_page.dart | 42 +++++++++++++++++++- 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 583fca46..b2ae19c5 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -1,7 +1,11 @@ { "@@locale": "cs", + "about": "O aplikaci", + "analytics": "Shromažďování údajů", "appName": "Autojídelna", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", + "appearance": "Vzhled", + "convenience": "Pohodlí", "gettingDataNotifications": "Získávám data pro oznámení", "internetConnectionState": "{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}", "@internetConnectionState": { @@ -22,6 +26,7 @@ "more": "Více", "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", + "notifications": "Oznámení", "orders": "Objednávky", "password": "Heslo", "patch": "patch", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 99c73b4a..6b5104bc 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -91,6 +91,18 @@ abstract class Texts { /// A list of this localizations delegate's supported locales. static const List supportedLocales = [Locale('cs')]; + /// No description provided for @about. + /// + /// In cs, this message translates to: + /// **'O aplikaci'** + String get about; + + /// No description provided for @analytics. + /// + /// In cs, this message translates to: + /// **'Shromažďování údajů'** + String get analytics; + /// No description provided for @appName. /// /// In cs, this message translates to: @@ -103,6 +115,18 @@ abstract class Texts { /// **'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'** String get appDescription; + /// No description provided for @appearance. + /// + /// In cs, this message translates to: + /// **'Vzhled'** + String get appearance; + + /// No description provided for @convenience. + /// + /// In cs, this message translates to: + /// **'Pohodlí'** + String get convenience; + /// No description provided for @gettingDataNotifications. /// /// In cs, this message translates to: @@ -169,6 +193,12 @@ abstract class Texts { /// **'Ne, děkuji'** String get noThankYou; + /// No description provided for @notifications. + /// + /// In cs, this message translates to: + /// **'Oznámení'** + String get notifications; + /// No description provided for @orders. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index c0f2f296..8f07e6f4 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -6,6 +6,12 @@ import 'texts.dart'; class TextsCs extends Texts { TextsCs([String locale = 'cs']) : super(locale); + @override + String get about => 'O aplikaci'; + + @override + String get analytics => 'Shromažďování údajů'; + @override String get appName => 'Autojídelna'; @@ -13,6 +19,12 @@ class TextsCs extends Texts { String get appDescription => 'Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.'; + @override + String get appearance => 'Vzhled'; + + @override + String get convenience => 'Pohodlí'; + @override String get gettingDataNotifications => 'Získávám data pro oznámení'; @@ -55,6 +67,9 @@ class TextsCs extends Texts { @override String get noThankYou => 'Ne, děkuji'; + @override + String get notifications => 'Oznámení'; + @override String get orders => 'Objednávky'; diff --git a/lib/src/ui/pages/settings/settings_page.dart b/lib/src/ui/pages/settings/settings_page.dart index 6b484505..0752b37e 100644 --- a/lib/src/ui/pages/settings/settings_page.dart +++ b/lib/src/ui/pages/settings/settings_page.dart @@ -1,4 +1,9 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_routing/app_router.gr.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; @RoutePage() @@ -7,6 +12,41 @@ class SettingsPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + final StackRouter router = context.router; + + return Scaffold( + appBar: AppBar(title: Text(lang.settings)), + body: ScrollViewColumn( + children: [ + const CustomDivider(height: 4), + ListTile( + leading: const Icon(Icons.palette_outlined), + title: Text(lang.appearance), + onTap: () async => router.push(const AppearancePage()), + ), + ListTile( + leading: const Icon(Icons.tune_outlined), + title: Text(lang.convenience), + onTap: () async => router.push(const ConveniencePage()), + ), + ListTile( + leading: const Icon(Icons.edit_notifications_outlined), + title: Text(lang.notifications), + onTap: () async => AwesomeNotifications().showNotificationConfigPage(), + ), + ListTile( + leading: const Icon(Icons.cookie_outlined), + title: Text(lang.analytics), + onTap: () async => router.push(const AnalyticsPage()), + ), + ListTile( + leading: const Icon(Icons.info_outline), + title: Text(lang.about), + onTap: () async => router.push(const AboutPage()), + ), + ], + ), + ); } } From d80435c027137bb16c1d2b0b9ca4933cd4673a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Wed, 2 Oct 2024 11:13:02 +0200 Subject: [PATCH 22/57] migrate settings provider --- .../_global/providers/settings.provider.dart | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 lib/src/_global/providers/settings.provider.dart diff --git a/lib/src/_global/providers/settings.provider.dart b/lib/src/_global/providers/settings.provider.dart new file mode 100644 index 00000000..7587ebf6 --- /dev/null +++ b/lib/src/_global/providers/settings.provider.dart @@ -0,0 +1,112 @@ +import 'dart:async'; + +import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/types/all.dart'; +import 'package:autojidelna/src/types/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; + +class Settings with ChangeNotifier { + static Box box = Hive.box(Boxes.settings); + + ThemeStyle _themeStyle = box.get(HiveKeys.themeStyle, defaultValue: ThemeStyle.defaultStyle); + ThemeMode _themeMode = box.get(HiveKeys.themeMode, defaultValue: ThemeMode.dark); + bool _isListUi = box.get(HiveKeys.listUi, defaultValue: false); + bool _amoledMode = box.get(HiveKeys.amoledMode, defaultValue: false); + bool _bigCalendarMarkers = box.get(HiveKeys.bigCalendarMarkers, defaultValue: false); + bool _skipWeekends = box.get(HiveKeys.skipWeekends, defaultValue: false); + DateFormatOptions _dateFormat = box.get(HiveKeys.dateFormat, defaultValue: DateFormatOptions.dMy); + bool _relTimeStamps = box.get(HiveKeys.relTimeStamps, defaultValue: false); + bool _disableAnalytics = box.get(HiveKeys.analytics, defaultValue: false); + + /// Theme style getter + ThemeStyle get themeStyle => _themeStyle; + + /// Theme mode getter + ThemeMode get themeMode => _themeMode; + + /// List UI getter + bool get isListUi => _isListUi; + + /// Amoled mode getter + bool get amoledMode => _amoledMode; + + /// Big calendar markers getter + bool get bigCalendarMarkers => _bigCalendarMarkers; + + /// Skip weekends getter + bool get getSkipWeekends => _skipWeekends; + + /// Date Format getter + DateFormatOptions get dateFormat => _dateFormat; + + /// Relative TimeStamps getter + bool get relTimeStamps => _relTimeStamps; + + /// Analytics getter + bool get disableAnalytics => _disableAnalytics; + + /// Setter for theme style + void setThemeStyle(ThemeStyle themeStyle) { + if (_themeStyle == themeStyle) return; + _themeStyle = themeStyle; + unawaited(box.put(HiveKeys.themeStyle, _themeStyle)); + notifyListeners(); + } + + /// Setter for theme mode + void setThemeMode(ThemeMode themeMode) { + _themeMode = themeMode; + unawaited(box.put(HiveKeys.themeMode, _themeMode)); + notifyListeners(); + } + + /// Setter for list UI + void setListUi(bool isListUi) { + _isListUi = isListUi; + unawaited(box.put(HiveKeys.listUi, _isListUi)); + notifyListeners(); + } + + /// Setter for amoled mode + void setAmoledMode(bool amoledMode) { + _amoledMode = amoledMode; + unawaited(box.put(HiveKeys.amoledMode, _amoledMode)); + notifyListeners(); + } + + /// Setter for big calendar markers + void setCalendarMarkers(bool bigCalendarMarkers) { + _bigCalendarMarkers = bigCalendarMarkers; + unawaited(box.put(HiveKeys.bigCalendarMarkers, _bigCalendarMarkers)); + notifyListeners(); + } + + /// Setter for date format + void setDateFormat(DateFormatOptions dateFormat) { + _dateFormat = dateFormat; + unawaited(box.put(HiveKeys.dateFormat, _dateFormat)); + notifyListeners(); + } + + /// Setter for relative timestamps + void setRelTimeStamps(bool relTimeStamps) { + _relTimeStamps = relTimeStamps; + unawaited(box.put(HiveKeys.relTimeStamps, _relTimeStamps)); + notifyListeners(); + } + + /// Setter for skip weekends + void setSkipWeekends(bool privateSkipWeekends) { + _skipWeekends = privateSkipWeekends; + unawaited(box.put(HiveKeys.skipWeekends, _skipWeekends)); + notifyListeners(); + } + + /// Setter for analytics + void setAnalytics(bool disabled) { + _disableAnalytics = disabled; + unawaited(box.put(HiveKeys.analytics, _disableAnalytics)); + notifyListeners(); + } +} From 5f5fee342c614d80a5f87a961ea666e0559d90e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Wed, 2 Oct 2024 11:13:46 +0200 Subject: [PATCH 23/57] migrate SectionTitle() widget --- lib/src/ui/widgets/section_title.dart | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 lib/src/ui/widgets/section_title.dart diff --git a/lib/src/ui/widgets/section_title.dart b/lib/src/ui/widgets/section_title.dart new file mode 100644 index 00000000..59e67d4a --- /dev/null +++ b/lib/src/ui/widgets/section_title.dart @@ -0,0 +1,26 @@ +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:flutter/material.dart'; + +class SectionTitle extends StatelessWidget { + const SectionTitle(this.title, {super.key}); + final String title; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CustomDivider(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + title, + style: Theme.of(context).textTheme.titleMedium!.copyWith(color: Theme.of(context).colorScheme.primary), + ), + ), + const CustomDivider(height: 8, isTransparent: false), + const CustomDivider(height: 4), + ], + ); + } +} From 9738759d78a2c272ff78080ecdceb775f6eafe5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Wed, 2 Oct 2024 11:28:21 +0200 Subject: [PATCH 24/57] migrate analytics page --- lib/src/lang/app_cs.arb | 5 ++ lib/src/lang/output/texts.dart | 30 +++++++++ lib/src/lang/output/texts_cs.dart | 16 +++++ lib/src/ui/material_app.dart | 2 + lib/src/ui/pages/settings/analytics_page.dart | 63 ++++++++++++++++++- 5 files changed, 115 insertions(+), 1 deletion(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index b2ae19c5..4753e7d3 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -2,6 +2,10 @@ "@@locale": "cs", "about": "O aplikaci", "analytics": "Shromažďování údajů", + "analyticsDescription_1": "Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve ", + "analyticsDescription_2": "Zdrojovém kódu", + "analyticsDescription_3": " nebo v ", + "analyticsDescription_4": "Zásadách ochrany osobních údajů.", "appName": "Autojídelna", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", "appearance": "Vzhled", @@ -33,6 +37,7 @@ "requestNotificationPermission": "Požádat o povolení notifikací", "settings": "Nastavení", "signOut": "Odhlásit se", + "stopAnalytics": "Zastavit sledování analytických služeb", "themeModeSystem": "Systém", "themeModeLight": "Světlý", "themeModeDark": "Tmavý", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 6b5104bc..274993d1 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -103,6 +103,30 @@ abstract class Texts { /// **'Shromažďování údajů'** String get analytics; + /// No description provided for @analyticsDescription_1. + /// + /// In cs, this message translates to: + /// **'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '** + String get analyticsDescription_1; + + /// No description provided for @analyticsDescription_2. + /// + /// In cs, this message translates to: + /// **'Zdrojovém kódu'** + String get analyticsDescription_2; + + /// No description provided for @analyticsDescription_3. + /// + /// In cs, this message translates to: + /// **' nebo v '** + String get analyticsDescription_3; + + /// No description provided for @analyticsDescription_4. + /// + /// In cs, this message translates to: + /// **'Zásadách ochrany osobních údajů.'** + String get analyticsDescription_4; + /// No description provided for @appName. /// /// In cs, this message translates to: @@ -235,6 +259,12 @@ abstract class Texts { /// **'Odhlásit se'** String get signOut; + /// No description provided for @stopAnalytics. + /// + /// In cs, this message translates to: + /// **'Zastavit sledování analytických služeb'** + String get stopAnalytics; + /// No description provided for @themeModeSystem. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 8f07e6f4..b52b65a2 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -12,6 +12,19 @@ class TextsCs extends Texts { @override String get analytics => 'Shromažďování údajů'; + @override + String get analyticsDescription_1 => + 'Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve '; + + @override + String get analyticsDescription_2 => 'Zdrojovém kódu'; + + @override + String get analyticsDescription_3 => ' nebo v '; + + @override + String get analyticsDescription_4 => 'Zásadách ochrany osobních údajů.'; + @override String get appName => 'Autojídelna'; @@ -88,6 +101,9 @@ class TextsCs extends Texts { @override String get signOut => 'Odhlásit se'; + @override + String get stopAnalytics => 'Zastavit sledování analytických služeb'; + @override String get themeModeSystem => 'Systém'; diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index 72199b52..3de0c17d 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_global/app.dart'; +import 'package:autojidelna/src/_global/providers/settings.provider.dart'; import 'package:autojidelna/src/_global/providers/theme.provider.dart'; import 'package:autojidelna/src/_sentry/sentry.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; @@ -83,6 +84,7 @@ class MyAppWrapper extends StatelessWidget { providers: [ ChangeNotifierProvider.value(value: App.remoteConfigProvider), ChangeNotifierProvider(create: (_) => ThemeProvider()), + ChangeNotifierProvider(create: (_) => Settings()) ], child: const MyApp(), ); diff --git a/lib/src/ui/pages/settings/analytics_page.dart b/lib/src/ui/pages/settings/analytics_page.dart index ba45867b..e7270a38 100644 --- a/lib/src/ui/pages/settings/analytics_page.dart +++ b/lib/src/ui/pages/settings/analytics_page.dart @@ -1,5 +1,15 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/_global/providers/settings.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; @RoutePage() class AnalyticsPage extends StatelessWidget { @@ -7,6 +17,57 @@ class AnalyticsPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + const TextStyle style = TextStyle(color: Colors.blue, decoration: TextDecoration.underline); + + return Scaffold( + appBar: AppBar(title: Text(lang.analytics)), + body: ScrollViewColumn( + children: [ + SectionTitle(lang.analytics), + Selector( + selector: (_, p1) => (read: p1.disableAnalytics, set: p1.setAnalytics), + builder: (_, analytics, ___) { + return SwitchListTile( + title: Text(lang.stopAnalytics), + value: analytics.read, + onChanged: analytics.set, + ); + }, + ), + const CustomDivider(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: RichText( + text: TextSpan( + text: lang.analyticsDescription_1, + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), + children: [ + TextSpan( + text: lang.analyticsDescription_2, + style: style, + recognizer: TapGestureRecognizer()..onTap = () => openDataCollectionUrl(true), + ), + TextSpan(text: lang.analyticsDescription_3), + TextSpan( + text: lang.analyticsDescription_4, + style: style, + recognizer: TapGestureRecognizer()..onTap = () => openDataCollectionUrl(false), + ), + ], + ), + ), + ), + ], + ), + ); + } + + void openDataCollectionUrl(bool sourceCode) async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + String appVersion = packageInfo.version; + + String url = sourceCode ? Links.currentVersionCode(appVersion) : Links.privacyPolicy; + launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); } } From 94d1c4d60f5ff961b3d6eaf54626780bb21b5324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:20:54 +0200 Subject: [PATCH 25/57] add configured alert dialog, dialog and bottom sheet --- lib/src/lang/app_cs.arb | 1 + lib/src/lang/output/texts.dart | 6 +++ lib/src/lang/output/texts_cs.dart | 3 ++ .../ui/widgets/configured_alert_dialog.dart | 49 +++++++++++++++++++ .../ui/widgets/configured_bottom_sheet.dart | 14 ++++++ lib/src/ui/widgets/configured_dialog.dart | 13 +++++ 6 files changed, 86 insertions(+) create mode 100644 lib/src/ui/widgets/configured_alert_dialog.dart create mode 100644 lib/src/ui/widgets/configured_bottom_sheet.dart create mode 100644 lib/src/ui/widgets/configured_dialog.dart diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 4753e7d3..ca1bd9d7 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -9,6 +9,7 @@ "appName": "Autojídelna", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", "appearance": "Vzhled", + "cancel": "Zrušit", "convenience": "Pohodlí", "gettingDataNotifications": "Získávám data pro oznámení", "internetConnectionState": "{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 274993d1..e78bfb34 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -145,6 +145,12 @@ abstract class Texts { /// **'Vzhled'** String get appearance; + /// No description provided for @cancel. + /// + /// In cs, this message translates to: + /// **'Zrušit'** + String get cancel; + /// No description provided for @convenience. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index b52b65a2..e183938c 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -35,6 +35,9 @@ class TextsCs extends Texts { @override String get appearance => 'Vzhled'; + @override + String get cancel => 'Zrušit'; + @override String get convenience => 'Pohodlí'; diff --git a/lib/src/ui/widgets/configured_alert_dialog.dart b/lib/src/ui/widgets/configured_alert_dialog.dart new file mode 100644 index 00000000..cbceb202 --- /dev/null +++ b/lib/src/ui/widgets/configured_alert_dialog.dart @@ -0,0 +1,49 @@ +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; +import 'package:flutter/material.dart'; + +class ConfiguredAlertDialog extends StatelessWidget { + const ConfiguredAlertDialog({super.key, required this.title, required this.content, this.actions = const []}); + final String title; + final Widget content; + final List actions; + + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + return AlertDialog( + titlePadding: const EdgeInsets.only(top: 4), + contentPadding: EdgeInsets.zero, + iconPadding: EdgeInsets.zero, + buttonPadding: EdgeInsets.zero, + actionsPadding: const EdgeInsets.fromLTRB(0, 0, 8, 8), + title: SectionTitle(title), + content: SizedBox(width: MediaQuery.sizeOf(context).width * .75, child: content), + actions: [ + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const CustomDivider(height: 4), + const CustomDivider(height: 8, isTransparent: false), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ...actions, + TextButton( + onPressed: () => Navigator.pop(context), + style: TextButton.styleFrom( + foregroundColor: Theme.of(context).colorScheme.secondary, + visualDensity: const VisualDensity(vertical: -4), + padding: const EdgeInsets.only(right: 16), + ), + child: Text(lang.cancel), + ), + ], + ), + ], + ), + ], + ); + } +} diff --git a/lib/src/ui/widgets/configured_bottom_sheet.dart b/lib/src/ui/widgets/configured_bottom_sheet.dart new file mode 100644 index 00000000..1bbeca7e --- /dev/null +++ b/lib/src/ui/widgets/configured_bottom_sheet.dart @@ -0,0 +1,14 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +void configuredBottomSheet(BuildContext context, {required Widget Function(BuildContext) builder}) { + unawaited( + showModalBottomSheet( + context: context, + builder: builder, + useRootNavigator: true, + constraints: BoxConstraints(maxHeight: MediaQuery.sizeOf(context).height * .6), + ), + ); +} diff --git a/lib/src/ui/widgets/configured_dialog.dart b/lib/src/ui/widgets/configured_dialog.dart new file mode 100644 index 00000000..0e8440c9 --- /dev/null +++ b/lib/src/ui/widgets/configured_dialog.dart @@ -0,0 +1,13 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +void configuredDialog(BuildContext context, {required Widget Function(BuildContext) builder}) { + unawaited( + showDialog( + context: context, + builder: builder, + useRootNavigator: true, + ), + ); +} From 0a26a261324c85079a236eb4dbfb48206472d80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:24:09 +0200 Subject: [PATCH 26/57] migrate getCorrectDateString --- lib/src/logic/get_correct_date_string.dart | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 lib/src/logic/get_correct_date_string.dart diff --git a/lib/src/logic/get_correct_date_string.dart b/lib/src/logic/get_correct_date_string.dart new file mode 100644 index 00000000..71e7c025 --- /dev/null +++ b/lib/src/logic/get_correct_date_string.dart @@ -0,0 +1,35 @@ +import 'package:autojidelna/src/types/all.dart'; +import 'package:intl/intl.dart'; + +/// Returns correctly formated date string +/// +/// [format] | what format it should use +/// +/// [date] | date to be formated, if null returns DateTime.now() +/// +/// [inSettings] | If true, adds a "title" to the date -> ex. "d. M. y (1.1.2024)" +String getCorrectDateString(DateFormatOptions format, {DateTime? date, bool inSettings = false}) { + String formatStr; + switch (format) { + case DateFormatOptions.ddmmmyyyy: + formatStr = 'dd MMM yyyy'; + break; + case DateFormatOptions.ddmmyy: + formatStr = 'dd/MM/yy'; + break; + case DateFormatOptions.mmddyy: + formatStr = 'MM/dd/yy'; + break; + case DateFormatOptions.mmmddyyyy: + formatStr = 'MMM dd, yyyy'; + break; + case DateFormatOptions.yyyymmdd: + formatStr = 'yyy-MM-dd'; + break; + default: + formatStr = 'd. M. y'; + } + String dateStr = DateFormat(formatStr).format(date ?? DateTime.now()); + String settingsStr = '$formatStr ($dateStr)'; + return inSettings ? settingsStr : dateStr; +} From eb1bc1e6d24c152dff5d00ade24e0862a2f7b722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:25:40 +0200 Subject: [PATCH 27/57] migrate dateFormatPicker --- lib/src/lang/app_cs.arb | 1 + lib/src/lang/output/texts.dart | 6 +++ lib/src/lang/output/texts_cs.dart | 3 ++ lib/src/ui/widgets/date_format_picker.dart | 59 ++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 lib/src/ui/widgets/date_format_picker.dart diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index ca1bd9d7..d51fdf5a 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -11,6 +11,7 @@ "appearance": "Vzhled", "cancel": "Zrušit", "convenience": "Pohodlí", + "dateFormat": "Formát dat", "gettingDataNotifications": "Získávám data pro oznámení", "internetConnectionState": "{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}", "@internetConnectionState": { diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index e78bfb34..31eda65a 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -157,6 +157,12 @@ abstract class Texts { /// **'Pohodlí'** String get convenience; + /// No description provided for @dateFormat. + /// + /// In cs, this message translates to: + /// **'Formát dat'** + String get dateFormat; + /// No description provided for @gettingDataNotifications. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index e183938c..51605834 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -41,6 +41,9 @@ class TextsCs extends Texts { @override String get convenience => 'Pohodlí'; + @override + String get dateFormat => 'Formát dat'; + @override String get gettingDataNotifications => 'Získávám data pro oznámení'; diff --git a/lib/src/ui/widgets/date_format_picker.dart b/lib/src/ui/widgets/date_format_picker.dart new file mode 100644 index 00000000..dff290e4 --- /dev/null +++ b/lib/src/ui/widgets/date_format_picker.dart @@ -0,0 +1,59 @@ +import 'package:autojidelna/src/_global/providers/settings.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/logic/get_correct_date_string.dart'; +import 'package:autojidelna/src/types/all.dart'; +import 'package:autojidelna/src/ui/widgets/configured_alert_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/configured_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class DateFormatPickerListTile extends StatelessWidget { + const DateFormatPickerListTile({super.key}); + + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + return Selector( + selector: (_, p1) => (read: p1.dateFormat), + builder: (context, dateFormat, child) => ListTile( + title: Text(lang.dateFormat), + subtitle: Text(getCorrectDateString(dateFormat.read, inSettings: true)), + onTap: () => configuredDialog(context, builder: (context) => const DateFormatPicker()), + ), + ); + } +} + +class DateFormatPicker extends StatelessWidget { + const DateFormatPicker({super.key}); + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + return ConfiguredAlertDialog( + title: lang.dateFormat, + content: Selector( + selector: (_, p1) => (read: p1.dateFormat, set: p1.setDateFormat), + builder: (context, dateFormat, child) => SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: DateFormatOptions.values + .map( + (format) => ListTile( + minVerticalPadding: 0, + visualDensity: const VisualDensity(vertical: -4), + title: Text(getCorrectDateString(format, inSettings: true)), + titleTextStyle: Theme.of(context).textTheme.bodyMedium, + trailing: dateFormat.read == format ? const Icon(Icons.check) : null, + onTap: () { + dateFormat.set(format); + Navigator.pop(context); + }, + ), + ) + .toList(), + ), + ), + ), + ); + } +} From 2152f83a7d863f71c2bb54665387a4fbd10b5882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:27:04 +0200 Subject: [PATCH 28/57] migrate appearance page --- lib/src/lang/app_cs.arb | 6 ++- lib/src/lang/output/texts.dart | 24 ++++++++++++ lib/src/lang/output/texts_cs.dart | 12 ++++++ .../ui/pages/settings/appearance_page.dart | 38 ++++++++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index d51fdf5a..f7b7d9bc 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -1,6 +1,8 @@ { "@@locale": "cs", "about": "O aplikaci", + "amoledMode": "AMOLED mód", + "amoledModeSubtitle": "Přidej se k temné straně síly!", "analytics": "Shromažďování údajů", "analyticsDescription_1": "Informace shromažďujeme výhradně za účelem oprav chyb v aplikaci a udržování základních statistických údajů. Nemůžeme vyzkoušet autojídelnu u jídelen, kde nemáme přístup, jsme na těchto informacích závislí. Podrobnější informace naleznete ve ", "analyticsDescription_2": "Zdrojovém kódu", @@ -40,8 +42,10 @@ "settings": "Nastavení", "signOut": "Odhlásit se", "stopAnalytics": "Zastavit sledování analytických služeb", + "theme": "Schéma", "themeModeSystem": "Systém", "themeModeLight": "Světlý", "themeModeDark": "Tmavý", - "typeCrash": "Napište \"crash\" pro pád aplikace" + "typeCrash": "Napište \"crash\" pro pád aplikace", + "view": "Zobrazení" } \ No newline at end of file diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 31eda65a..4b9cd14d 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -97,6 +97,18 @@ abstract class Texts { /// **'O aplikaci'** String get about; + /// No description provided for @amoledMode. + /// + /// In cs, this message translates to: + /// **'AMOLED mód'** + String get amoledMode; + + /// No description provided for @amoledModeSubtitle. + /// + /// In cs, this message translates to: + /// **'Přidej se k temné straně síly!'** + String get amoledModeSubtitle; + /// No description provided for @analytics. /// /// In cs, this message translates to: @@ -277,6 +289,12 @@ abstract class Texts { /// **'Zastavit sledování analytických služeb'** String get stopAnalytics; + /// No description provided for @theme. + /// + /// In cs, this message translates to: + /// **'Schéma'** + String get theme; + /// No description provided for @themeModeSystem. /// /// In cs, this message translates to: @@ -300,6 +318,12 @@ abstract class Texts { /// In cs, this message translates to: /// **'Napište \"crash\" pro pád aplikace'** String get typeCrash; + + /// No description provided for @view. + /// + /// In cs, this message translates to: + /// **'Zobrazení'** + String get view; } class _TextsDelegate extends LocalizationsDelegate { diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 51605834..b04bba02 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -9,6 +9,12 @@ class TextsCs extends Texts { @override String get about => 'O aplikaci'; + @override + String get amoledMode => 'AMOLED mód'; + + @override + String get amoledModeSubtitle => 'Přidej se k temné straně síly!'; + @override String get analytics => 'Shromažďování údajů'; @@ -110,6 +116,9 @@ class TextsCs extends Texts { @override String get stopAnalytics => 'Zastavit sledování analytických služeb'; + @override + String get theme => 'Schéma'; + @override String get themeModeSystem => 'Systém'; @@ -121,4 +130,7 @@ class TextsCs extends Texts { @override String get typeCrash => 'Napište \"crash\" pro pád aplikace'; + + @override + String get view => 'Zobrazení'; } diff --git a/lib/src/ui/pages/settings/appearance_page.dart b/lib/src/ui/pages/settings/appearance_page.dart index 57b94819..a20bfd9e 100644 --- a/lib/src/ui/pages/settings/appearance_page.dart +++ b/lib/src/ui/pages/settings/appearance_page.dart @@ -1,5 +1,14 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_global/providers/theme.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/date_format_picker.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; +import 'package:autojidelna/src/ui/widgets/theme_mode_picker.dart'; +import 'package:autojidelna/src/ui/widgets/theme_style_picker.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; @RoutePage() class AppearancePage extends StatelessWidget { @@ -7,6 +16,33 @@ class AppearancePage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + final bool isLightMode = context.select((value) => value.themeMode) == ThemeMode.light; + final bool isBright = MediaQuery.platformBrightnessOf(context) == Brightness.light || isLightMode; + + return Scaffold( + appBar: AppBar(title: Text(lang.appearance)), + body: ScrollViewColumn( + children: [ + SectionTitle(lang.theme), + const CustomDivider(height: 24), + const ThemeModePicker(), + const CustomDivider(height: 38), + const ThemeStylePicker(), + const CustomDivider(height: 30), + Selector( + selector: (_, p1) => (read: p1.amoledMode, set: p1.setAmoledMode), + builder: (context, amoledMode, child) => SwitchListTile( + title: Text(lang.amoledMode), + subtitle: Text(lang.amoledModeSubtitle), + value: amoledMode.read, + onChanged: isBright ? null : amoledMode.set, + ), + ), + SectionTitle(lang.view), + const DateFormatPickerListTile(), + ], + ), + ); } } From b0912394cf39ccd9331c3cfcac5375cfa6844a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:47:47 +0200 Subject: [PATCH 29/57] chore: static indent size in custom divider --- lib/src/ui/widgets/custom_divider.dart | 2 +- lib/src/ui/widgets/section_title.dart | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/src/ui/widgets/custom_divider.dart b/lib/src/ui/widgets/custom_divider.dart index 5885b192..0526c085 100644 --- a/lib/src/ui/widgets/custom_divider.dart +++ b/lib/src/ui/widgets/custom_divider.dart @@ -15,7 +15,7 @@ class CustomDivider extends StatelessWidget { @override Widget build(BuildContext context) { - double indent = MediaQuery.sizeOf(context).width * 0.025; + double indent = 10; return Divider( color: isTransparent ? Colors.transparent : null, height: height, diff --git a/lib/src/ui/widgets/section_title.dart b/lib/src/ui/widgets/section_title.dart index 59e67d4a..7948c3f9 100644 --- a/lib/src/ui/widgets/section_title.dart +++ b/lib/src/ui/widgets/section_title.dart @@ -13,10 +13,7 @@ class SectionTitle extends StatelessWidget { const CustomDivider(height: 8), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - title, - style: Theme.of(context).textTheme.titleMedium!.copyWith(color: Theme.of(context).colorScheme.primary), - ), + child: Text(title, style: Theme.of(context).textTheme.titleMedium!.copyWith(color: Theme.of(context).colorScheme.primary)), ), const CustomDivider(height: 8, isTransparent: false), const CustomDivider(height: 4), From cb0aadb21b4298e505bbbcc329e9907cc6804b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 10:48:09 +0200 Subject: [PATCH 30/57] migrate convenience page --- lib/src/lang/app_cs.arb | 6 ++- lib/src/lang/output/texts.dart | 36 ++++++++++++--- lib/src/lang/output/texts_cs.dart | 18 ++++++-- .../ui/pages/settings/convenience_page.dart | 44 ++++++++++++++++++- 4 files changed, 93 insertions(+), 11 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index f7b7d9bc..7f7d78ec 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -11,9 +11,12 @@ "appName": "Autojídelna", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", "appearance": "Vzhled", + "calendarBigMarkers": "Velké ukazatele v kalendáři", "cancel": "Zrušit", "convenience": "Pohodlí", "dateFormat": "Formát dat", + "debug": "Debug", + "experimental": "Experimentální", "gettingDataNotifications": "Získávám data pro oznámení", "internetConnectionState": "{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}", "@internetConnectionState": { @@ -25,10 +28,10 @@ } } }, - "debug": "Debug", "language": "Jazyk", "languageCzech": "Čeština", "languageEnglish": "Angličtina", + "listUi": "List UI", "login": "Přihlásit se", "menu": "Jídelníček", "more": "Více", @@ -41,6 +44,7 @@ "requestNotificationPermission": "Požádat o povolení notifikací", "settings": "Nastavení", "signOut": "Odhlásit se", + "skipWeekends": "Přeskakovat víkendy", "stopAnalytics": "Zastavit sledování analytických služeb", "theme": "Schéma", "themeModeSystem": "Systém", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 4b9cd14d..dccabc5e 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -157,6 +157,12 @@ abstract class Texts { /// **'Vzhled'** String get appearance; + /// No description provided for @calendarBigMarkers. + /// + /// In cs, this message translates to: + /// **'Velké ukazatele v kalendáři'** + String get calendarBigMarkers; + /// No description provided for @cancel. /// /// In cs, this message translates to: @@ -175,6 +181,18 @@ abstract class Texts { /// **'Formát dat'** String get dateFormat; + /// No description provided for @debug. + /// + /// In cs, this message translates to: + /// **'Debug'** + String get debug; + + /// No description provided for @experimental. + /// + /// In cs, this message translates to: + /// **'Experimentální'** + String get experimental; + /// No description provided for @gettingDataNotifications. /// /// In cs, this message translates to: @@ -187,12 +205,6 @@ abstract class Texts { /// **'{arg, select, other{Odpojeno od internetu} true{Připojeno k internetu}}'** String internetConnectionState(String arg); - /// No description provided for @debug. - /// - /// In cs, this message translates to: - /// **'Debug'** - String get debug; - /// No description provided for @language. /// /// In cs, this message translates to: @@ -211,6 +223,12 @@ abstract class Texts { /// **'Angličtina'** String get languageEnglish; + /// No description provided for @listUi. + /// + /// In cs, this message translates to: + /// **'List UI'** + String get listUi; + /// No description provided for @login. /// /// In cs, this message translates to: @@ -283,6 +301,12 @@ abstract class Texts { /// **'Odhlásit se'** String get signOut; + /// No description provided for @skipWeekends. + /// + /// In cs, this message translates to: + /// **'Přeskakovat víkendy'** + String get skipWeekends; + /// No description provided for @stopAnalytics. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index b04bba02..65343378 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -41,6 +41,9 @@ class TextsCs extends Texts { @override String get appearance => 'Vzhled'; + @override + String get calendarBigMarkers => 'Velké ukazatele v kalendáři'; + @override String get cancel => 'Zrušit'; @@ -50,6 +53,12 @@ class TextsCs extends Texts { @override String get dateFormat => 'Formát dat'; + @override + String get debug => 'Debug'; + + @override + String get experimental => 'Experimentální'; + @override String get gettingDataNotifications => 'Získávám data pro oznámení'; @@ -65,9 +74,6 @@ class TextsCs extends Texts { return '$_temp0'; } - @override - String get debug => 'Debug'; - @override String get language => 'Jazyk'; @@ -77,6 +83,9 @@ class TextsCs extends Texts { @override String get languageEnglish => 'Angličtina'; + @override + String get listUi => 'List UI'; + @override String get login => 'Přihlásit se'; @@ -113,6 +122,9 @@ class TextsCs extends Texts { @override String get signOut => 'Odhlásit se'; + @override + String get skipWeekends => 'Přeskakovat víkendy'; + @override String get stopAnalytics => 'Zastavit sledování analytických služeb'; diff --git a/lib/src/ui/pages/settings/convenience_page.dart b/lib/src/ui/pages/settings/convenience_page.dart index f94398a3..58b7da36 100644 --- a/lib/src/ui/pages/settings/convenience_page.dart +++ b/lib/src/ui/pages/settings/convenience_page.dart @@ -1,5 +1,10 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_global/providers/settings.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; @RoutePage() class ConveniencePage extends StatelessWidget { @@ -7,6 +12,43 @@ class ConveniencePage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + + return Scaffold( + appBar: AppBar(title: Text(lang.convenience)), + body: ScrollViewColumn( + children: [ + SectionTitle(lang.convenience), + // skip weekends + Selector( + selector: (_, p1) => (read: p1.getSkipWeekends, set: p1.setSkipWeekends), + builder: (context, skipWeekends, child) => SwitchListTile( + title: Text(lang.skipWeekends), + value: skipWeekends.read, + onChanged: skipWeekends.set, + ), + ), + // big calendar markers + Selector( + selector: (_, p1) => (read: p1.bigCalendarMarkers, set: p1.setCalendarMarkers), + builder: (context, bigCalendarMarkers, child) => SwitchListTile( + title: Text(lang.calendarBigMarkers), + value: bigCalendarMarkers.read, + onChanged: bigCalendarMarkers.set, + ), + ), + SectionTitle(lang.experimental), + // list UI + Selector( + selector: (_, p1) => (read: p1.isListUi, set: p1.setListUi), + builder: (context, listUi, child) => SwitchListTile( + title: Text(lang.listUi), + value: listUi.read, + onChanged: listUi.set, + ), + ), + ], + ), + ); } } From de8fe13bf9902cf7f23874e583b83430ed27ac46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 11:58:02 +0200 Subject: [PATCH 31/57] remove default appbar from routerPage --- lib/src/lang/app_cs.arb | 1 + lib/src/lang/output/texts.dart | 6 ++++++ lib/src/lang/output/texts_cs.dart | 3 +++ lib/src/ui/pages/router_page.dart | 5 +---- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 7f7d78ec..ddef0f79 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -34,6 +34,7 @@ "listUi": "List UI", "login": "Přihlásit se", "menu": "Jídelníček", + "navigationRailExpantionButtonTitle": "Menu", "more": "Více", "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index dccabc5e..357d9599 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -241,6 +241,12 @@ abstract class Texts { /// **'Jídelníček'** String get menu; + /// No description provided for @navigationRailExpantionButtonTitle. + /// + /// In cs, this message translates to: + /// **'Menu'** + String get navigationRailExpantionButtonTitle; + /// No description provided for @more. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 65343378..636262ad 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -92,6 +92,9 @@ class TextsCs extends Texts { @override String get menu => 'Jídelníček'; + @override + String get navigationRailExpantionButtonTitle => 'Menu'; + @override String get more => 'Více'; diff --git a/lib/src/ui/pages/router_page.dart b/lib/src/ui/pages/router_page.dart index d103e1c1..6e126049 100644 --- a/lib/src/ui/pages/router_page.dart +++ b/lib/src/ui/pages/router_page.dart @@ -1,7 +1,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; -import 'package:autojidelna/src/ui/widgets/appbars/default_appbar.dart'; import 'package:autojidelna/src/ui/widgets/appbars/menu_page.dart'; import 'package:autojidelna/src/ui/widgets/appbars/more_page.dart'; import 'package:flutter/material.dart'; @@ -51,8 +50,6 @@ class _RouterPageState extends State { ) : null; - final defaultAppBar = DefaultAppbar(leading: leading, leadingWidth: leadingWidth); - // use null to not show an appbar for a specific page. Use the defaultAppBar for a default appbar // note: using null will not show the appbar at all. This includes the navigation drawer button. Use with caution. final List appBars = [ @@ -98,7 +95,7 @@ class _RouterPageState extends State { contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(128)), leading: const Icon(Icons.menu), - title: const Text('Menu'), // TODO: add to localizations + title: Text(lang.navigationRailExpantionButtonTitle), // TODO: add to localizations onTap: () => changeExtention(context), ), ), From 9ca943fcf0ca69909b60fbee112cdb2d84fc9e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 3 Oct 2024 12:47:34 +0200 Subject: [PATCH 32/57] chore: update notifications.dart --- lib/src/_conf/notifications.dart | 69 +++++++++---------- lib/src/ui/pages/settings/analytics_page.dart | 12 ++-- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/lib/src/_conf/notifications.dart b/lib/src/_conf/notifications.dart index 881cc2ef..e099a1e7 100644 --- a/lib/src/_conf/notifications.dart +++ b/lib/src/_conf/notifications.dart @@ -1,67 +1,64 @@ // Purpose: stores constants used throughout the app. +import 'package:autojidelna/src/_global/app.dart'; + class NotificationIds { static String kreditChannel(String userName, String url) => 'kredit_channel_${userName}_$url'; static String objednanoChannel(String userName, String url) => 'objednano_channel_${userName}_$url'; static String dnesniJidloChannel(String userName, String url) => 'jidlo_channel_${userName}_$url'; static String channelGroup(String userName, String url) => 'channel_group_${userName}_$url'; - static const String channelGroupElse = 'channel_group_else'; - static const String channelElse = 'else_channel'; - static const String payloadUser = 'user'; - static const String payloadIndex = 'index'; - static const String payloadIndexDne = 'indexDne'; + static String get channelGroupElse => 'channel_group_else'; + static String get channelElse => 'else_channel'; + static String get payloadUser => 'user'; + static String get payloadIndex => 'index'; + static String get payloadIndexDne => 'indexDne'; static String objednatButton(String userName, String url) => 'objednat_${userName}_$url'; - static const String onlyObjednatButton = 'objednat_'; -} - -class Nums { - static int get switchAccountPanelDuration => 300; + static String get onlyObjednatButton => 'objednat_'; } class AnalyticsEventIds { - static const String updateButtonClicked = 'updateButtonClicked'; - static const String oldVer = 'oldVersion'; - static const String newVer = 'newVersion'; - static const String updateDownloaded = 'updateDownloaded'; + static String get updateButtonClicked => 'updateButtonClicked'; + static String get oldVer => 'oldVersion'; + static String get newVer => 'newVersion'; + static String get updateDownloaded => 'updateDownloaded'; } // Strings shown to the user class NotificationsTexts { /// initAwesome and notifications in general have a problem with the localization package so we just force czech static String notificationsFor(String user) => 'Notifikace pro $user'; - static const String jidloChannelName = 'Dnešní jídlo'; + static String get jidloChannelName => 'Dnešní jídlo'; static String jidloChannelDescription(String user) => 'Notifikace každý den o tom jaké je dnes jídlo pro $user'; - static const String dochazejiciKreditChannelName = 'Docházející kredit'; + static String get dochazejiciKreditChannelName => 'Docházející kredit'; static String dochazejiciKreditChannelDescription(String user) => 'Notifikace o tom, zda vám dochází kredit týden dopředu pro $user'; - static const String objednanoChannelName = 'Objednáno?'; + static String get objednanoChannelName => 'Objednáno?'; static String objednanoChannelDescription(String user) => 'Notifikace každý den o tom jaké je dnes jídlo pro $user'; - static const String notificationOther = 'Ostatní'; - static const String notificationOtherDescription = 'Ostatní notifikace, např. chybové hlášky...'; - static const String stringtingDataNotifications = 'Získávám data pro notifikace'; - static const String notificationDochaziVamKredit = 'Dochází vám kredit!'; + static String get notificationOther => 'Ostatní'; + static String get notificationOtherDescription => 'Ostatní notifikace, např. chybové hlášky...'; + static String get gettingDataNotifications => 'Získávám data pro notifikace'; + static String get notificationDochaziVamKredit => 'Dochází vám kredit!'; static String notificationKreditPro(String jmeno, String prijmeni, int kredit) => 'Kredit pro $jmeno $prijmeni: $kredit Kč'; - static const String notificationZtlumit = 'Ztlumit na týden'; - static const String notificationObjednejteSi = 'Objednejte si na příští týden'; + static String get notificationZtlumit => 'Ztlumit na týden'; + static String get notificationObjednejteSi => 'Objednejte si na příští týden'; static String notificationObjednejteSiDetail(String jmeno, String prijmeni) => 'Uživatel $jmeno $prijmeni si stále ještě neobjenal na příští týden'; - static const String objednatAction = 'Objednat náhodně'; - static const String notificationNoFood = 'Žádná jídla pro tento den'; - static const String nastalaChyba = 'Nastala chyba'; + static String get objednatAction => 'Objednat náhodně'; + static String get notificationNoFood => 'Žádná jídla pro tento den'; + static String get nastalaChyba => 'Nastala chyba'; } class Links { - static const String autojidelna = 'https://autojidelna.cz'; - static const String repo = 'https://github.com/App-Elevate/AUT.aplikace'; - static const String latestVersionApi = 'https://api.github.com/repos/App-Elevate/AUT.aplikace/releases/latest'; - static const String appStore = '$autojidelna/release/appStore.json'; - static String currentVersionCode(String appVersion) => '$repo/blob/v$appVersion'; + static String get autojidelna => 'https://autojidelna.cz'; + static String get repo => 'https://github.com/App-Elevate/AUT.aplikace'; + static String get appStore => '$autojidelna/release/appStore.json'; + static String get currentVersionCode => '$repo/blob/v${App.packageInfo.version}'; - static const String privacyPolicy = '$autojidelna/cs/privacy-policy/'; - static String currentChangelog(String version) => '$autojidelna/cs/changelogs/#$version'; + static String get privacyPolicy => '$autojidelna/cs/privacy-policy/'; + static String get currentChangelog => '$autojidelna/cs/changelogs/#${App.packageInfo.version}'; - static const String latestRelease = '$repo/releases/latest'; - static const String email = 'info@appelevate.cz'; + static String get latestRelease => '$repo/releases/latest'; + static String get email => 'info@appelevate.cz'; } class Assets { - static const String logo = 'assets/images/logo.svg'; + static String get logo => 'assets/logo.svg'; } diff --git a/lib/src/ui/pages/settings/analytics_page.dart b/lib/src/ui/pages/settings/analytics_page.dart index e7270a38..aa3af850 100644 --- a/lib/src/ui/pages/settings/analytics_page.dart +++ b/lib/src/ui/pages/settings/analytics_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_global/providers/settings.provider.dart'; @@ -7,7 +9,6 @@ import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; import 'package:autojidelna/src/ui/widgets/section_title.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -63,11 +64,8 @@ class AnalyticsPage extends StatelessWidget { ); } - void openDataCollectionUrl(bool sourceCode) async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - String appVersion = packageInfo.version; - - String url = sourceCode ? Links.currentVersionCode(appVersion) : Links.privacyPolicy; - launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); + void openDataCollectionUrl(bool sourceCode) { + String url = sourceCode ? Links.currentVersionCode : Links.privacyPolicy; + unawaited(launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication)); } } From 13a47d28c2b313f9373a7105bcfb0d957b98225a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 4 Oct 2024 10:31:08 +0200 Subject: [PATCH 33/57] migrate about page --- assets/logo.svg | 70 ++++++++++++++++++++++ assets_dev/logo.svg | 70 ++++++++++++++++++++++ lib/src/lang/app_cs.arb | 26 +++++++++ lib/src/lang/output/texts.dart | 30 ++++++++++ lib/src/lang/output/texts_cs.dart | 29 +++++++++ lib/src/ui/pages/more/about_page.dart | 84 ++++++++++++++++++++++++++- pubspec.lock | 48 +++++++++++++++ pubspec.yaml | 3 + 8 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 assets/logo.svg create mode 100644 assets_dev/logo.svg diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 00000000..f471876d --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,70 @@ + + + + + Logo - Autojídelna + + + + + + + + + Autojídelna - Logo + + + Matěj Verhaegen + + + Logo for the app Autojídelna + 15/10/2023 + + + + diff --git a/assets_dev/logo.svg b/assets_dev/logo.svg new file mode 100644 index 00000000..f471876d --- /dev/null +++ b/assets_dev/logo.svg @@ -0,0 +1,70 @@ + + + + + Logo - Autojídelna + + + + + + + + + Autojídelna - Logo + + + Matěj Verhaegen + + + Logo for the app Autojídelna + 15/10/2023 + + + + diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index ddef0f79..88288d01 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -11,6 +11,16 @@ "appName": "Autojídelna", "appDescription": "Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů.", "appearance": "Vzhled", + "appLegalese": "© 2023 - {year} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3", + "@appLegalese": { + "description": "appLegalese", + "placeholders": { + "year": { + "type": "DateTime", + "format": "y" + } + } + }, "calendarBigMarkers": "Velké ukazatele v kalendáři", "cancel": "Zrušit", "convenience": "Pohodlí", @@ -31,6 +41,7 @@ "language": "Jazyk", "languageCzech": "Čeština", "languageEnglish": "Angličtina", + "licenses": "Licence", "listUi": "List UI", "login": "Přihlásit se", "menu": "Jídelníček", @@ -42,6 +53,7 @@ "orders": "Objednávky", "password": "Heslo", "patch": "patch", + "privacyPolicy": "Zásady ochrany osobních údajů", "requestNotificationPermission": "Požádat o povolení notifikací", "settings": "Nastavení", "signOut": "Odhlásit se", @@ -52,5 +64,19 @@ "themeModeLight": "Světlý", "themeModeDark": "Tmavý", "typeCrash": "Napište \"crash\" pro pád aplikace", + "version": "Verze", + "versionSubtitle": "{arg, select, true{Debug} other{Stable}} {version}", + "@versionSubtitle": { + "description": "versionSubtitle", + "placeholders": { + "arg": { + "type": "String", + "example": "true" + }, + "version": { + "type": "String" + } + } + }, "view": "Zobrazení" } \ No newline at end of file diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 357d9599..d4cd6935 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -157,6 +157,12 @@ abstract class Texts { /// **'Vzhled'** String get appearance; + /// appLegalese + /// + /// In cs, this message translates to: + /// **'© 2023 - {year} Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'** + String appLegalese(DateTime year); + /// No description provided for @calendarBigMarkers. /// /// In cs, this message translates to: @@ -223,6 +229,12 @@ abstract class Texts { /// **'Angličtina'** String get languageEnglish; + /// No description provided for @licenses. + /// + /// In cs, this message translates to: + /// **'Licence'** + String get licenses; + /// No description provided for @listUi. /// /// In cs, this message translates to: @@ -289,6 +301,12 @@ abstract class Texts { /// **'patch'** String get patch; + /// No description provided for @privacyPolicy. + /// + /// In cs, this message translates to: + /// **'Zásady ochrany osobních údajů'** + String get privacyPolicy; + /// No description provided for @requestNotificationPermission. /// /// In cs, this message translates to: @@ -349,6 +367,18 @@ abstract class Texts { /// **'Napište \"crash\" pro pád aplikace'** String get typeCrash; + /// No description provided for @version. + /// + /// In cs, this message translates to: + /// **'Verze'** + String get version; + + /// versionSubtitle + /// + /// In cs, this message translates to: + /// **'{arg, select, true{Debug} other{Stable}} {version}'** + String versionSubtitle(String arg, String version); + /// No description provided for @view. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 636262ad..4390e547 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -41,6 +41,14 @@ class TextsCs extends Texts { @override String get appearance => 'Vzhled'; + @override + String appLegalese(DateTime year) { + final intl.DateFormat yearDateFormat = intl.DateFormat.y(localeName); + final String yearString = yearDateFormat.format(year); + + return '© 2023 - $yearString Tomáš Protiva, Matěj Verhaegen a kolaborátoři\nZveřejněno pod licencí GNU GPLv3'; + } + @override String get calendarBigMarkers => 'Velké ukazatele v kalendáři'; @@ -83,6 +91,9 @@ class TextsCs extends Texts { @override String get languageEnglish => 'Angličtina'; + @override + String get licenses => 'Licence'; + @override String get listUi => 'List UI'; @@ -116,6 +127,9 @@ class TextsCs extends Texts { @override String get patch => 'patch'; + @override + String get privacyPolicy => 'Zásady ochrany osobních údajů'; + @override String get requestNotificationPermission => 'Požádat o povolení notifikací'; @@ -146,6 +160,21 @@ class TextsCs extends Texts { @override String get typeCrash => 'Napište \"crash\" pro pád aplikace'; + @override + String get version => 'Verze'; + + @override + String versionSubtitle(String arg, String version) { + String _temp0 = intl.Intl.selectLogic( + arg, + { + 'true': 'Debug', + 'other': 'Stable', + }, + ); + return '$_temp0 $version'; + } + @override String get view => 'Zobrazení'; } diff --git a/lib/src/ui/pages/more/about_page.dart b/lib/src/ui/pages/more/about_page.dart index 7de0e9f6..3985d97b 100644 --- a/lib/src/ui/pages/more/about_page.dart +++ b/lib/src/ui/pages/more/about_page.dart @@ -1,5 +1,16 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/_global/app.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:icons_flutter/icons_flutter.dart'; +import 'package:url_launcher/url_launcher.dart'; @RoutePage() class AboutPage extends StatelessWidget { @@ -7,6 +18,77 @@ class AboutPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + + String appVersion = lang.versionSubtitle(kDebugMode.toString(), App.packageInfo.version); + + Widget logo = SvgPicture.asset( + Assets.logo, + colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.onSurface, BlendMode.srcIn), + height: MediaQuery.sizeOf(context).height * .10, + ); + + return Scaffold( + appBar: AppBar(title: Text(lang.about)), + body: ScrollViewColumn( + children: [ + // logo + Padding( + padding: const EdgeInsets.symmetric(vertical: 85.0), + child: SvgPicture.asset( + Assets.logo, + colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.onSurface, BlendMode.srcIn), + height: MediaQuery.sizeOf(context).height * .10, + ), + ), + const CustomDivider(isTransparent: false), + // version list tile + ListTile( + title: Text(lang.version), + subtitle: Text(appVersion), + ), + // licenses list tile + ListTile( + title: Text(lang.licenses), + onTap: () => unawaited( + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => LicensePage( + applicationName: lang.appName, + applicationVersion: appVersion, + applicationIcon: logo, + applicationLegalese: lang.appLegalese(DateTime.now()), + ), + ), + ), + ), + ), + // privacy policy + ListTile( + title: Text(lang.privacyPolicy), + onTap: () => unawaited(launchUrl(Uri.parse(Links.privacyPolicy))), + ), + const CustomDivider(isTransparent: false), + // links + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + IconButton( + onPressed: () => unawaited(launchUrl(Uri.parse(Links.autojidelna))), + icon: const Icon(Icons.public_outlined), + ), + IconButton( + onPressed: () => unawaited(launchUrl(Uri.parse(Links.repo))), + icon: const Icon(Octicons.mark_github), + ), + IconButton( + onPressed: () => unawaited(launchUrl(Uri(scheme: 'mailto', path: Links.email))), + icon: const Icon(Icons.email_outlined), + ), + ], + ), + ], + ), + ); } } diff --git a/pubspec.lock b/pubspec.lock index e5d77e2e..20b869ee 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -523,6 +523,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -645,6 +653,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + icons_flutter: + dependency: "direct main" + description: + name: icons_flutter + sha256: def6e6a79709a5ed62e564005ab34bf39b4cc6377604c4422af6397941da4607 + url: "https://pub.dev" + source: hosted + version: "0.0.4" ini: dependency: transitive description: @@ -853,6 +869,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -1330,6 +1354,30 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e25f89da..83f39952 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,6 +62,9 @@ dependencies: canteenlib: ^4.1.0 internet_connection_checker: ^1.0.0+1 + icons_flutter: ^0.0.4 + flutter_svg: ^2.0.10+1 + dev_dependencies: flutter_test: sdk: flutter From 9aee2c05dfd99342a236a928c753ef52955a6010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 4 Oct 2024 10:34:48 +0200 Subject: [PATCH 34/57] fix about page logo --- lib/src/ui/pages/more/about_page.dart | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/src/ui/pages/more/about_page.dart b/lib/src/ui/pages/more/about_page.dart index 3985d97b..fc788c6d 100644 --- a/lib/src/ui/pages/more/about_page.dart +++ b/lib/src/ui/pages/more/about_page.dart @@ -33,14 +33,7 @@ class AboutPage extends StatelessWidget { body: ScrollViewColumn( children: [ // logo - Padding( - padding: const EdgeInsets.symmetric(vertical: 85.0), - child: SvgPicture.asset( - Assets.logo, - colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.onSurface, BlendMode.srcIn), - height: MediaQuery.sizeOf(context).height * .10, - ), - ), + Padding(padding: const EdgeInsets.symmetric(vertical: 85.0), child: logo), const CustomDivider(isTransparent: false), // version list tile ListTile( From e7496b0f99dba1d597fa8b7f855f5741e418ee21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 4 Oct 2024 10:51:43 +0200 Subject: [PATCH 35/57] migrate part of more page --- lib/src/lang/app_cs.arb | 2 ++ lib/src/lang/output/texts.dart | 12 +++++++++ lib/src/lang/output/texts_cs.dart | 6 +++++ lib/src/ui/pages/more_page.dart | 45 ++++++++++++++++++++++++++++++- lib/src/ui/pages/router_page.dart | 4 +-- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 88288d01..647a3d2e 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -1,6 +1,7 @@ { "@@locale": "cs", "about": "O aplikaci", + "account": "Účet", "amoledMode": "AMOLED mód", "amoledModeSubtitle": "Přidej se k temné straně síly!", "analytics": "Shromažďování údajů", @@ -56,6 +57,7 @@ "privacyPolicy": "Zásady ochrany osobních údajů", "requestNotificationPermission": "Požádat o povolení notifikací", "settings": "Nastavení", + "shareApp": "Sdílet aplikaci", "signOut": "Odhlásit se", "skipWeekends": "Přeskakovat víkendy", "stopAnalytics": "Zastavit sledování analytických služeb", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index d4cd6935..9f083504 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -97,6 +97,12 @@ abstract class Texts { /// **'O aplikaci'** String get about; + /// No description provided for @account. + /// + /// In cs, this message translates to: + /// **'Účet'** + String get account; + /// No description provided for @amoledMode. /// /// In cs, this message translates to: @@ -319,6 +325,12 @@ abstract class Texts { /// **'Nastavení'** String get settings; + /// No description provided for @shareApp. + /// + /// In cs, this message translates to: + /// **'Sdílet aplikaci'** + String get shareApp; + /// No description provided for @signOut. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 4390e547..22ebdad1 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -9,6 +9,9 @@ class TextsCs extends Texts { @override String get about => 'O aplikaci'; + @override + String get account => 'Účet'; + @override String get amoledMode => 'AMOLED mód'; @@ -136,6 +139,9 @@ class TextsCs extends Texts { @override String get settings => 'Nastavení'; + @override + String get shareApp => 'Sdílet aplikaci'; + @override String get signOut => 'Odhlásit se'; diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart index 5282c467..bfe5abce 100644 --- a/lib/src/ui/pages/more_page.dart +++ b/lib/src/ui/pages/more_page.dart @@ -1,5 +1,13 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/_routing/app_router.gr.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; import 'package:flutter/material.dart'; +import 'package:share_plus/share_plus.dart'; @RoutePage() class MorePage extends StatelessWidget { @@ -7,6 +15,41 @@ class MorePage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + final StackRouter router = context.router; + + return ScrollViewColumn( + children: [ + const CustomDivider(height: 38), + const CustomDivider(isTransparent: false), + ListTile( + leading: const Icon(Icons.person_outline), + title: Text(lang.account), + onTap: () => unawaited(router.push(const AccountPage())), + ), + /* TODO: make the page + ListTile( + leading: const Icon(Icons.analytics_outlined), + title: Text(lang.statistics), + onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => const StatisticsScreen())), + ),*/ + const CustomDivider(isTransparent: false), + ListTile( + leading: const Icon(Icons.settings_outlined), + title: Text(lang.settings), + onTap: () => unawaited(router.push(const SettingsPage())), + ), + ListTile( + leading: const Icon(Icons.info_outline), + title: Text(lang.about), + onTap: () => unawaited(router.push(const AboutPage())), + ), + ListTile( + leading: const Icon(Icons.share_outlined), + title: Text(lang.shareApp), + onTap: () => unawaited(Share.share(Links.autojidelna, subject: lang.appName)), + ), + ], + ); } } diff --git a/lib/src/ui/pages/router_page.dart b/lib/src/ui/pages/router_page.dart index 6e126049..195f9d1b 100644 --- a/lib/src/ui/pages/router_page.dart +++ b/lib/src/ui/pages/router_page.dart @@ -53,8 +53,8 @@ class _RouterPageState extends State { // use null to not show an appbar for a specific page. Use the defaultAppBar for a default appbar // note: using null will not show the appbar at all. This includes the navigation drawer button. Use with caution. final List appBars = [ - (context) => const MenuAppBar(), - (context) => const MoreAppBar(), + (_) => const MenuAppBar(), + (_) => const MoreAppBar(), ]; final List routes = [ From 1b7733b2c3033bba71bda7ce34145f4d89217bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 4 Oct 2024 10:53:58 +0200 Subject: [PATCH 36/57] more page stuff --- lib/src/ui/pages/more_page.dart | 8 +++---- pubspec.lock | 40 ++++++++++++++++++++++++++------- pubspec.yaml | 1 + 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart index bfe5abce..2c4d0554 100644 --- a/lib/src/ui/pages/more_page.dart +++ b/lib/src/ui/pages/more_page.dart @@ -25,7 +25,7 @@ class MorePage extends StatelessWidget { ListTile( leading: const Icon(Icons.person_outline), title: Text(lang.account), - onTap: () => unawaited(router.push(const AccountPage())), + onTap: () async => router.push(const AccountPage()), ), /* TODO: make the page ListTile( @@ -37,17 +37,17 @@ class MorePage extends StatelessWidget { ListTile( leading: const Icon(Icons.settings_outlined), title: Text(lang.settings), - onTap: () => unawaited(router.push(const SettingsPage())), + onTap: () async => router.push(const SettingsPage()), ), ListTile( leading: const Icon(Icons.info_outline), title: Text(lang.about), - onTap: () => unawaited(router.push(const AboutPage())), + onTap: () async => router.push(const AboutPage()), ), ListTile( leading: const Icon(Icons.share_outlined), title: Text(lang.shareApp), - onTap: () => unawaited(Share.share(Links.autojidelna, subject: lang.appName)), + onTap: () async => Share.share(Links.autojidelna, subject: lang.appName), ), ], ); diff --git a/pubspec.lock b/pubspec.lock index 20b869ee..7b1555af 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: "direct main" description: name: auto_route - sha256: bb673104dbdc22667d01ec668df3d2a358b6e3da481428eeb1151933cfc1a7d6 + sha256: b83e8ce46da7228cdd019b5a11205454847f0a971bca59a7529b98df9876889b url: "https://pub.dev" source: hosted - version: "9.2.0" + version: "9.2.2" auto_route_generator: dependency: "direct dev" description: @@ -249,6 +249,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -389,18 +397,18 @@ packages: dependency: transitive description: name: firebase_core_platform_interface - sha256: "3c3a1e92d6f4916c32deea79c4a7587aa0e9dbbe5889c7a16afcf005a485ee02" + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.3.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: e8d1e22de72cb21cdcfc5eed7acddab3e99cd83f3b317f54f7a96c32f25fd11e + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 url: "https://pub.dev" source: hosted - version: "2.17.4" + version: "2.18.1" firebase_crashlytics: dependency: "direct main" description: @@ -1061,6 +1069,22 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.0" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "468c43f285207c84bcabf5737f33b914ceb8eb38398b91e5e3ad1698d1b72a52" + url: "https://pub.dev" + source: hosted + version: "10.0.2" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "6ababf341050edff57da8b6990f11f4e99eaba837865e2e6defe16d039619db5" + url: "https://pub.dev" + source: hosted + version: "5.0.0" shared_preferences: dependency: transitive description: @@ -1406,10 +1430,10 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.1.0" web_socket: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 83f39952..878882a7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: flutter_adaptive_scaffold: ^0.2.1 package_info_plus: ^8.0.0 # Package info used in about page + share_plus: ^10.0.2 url_launcher: ^6.3.0 From 1370d311e505c9649d2d8f56723970684c9d5ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Fri, 4 Oct 2024 10:59:55 +0200 Subject: [PATCH 37/57] delete unused import --- lib/src/ui/pages/more_page.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart index 2c4d0554..522e8f76 100644 --- a/lib/src/ui/pages/more_page.dart +++ b/lib/src/ui/pages/more_page.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; From eb04de5680fa9fe80b2157364d492cbfa18aaada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:02:18 +0200 Subject: [PATCH 38/57] chore: rename account classes - LoggedInUser -> Account - LoginDataAutojidelna -> LoggedAccounts - LoggedAccountsInAccountPanel -> LoggedAccountsLimited --- lib/src/_global/app.dart | 4 ++-- lib/src/logic/canteenwrapper.dart | 35 +++++++++++++--------------- lib/src/logic/notifications.dart | 10 ++++---- lib/src/types/all.dart | 38 +++++++++++++++---------------- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/lib/src/_global/app.dart b/lib/src/_global/app.dart index 345c88df..b2a0aa40 100644 --- a/lib/src/_global/app.dart +++ b/lib/src/_global/app.dart @@ -72,9 +72,9 @@ class App { Hive.box(Boxes.appState).put(HiveKeys.lastVersion, version); try { - LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); - for (LoggedInUser uzivatel in loginData.users) { + for (Account uzivatel in loginData.users) { AwesomeNotifications().removeChannel(NotificationIds.kreditChannel(uzivatel.username, uzivatel.url)); await AwesomeNotifications().removeChannel(NotificationIds.objednanoChannel(uzivatel.username, uzivatel.url)); } diff --git a/lib/src/logic/canteenwrapper.dart b/lib/src/logic/canteenwrapper.dart index c039853a..8a5a9344 100644 --- a/lib/src/logic/canteenwrapper.dart +++ b/lib/src/logic/canteenwrapper.dart @@ -129,8 +129,8 @@ class LoggedInCanteen { /// If there is an error it's probably because of the internet connection or change of password. The popup is the best solution. Future loginFromStorage() async { try { - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); - if (loginData.currentlyLoggedIn) { + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); + if (loginData.currentlyLoggedInId != null) { _canteenInstance = await _login( loginData.users[loginData.currentlyLoggedInId!].url, loginData.users[loginData.currentlyLoggedInId!].username, @@ -366,14 +366,14 @@ class LoggedInCanteen { // just switches the account - YOU NEED TO CALL [loginFromStorage] AFTER THIS Future switchAccount(int id) async { - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); loginData.currentlyLoggedInId = id; await saveLoginToSecureStorage(loginData); } // switches the account and logs in as the new account Future changeAccount(int id, {bool indexLunches = false, bool saveToStorage = true}) async { - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); String url = loginData.users[id].url; String username = loginData.users[id].username; String password = loginData.users[id].password; @@ -392,10 +392,9 @@ class LoggedInCanteen { Future addAccount(String url, String username, String password) async { try { await _login(url, username, password, safetyId: (_canteenData?.id ?? 0) + 1); - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); - loginData.users.add(LoggedInUser(username: username, password: password, url: url)); + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); + loginData.users.add(Account(username: username, password: password, url: url)); loginData.currentlyLoggedInId = loginData.users.length - 1; - loginData.currentlyLoggedIn = true; saveLoginToSecureStorage(loginData); return true; } catch (e) { @@ -410,7 +409,7 @@ class LoggedInCanteen { } /// saves the loginData class to secure storage - Future saveLoginToSecureStorage(LoginDataAutojidelna loginData) async { + Future saveLoginToSecureStorage(LoggedAccounts loginData) async { await saveStringToSharedPreferencesToSecureStorage('loginData', jsonEncode(loginData)); initAwesome(); } @@ -439,7 +438,7 @@ class LoggedInCanteen { if (analyticsEnabledGlobally && analytics != null) { analytics!.logEvent(name: 'logout'); } - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); bool isDuplicate = false; for (int i = 0; i < loginData.users.length; i++) { if (loginData.users[i].username == loginData.users[id].username && i != id) { @@ -464,7 +463,6 @@ class LoggedInCanteen { loginData.users.removeAt(id); // if it's empty make sure to throw user on login screen if (loginData.users.isEmpty) { - loginData.currentlyLoggedIn = false; loginData.currentlyLoggedInId = null; } await saveLoginToSecureStorage(loginData); @@ -476,10 +474,9 @@ class LoggedInCanteen { ///logs out everyone Future logoutEveryone() async { - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); - loginData.currentlyLoggedIn = false; - loginData.users.clear(); + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); loginData.currentlyLoggedInId = null; + loginData.users.clear(); for (int id = 0; id < loginData.users.length; id++) { AwesomeNotifications().removeChannel(NotificationIds.objednanoChannel(loginData.users[id].username, loginData.users[id].url)); AwesomeNotifications().removeChannel(NotificationIds.kreditChannel(loginData.users[id].username, loginData.users[id].url)); @@ -491,15 +488,15 @@ class LoggedInCanteen { return; } - Future getLoginDataFromSecureStorage() async { + Future getLoginDataFromSecureStorage() async { try { String? value = await getDataFromSecureStorage('loginData'); if (value == null || value.trim().isEmpty) { - return LoginDataAutojidelna(currentlyLoggedIn: false); + return LoggedAccounts(); } - return LoginDataAutojidelna.fromJson(jsonDecode(value)); + return LoggedAccounts.fromJson(jsonDecode(value)); } catch (e) { - return LoginDataAutojidelna(currentlyLoggedIn: false); + return LoggedAccounts(); } } @@ -544,8 +541,8 @@ class LoggedInCanteen { } Future loginAsUsername(String username, {bool saveToStorage = false}) async { - LoginDataAutojidelna loginData = await getLoginDataFromSecureStorage(); - for (LoggedInUser uzivatel in loginData.users) { + LoggedAccounts loginData = await getLoginDataFromSecureStorage(); + for (Account uzivatel in loginData.users) { try { if (uzivatel.username == username) { await _login(uzivatel.url, uzivatel.username, uzivatel.password, safetyId: (_canteenData?.id ?? 0) + 1, indexLunches: false); diff --git a/lib/src/logic/notifications.dart b/lib/src/logic/notifications.dart index ce1a54b1..206ec5d8 100644 --- a/lib/src/logic/notifications.dart +++ b/lib/src/logic/notifications.dart @@ -78,11 +78,11 @@ void backgroundFetchHeadlessTask(HeadlessTask task) async { } Future initAwesome() async { - LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); List notificationChannelGroups = []; List notificationChannels = []; for (int i = 0; i < loginData.users.length; i++) { - LoggedInUser user = loginData.users[i]; + Account user = loginData.users[i]; notificationChannelGroups.add( NotificationChannelGroup( channelGroupKey: NotificationIds.channelGroup(user.username, user.url), @@ -155,7 +155,7 @@ Future doNotifications({bool force = false}) async { //TODO: add more langueages final lang = lookupTexts(Locales.cs); LoggedInCanteen loggedInCanteen = LoggedInCanteen(); - LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + LoggedAccounts loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); AwesomeNotifications().createNotification( content: NotificationContent( id: 588, @@ -435,8 +435,8 @@ class NotificationController { } //přepnutí účtu, když uživatel klikne na notifikaci if (receivedAction?.payload?[NotificationIds.payloadUser] != null) { - LoginDataAutojidelna loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); - for (LoggedInUser uzivatel in loginData.users) { + LoggedAccounts loginData = await loggedInCanteen.getLoginDataFromSecureStorage(); + for (Account uzivatel in loginData.users) { if (uzivatel.username == receivedAction?.payload?[NotificationIds.payloadUser]) { await loggedInCanteen.switchAccount(loginData.users.indexOf(uzivatel)); break; diff --git a/lib/src/types/all.dart b/lib/src/types/all.dart index 7154484e..6d97fe20 100644 --- a/lib/src/types/all.dart +++ b/lib/src/types/all.dart @@ -24,16 +24,18 @@ enum ConnectionErrors { //classy pro přihlašování ///samotný uživatel -class LoggedInUser { +class Account { String username; String password; String url; - LoggedInUser({ + + Account({ required this.username, required this.password, required this.url, }); - LoggedInUser.fromJson(Map json) + + Account.fromJson(Map json) : username = json['username'], password = json['password'], url = json['url']; @@ -44,32 +46,29 @@ class LoggedInUser { }; } -///všichni přihlášení uživatelé -class LoginDataAutojidelna { - LoginDataAutojidelna({ - required this.currentlyLoggedIn, - }); - bool currentlyLoggedIn; +/// Všichni přihlášení uživatelé +class LoggedAccounts { int? currentlyLoggedInId; - List users = []; + List users = []; + + LoggedAccounts({this.currentlyLoggedInId}); - LoginDataAutojidelna.fromJson(Map json) - : currentlyLoggedIn = json['currentlyLoggedIn'], - currentlyLoggedInId = json['currentlyLoggedInId'], - users = json['users'].map((e) => LoggedInUser.fromJson(e)).toList(); + LoggedAccounts.fromJson(Map json) + : currentlyLoggedInId = json['currentlyLoggedInId'], + users = (json['users'] as List).map((e) => Account.fromJson(e)).toList(); Map toJson() => { - 'currentlyLoggedIn': currentlyLoggedIn, 'currentlyLoggedInId': currentlyLoggedInId, 'users': users.map((e) => e.toJson()).toList(), }; } -///omezená data pro zobrazení ve výběru účtů -class LoggedAccountsInAccountPanel { +/// Omezená data pro zobrazení ve výběru účtů +class LoggedAccountsLimited { List usernames; int? loggedInID; - LoggedAccountsInAccountPanel({required this.usernames, required this.loggedInID}); + + LoggedAccountsLimited({required this.usernames, required this.loggedInID}); } ///informace o nejnovější verzi aplikace (podpora jen pro android) @@ -151,8 +150,9 @@ class CanteenData { ///class pro general access o stavu snackbaru class SnackBarShown { - SnackBarShown({required this.shown}); bool shown = false; + + SnackBarShown({required this.shown}); } ///Popisuje všechny možné stavy jídla From 71fc7a531de5e9e13803b0932f7b5d74b759255e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:23:10 +0200 Subject: [PATCH 39/57] update fromJson methods in Account() and LoggedAccounts() --- lib/src/types/all.dart | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/src/types/all.dart b/lib/src/types/all.dart index 6d97fe20..23bc8365 100644 --- a/lib/src/types/all.dart +++ b/lib/src/types/all.dart @@ -35,15 +35,17 @@ class Account { required this.url, }); - Account.fromJson(Map json) - : username = json['username'], - password = json['password'], - url = json['url']; Map toJson() => { 'username': username, 'password': password, 'url': url, }; + + factory Account.fromJson(Map json) => Account( + username: json['username'], + password: json['password'], + url: json['url'], + ); } /// Všichni přihlášení uživatelé @@ -51,16 +53,20 @@ class LoggedAccounts { int? currentlyLoggedInId; List users = []; - LoggedAccounts({this.currentlyLoggedInId}); - - LoggedAccounts.fromJson(Map json) - : currentlyLoggedInId = json['currentlyLoggedInId'], - users = (json['users'] as List).map((e) => Account.fromJson(e)).toList(); + LoggedAccounts({ + this.currentlyLoggedInId, + this.users = const [], + }); Map toJson() => { 'currentlyLoggedInId': currentlyLoggedInId, 'users': users.map((e) => e.toJson()).toList(), }; + + factory LoggedAccounts.fromJson(Map json) => LoggedAccounts( + currentlyLoggedInId: json['currentlyLoggedInId'], + users: (json['users'] as List).map((e) => Account.fromJson(e)).toList(), + ); } /// Omezená data pro zobrazení ve výběru účtů From ad4aec136d5404f99b0464f98e4eabb0073a2138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:34:04 +0200 Subject: [PATCH 40/57] chore: secure storage naming --- lib/src/_conf/secure_storage.dart | 5 +++-- lib/src/logic/canteenwrapper.dart | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/_conf/secure_storage.dart b/lib/src/_conf/secure_storage.dart index 9a722079..5d33e18f 100644 --- a/lib/src/_conf/secure_storage.dart +++ b/lib/src/_conf/secure_storage.dart @@ -2,6 +2,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; /// Secure storage keys for FlutterSecureStorage and options for iOS class SecureStorage { - static const String appleAuthKey = 'apple_auth_key'; - static const options = IOSOptions(accessibility: KeychainAccessibility.first_unlock); + static String get loginData => 'loginData'; + static String get appleAuthKey => 'apple_auth_key'; + static get options => const IOSOptions(accessibility: KeychainAccessibility.first_unlock); } diff --git a/lib/src/logic/canteenwrapper.dart b/lib/src/logic/canteenwrapper.dart index 8a5a9344..1a6bd504 100644 --- a/lib/src/logic/canteenwrapper.dart +++ b/lib/src/logic/canteenwrapper.dart @@ -9,6 +9,7 @@ import 'dart:math'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; +import 'package:autojidelna/src/_conf/secure_storage.dart'; import 'package:autojidelna/src/logic/notifications.dart'; import 'package:autojidelna/src/types/all.dart'; import 'package:awesome_notifications/awesome_notifications.dart'; @@ -403,14 +404,14 @@ class LoggedInCanteen { } /// save data to secure storage used for storing username and password - Future saveStringToSharedPreferencesToSecureStorage(String key, String value) async { + Future saveStringToSecureStorage(String key, String value) async { const storage = FlutterSecureStorage(); await storage.write(key: key, value: value); } /// saves the loginData class to secure storage Future saveLoginToSecureStorage(LoggedAccounts loginData) async { - await saveStringToSharedPreferencesToSecureStorage('loginData', jsonEncode(loginData)); + await saveStringToSecureStorage(SecureStorage.loginData, jsonEncode(loginData)); initAwesome(); } @@ -490,7 +491,7 @@ class LoggedInCanteen { Future getLoginDataFromSecureStorage() async { try { - String? value = await getDataFromSecureStorage('loginData'); + String? value = await getDataFromSecureStorage(SecureStorage.loginData); if (value == null || value.trim().isEmpty) { return LoggedAccounts(); } From e0da95720f903c4c3465d9d2df440f6df3b1ed33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:44:53 +0200 Subject: [PATCH 41/57] delete AnalyticsEventIds & merge Assets classes --- lib/src/_conf/assets.dart | 1 + lib/src/_conf/notifications.dart | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/src/_conf/assets.dart b/lib/src/_conf/assets.dart index 875453f7..557fc909 100644 --- a/lib/src/_conf/assets.dart +++ b/lib/src/_conf/assets.dart @@ -2,4 +2,5 @@ class Assets { static const String icon = 'assets/app_favicon.webp'; static const String appElevateLogo = 'assets/app_elevate.webp'; + static const String logo = 'assets/logo.svg'; } diff --git a/lib/src/_conf/notifications.dart b/lib/src/_conf/notifications.dart index e099a1e7..3d243033 100644 --- a/lib/src/_conf/notifications.dart +++ b/lib/src/_conf/notifications.dart @@ -16,13 +16,6 @@ class NotificationIds { static String get onlyObjednatButton => 'objednat_'; } -class AnalyticsEventIds { - static String get updateButtonClicked => 'updateButtonClicked'; - static String get oldVer => 'oldVersion'; - static String get newVer => 'newVersion'; - static String get updateDownloaded => 'updateDownloaded'; -} - // Strings shown to the user class NotificationsTexts { /// initAwesome and notifications in general have a problem with the localization package so we just force czech @@ -58,7 +51,3 @@ class Links { static String get latestRelease => '$repo/releases/latest'; static String get email => 'info@appelevate.cz'; } - -class Assets { - static String get logo => 'assets/logo.svg'; -} From 3de441b1b0588120f97c3065efaab9e569e806dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:46:01 +0200 Subject: [PATCH 42/57] create Dates class --- lib/src/_conf/dates.dart | 6 ++++-- lib/src/logic/notifications.dart | 4 ++-- lib/src/ui/pages/more/about_page.dart | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/src/_conf/dates.dart b/lib/src/_conf/dates.dart index 9cbc5a10..efbb40d3 100644 --- a/lib/src/_conf/dates.dart +++ b/lib/src/_conf/dates.dart @@ -1,2 +1,4 @@ -final DateTime minimalDate = DateTime(DateTime.now().year, DateTime.now().month - 1, 1); -final DateTime maximalDate = DateTime(DateTime.now().year, DateTime.now().month + 2, 0); +class Dates { + static DateTime minimalDate = DateTime(DateTime.now().year, DateTime.now().month - 1, 1); + static DateTime maximalDate = DateTime(DateTime.now().year, DateTime.now().month + 2, 0); +} diff --git a/lib/src/logic/notifications.dart b/lib/src/logic/notifications.dart index 206ec5d8..6f760a71 100644 --- a/lib/src/logic/notifications.dart +++ b/lib/src/logic/notifications.dart @@ -232,7 +232,7 @@ Future doNotifications({bool force = false}) async { payload: { NotificationIds.payloadUser: loginData.users[i].username, NotificationIds.payloadIndex: k.toString(), - NotificationIds.payloadIndexDne: jidelnicek.den.difference(minimalDate).inDays.toString(), + NotificationIds.payloadIndexDne: jidelnicek.den.difference(Dates.minimalDate).inDays.toString(), }, body: jidelnicek.jidla[0].nazev, ), @@ -249,7 +249,7 @@ Future doNotifications({bool force = false}) async { payload: { NotificationIds.payloadUser: loginData.users[i].username, NotificationIds.payloadIndex: k.toString(), - NotificationIds.payloadIndexDne: jidelnicek.den.difference(minimalDate).inDays.toString(), + NotificationIds.payloadIndexDne: jidelnicek.den.difference(Dates.minimalDate).inDays.toString(), }, body: jidelnicek.jidla[k].kategorizovano?.hlavniJidlo ?? jidelnicek.jidla[k].nazev, ), diff --git a/lib/src/ui/pages/more/about_page.dart b/lib/src/ui/pages/more/about_page.dart index fc788c6d..8447ac07 100644 --- a/lib/src/ui/pages/more/about_page.dart +++ b/lib/src/ui/pages/more/about_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_conf/assets.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_global/app.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; From f898f087bac6e1714aeb5270e1ddb3b406ecd234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 11:47:53 +0200 Subject: [PATCH 43/57] change getter to const in SecureStorage() --- lib/src/_conf/secure_storage.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/_conf/secure_storage.dart b/lib/src/_conf/secure_storage.dart index 5d33e18f..657ba101 100644 --- a/lib/src/_conf/secure_storage.dart +++ b/lib/src/_conf/secure_storage.dart @@ -2,7 +2,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; /// Secure storage keys for FlutterSecureStorage and options for iOS class SecureStorage { - static String get loginData => 'loginData'; - static String get appleAuthKey => 'apple_auth_key'; - static get options => const IOSOptions(accessibility: KeychainAccessibility.first_unlock); + static const String loginData = 'loginData'; + static const String appleAuthKey = 'apple_auth_key'; + static const IOSOptions iosOptions = IOSOptions(accessibility: KeychainAccessibility.first_unlock); } From 0b83dc2a86de886ce98377c6d6c8bc56d9fa1272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 13:24:04 +0200 Subject: [PATCH 44/57] use App.secureStorage --- lib/src/logic/canteenwrapper.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/src/logic/canteenwrapper.dart b/lib/src/logic/canteenwrapper.dart index 1a6bd504..7d9dadc8 100644 --- a/lib/src/logic/canteenwrapper.dart +++ b/lib/src/logic/canteenwrapper.dart @@ -10,6 +10,7 @@ import 'dart:math'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_conf/secure_storage.dart'; +import 'package:autojidelna/src/_global/app.dart'; import 'package:autojidelna/src/logic/notifications.dart'; import 'package:autojidelna/src/types/all.dart'; import 'package:awesome_notifications/awesome_notifications.dart'; @@ -19,7 +20,6 @@ import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:http/http.dart' as http; @@ -405,8 +405,7 @@ class LoggedInCanteen { /// save data to secure storage used for storing username and password Future saveStringToSecureStorage(String key, String value) async { - const storage = FlutterSecureStorage(); - await storage.write(key: key, value: value); + await App.secureStorage.write(key: key, value: value); } /// saves the loginData class to secure storage @@ -420,9 +419,8 @@ class LoggedInCanteen { /// get data from secure storage /// can return null if there is no data Future getDataFromSecureStorage(String key) async { - const storage = FlutterSecureStorage(); try { - String? value = await storage.read(key: key); + String? value = await App.secureStorage.read(key: key); return value; } catch (e) { return null; From 227fb63cb0223a89ec0eb7acebdfa11da93791ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 14:39:27 +0200 Subject: [PATCH 45/57] create AccountProvider --- .../_global/providers/account.provider.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/src/_global/providers/account.provider.dart diff --git a/lib/src/_global/providers/account.provider.dart b/lib/src/_global/providers/account.provider.dart new file mode 100644 index 00000000..665c9ab5 --- /dev/null +++ b/lib/src/_global/providers/account.provider.dart @@ -0,0 +1,27 @@ +import 'package:canteenlib/canteenlib.dart'; +import 'package:flutter/material.dart'; + +class AccountProvider extends ChangeNotifier { + int? _loggedInID; + Uzivatel? _uzivatel; + List _usernames = []; + + int? get loggedInID => _loggedInID; + Uzivatel? get uzivatel => _uzivatel; + List get usernames => _usernames; + + void setLoggedInID(int? id) { + _loggedInID = id; + notifyListeners(); + } + + void setUzivatel(Uzivatel uzivatel) { + _uzivatel = uzivatel; + notifyListeners(); + } + + void addUsername(String username) { + _usernames = List.from([..._usernames, username]); + notifyListeners(); + } +} From 7db3221c6955a55b7dc37aa6bc64cf8ea898d232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 14:44:07 +0200 Subject: [PATCH 46/57] move dialogs to dialogs folder --- lib/src/ui/widgets/{ => dialogs}/configured_alert_dialog.dart | 0 lib/src/ui/widgets/{ => dialogs}/configured_dialog.dart | 0 lib/src/ui/widgets/{ => dialogs}/date_format_picker.dart | 4 ++-- .../ui/widgets/{ => dialogs}/failed_login_dialog_widget.dart | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename lib/src/ui/widgets/{ => dialogs}/configured_alert_dialog.dart (100%) rename lib/src/ui/widgets/{ => dialogs}/configured_dialog.dart (100%) rename lib/src/ui/widgets/{ => dialogs}/date_format_picker.dart (93%) rename lib/src/ui/widgets/{ => dialogs}/failed_login_dialog_widget.dart (100%) diff --git a/lib/src/ui/widgets/configured_alert_dialog.dart b/lib/src/ui/widgets/dialogs/configured_alert_dialog.dart similarity index 100% rename from lib/src/ui/widgets/configured_alert_dialog.dart rename to lib/src/ui/widgets/dialogs/configured_alert_dialog.dart diff --git a/lib/src/ui/widgets/configured_dialog.dart b/lib/src/ui/widgets/dialogs/configured_dialog.dart similarity index 100% rename from lib/src/ui/widgets/configured_dialog.dart rename to lib/src/ui/widgets/dialogs/configured_dialog.dart diff --git a/lib/src/ui/widgets/date_format_picker.dart b/lib/src/ui/widgets/dialogs/date_format_picker.dart similarity index 93% rename from lib/src/ui/widgets/date_format_picker.dart rename to lib/src/ui/widgets/dialogs/date_format_picker.dart index dff290e4..d2ed56c9 100644 --- a/lib/src/ui/widgets/date_format_picker.dart +++ b/lib/src/ui/widgets/dialogs/date_format_picker.dart @@ -2,8 +2,8 @@ import 'package:autojidelna/src/_global/providers/settings.provider.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/logic/get_correct_date_string.dart'; import 'package:autojidelna/src/types/all.dart'; -import 'package:autojidelna/src/ui/widgets/configured_alert_dialog.dart'; -import 'package:autojidelna/src/ui/widgets/configured_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_alert_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_dialog.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; diff --git a/lib/src/ui/widgets/failed_login_dialog_widget.dart b/lib/src/ui/widgets/dialogs/failed_login_dialog_widget.dart similarity index 100% rename from lib/src/ui/widgets/failed_login_dialog_widget.dart rename to lib/src/ui/widgets/dialogs/failed_login_dialog_widget.dart From 3ce383be610c0673e8a14081d711f62424630d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 14:48:31 +0200 Subject: [PATCH 47/57] migrate LinedCard() --- .../ui/pages/settings/appearance_page.dart | 2 +- lib/src/ui/widgets/lined_card.dart | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 lib/src/ui/widgets/lined_card.dart diff --git a/lib/src/ui/pages/settings/appearance_page.dart b/lib/src/ui/pages/settings/appearance_page.dart index a20bfd9e..e32e67c1 100644 --- a/lib/src/ui/pages/settings/appearance_page.dart +++ b/lib/src/ui/pages/settings/appearance_page.dart @@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:autojidelna/src/_global/providers/theme.provider.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; -import 'package:autojidelna/src/ui/widgets/date_format_picker.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/date_format_picker.dart'; import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; import 'package:autojidelna/src/ui/widgets/section_title.dart'; import 'package:autojidelna/src/ui/widgets/theme_mode_picker.dart'; diff --git a/lib/src/ui/widgets/lined_card.dart b/lib/src/ui/widgets/lined_card.dart new file mode 100644 index 00000000..04d44224 --- /dev/null +++ b/lib/src/ui/widgets/lined_card.dart @@ -0,0 +1,100 @@ +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:flutter/material.dart'; + +/// Creates a card with a horizontal bar at the top and bottom +class LinedCard extends StatelessWidget { + const LinedCard({ + super.key, + this.title, + this.footer, + this.titleTextAlign = TextAlign.start, + this.footerTextAlign = TextAlign.center, + this.smallButton = true, + this.transparentTitleDivider = false, + this.transparentFooterDivider = false, + this.onPressed, + this.child, + }); + + /// Card title, aligned with the top bar + final String? title; + + /// Card title, aligned with the bottom bar + final String? footer; + + /// How to align the title text + final TextAlign titleTextAlign; + + /// How to align the footer text + final TextAlign footerTextAlign; + + /// If true, the whole card will be pressable, else only the bottom bar + final bool smallButton; + + /// If true, top bar will be transparent + final bool transparentTitleDivider; + + /// If true, bottom bar will be transparent + final bool transparentFooterDivider; + + /// The callback that is called when the button is tapped or otherwise activated. + final void Function()? onPressed; + + /// Creates a widget that insets its child. + final Widget? child; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: smallButton ? null : onPressed, + child: Card( + margin: const EdgeInsets.symmetric(horizontal: 16), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + dividerWithText(context, text: title, textAlign: titleTextAlign, transparentDivider: transparentTitleDivider), + child ?? const SizedBox(), + footerButton(context), + ], + ), + ), + ), + ); + } + + Widget footerButton(BuildContext context) { + Widget divider = dividerWithText(context, text: footer, textAlign: footerTextAlign, transparentDivider: transparentFooterDivider); + if (!smallButton) return divider; + + return MaterialButton( + visualDensity: const VisualDensity(vertical: -4), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: EdgeInsets.zero, + splashColor: Colors.transparent, + focusColor: Colors.transparent, + highlightColor: Colors.transparent, + textColor: Theme.of(context).colorScheme.primary, + onPressed: onPressed, + child: divider, + ); + } + + Widget dividerWithText(BuildContext context, {String? text, TextAlign? textAlign, bool transparentDivider = false}) { + if (text == null) return CustomDivider(isTransparent: transparentDivider, hasIndent: false, hasEndIndent: false); + return Row( + children: [ + if (textAlign != TextAlign.start && textAlign != TextAlign.left && textAlign != TextAlign.justify) + Flexible(child: CustomDivider(isTransparent: transparentDivider, hasIndent: false)), + if (text == footer && footerTextAlign == TextAlign.end && onPressed != null) ...[ + Icon(Icons.arrow_forward_ios_rounded, size: 15, color: Theme.of(context).listTileTheme.subtitleTextStyle!.color), + const SizedBox(width: 5), + ], + Text(text, style: Theme.of(context).textTheme.labelLarge), + if (textAlign != TextAlign.end && textAlign != TextAlign.right) + Flexible(child: CustomDivider(isTransparent: transparentDivider, hasEndIndent: false)), + ], + ); + } +} From c4d0b3fdda3d086d43be59889d2f91e76f52d0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 16:02:18 +0200 Subject: [PATCH 48/57] migrate LocationPickerCard() UI --- lib/src/lang/app_cs.arb | 2 + lib/src/lang/output/texts.dart | 12 +++ lib/src/lang/output/texts_cs.dart | 6 ++ lib/src/ui/pages/more_page.dart | 3 + .../ui/widgets/more/location_picker_card.dart | 94 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 lib/src/ui/widgets/more/location_picker_card.dart diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 647a3d2e..fd5c10ec 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -44,6 +44,7 @@ "languageEnglish": "Angličtina", "licenses": "Licence", "listUi": "List UI", + "location": "Výdejna", "login": "Přihlásit se", "menu": "Jídelníček", "navigationRailExpantionButtonTitle": "Menu", @@ -54,6 +55,7 @@ "orders": "Objednávky", "password": "Heslo", "patch": "patch", + "pickLocation": "Vyberte výdejnu:", "privacyPolicy": "Zásady ochrany osobních údajů", "requestNotificationPermission": "Požádat o povolení notifikací", "settings": "Nastavení", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 9f083504..c7a78837 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -247,6 +247,12 @@ abstract class Texts { /// **'List UI'** String get listUi; + /// No description provided for @location. + /// + /// In cs, this message translates to: + /// **'Výdejna'** + String get location; + /// No description provided for @login. /// /// In cs, this message translates to: @@ -307,6 +313,12 @@ abstract class Texts { /// **'patch'** String get patch; + /// No description provided for @pickLocation. + /// + /// In cs, this message translates to: + /// **'Vyberte výdejnu:'** + String get pickLocation; + /// No description provided for @privacyPolicy. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 22ebdad1..c7cb5bfe 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -100,6 +100,9 @@ class TextsCs extends Texts { @override String get listUi => 'List UI'; + @override + String get location => 'Výdejna'; + @override String get login => 'Přihlásit se'; @@ -130,6 +133,9 @@ class TextsCs extends Texts { @override String get patch => 'patch'; + @override + String get pickLocation => 'Vyberte výdejnu:'; + @override String get privacyPolicy => 'Zásady ochrany osobních údajů'; diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart index 522e8f76..9cc22e27 100644 --- a/lib/src/ui/pages/more_page.dart +++ b/lib/src/ui/pages/more_page.dart @@ -3,6 +3,7 @@ import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/more/location_picker_card.dart'; import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; import 'package:flutter/material.dart'; import 'package:share_plus/share_plus.dart'; @@ -18,6 +19,8 @@ class MorePage extends StatelessWidget { return ScrollViewColumn( children: [ + const CustomDivider(), + const LocationPickerCard(), const CustomDivider(height: 38), const CustomDivider(isTransparent: false), ListTile( diff --git a/lib/src/ui/widgets/more/location_picker_card.dart b/lib/src/ui/widgets/more/location_picker_card.dart new file mode 100644 index 00000000..422eb2f0 --- /dev/null +++ b/lib/src/ui/widgets/more/location_picker_card.dart @@ -0,0 +1,94 @@ +import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_alert_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/lined_card.dart'; +import 'package:flutter/material.dart'; +import 'package:hive_flutter/adapters.dart'; + +// TODO: IMPLEMENT +class LocationPickerCard extends StatefulWidget { + const LocationPickerCard({super.key}); + + @override + State createState() => _LocationPickerCardState(); +} + +class _LocationPickerCardState extends State { + final bool hasMoreLocations = true; + int selectedLocation = 1; + void updatePicked(int i) => setState(() { + selectedLocation = i; + }); + + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + final Map locations = /*loggedInCanteen.canteenDataUnsafe?.vydejny ?? */ {}; + return Stack( + alignment: AlignmentDirectional.center, + children: [ + LinedCard( + smallButton: false, + title: lang.location, + footer: locations.length > 1 ? lang.pickLocation : null, + footerTextAlign: TextAlign.end, + onPressed: locations.length < 2 ? null : () => pickerDialog(context, locations), + child: ListTile( + contentPadding: EdgeInsets.zero, + visualDensity: const VisualDensity(vertical: -4), + title: Text(locations[selectedLocation + 1] ?? locations[1] ?? ''), + ), + ), + if (locations.isEmpty) lockedCover(context), + ], + ); + } + + void pickerDialog(BuildContext context, Map locations) { + final Texts lang = context.l10n; + configuredDialog( + context, + builder: (context) => ConfiguredAlertDialog( + title: lang.pickLocation, + content: Column( + mainAxisSize: MainAxisSize.min, + children: List.generate( + locations.length, + (i) => ListTile( + visualDensity: VisualDensity.compact, + title: Text( + locations[i + 1]!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + trailing: selectedLocation == i ? const Icon(Icons.check) : null, + onTap: () async { + updatePicked(i); + // loggedInCanteen.zmenitVydejnu(i + 1); + Navigator.of(context).popUntil((route) => route.isFirst); + Hive.box(Boxes.appState) + .put(HiveKeys.location(/*loggedInCanteen.uzivatel?.uzivatelskeJmeno ?? '', loggedInCanteen.canteenDataUnsafe!.url*/ '', ''), i); + }, + ), + ), + ), + ), + ); + } + + Positioned lockedCover(BuildContext context) { + return Positioned.fill( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(.9), + border: Border.all(color: Theme.of(context).dividerTheme.color!), + ), + alignment: Alignment.center, + child: const Icon(Icons.lock_outline_rounded), + ), + ); + } +} From ea519a41a8aed7ddac46092649ff15fe10e44815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sat, 5 Oct 2024 16:17:26 +0200 Subject: [PATCH 49/57] migrate AccountOverviewCard() UI --- lib/src/lang/app_cs.arb | 10 ++++++ lib/src/lang/output/texts.dart | 12 +++++++ lib/src/lang/output/texts_cs.dart | 12 +++++++ lib/src/ui/pages/more_page.dart | 2 ++ .../widgets/more/account_overview_card.dart | 36 +++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 lib/src/ui/widgets/more/account_overview_card.dart diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index fd5c10ec..4327fbf7 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -24,7 +24,17 @@ }, "calendarBigMarkers": "Velké ukazatele v kalendáři", "cancel": "Zrušit", + "changeAccount": "Změnit účet", "convenience": "Pohodlí", + "credit": "Kredit: {ammount} Kč", + "@credit": { + "placeholders": { + "ammount": { + "type": "double", + "format": "decimalPattern" + } + } + }, "dateFormat": "Formát dat", "debug": "Debug", "experimental": "Experimentální", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index c7a78837..39cdcb5f 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -181,12 +181,24 @@ abstract class Texts { /// **'Zrušit'** String get cancel; + /// No description provided for @changeAccount. + /// + /// In cs, this message translates to: + /// **'Změnit účet'** + String get changeAccount; + /// No description provided for @convenience. /// /// In cs, this message translates to: /// **'Pohodlí'** String get convenience; + /// No description provided for @credit. + /// + /// In cs, this message translates to: + /// **'Kredit: {ammount} Kč'** + String credit(double ammount); + /// No description provided for @dateFormat. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index c7cb5bfe..d49db547 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -58,9 +58,21 @@ class TextsCs extends Texts { @override String get cancel => 'Zrušit'; + @override + String get changeAccount => 'Změnit účet'; + @override String get convenience => 'Pohodlí'; + @override + String credit(double ammount) { + final intl.NumberFormat ammountNumberFormat = + intl.NumberFormat.decimalPattern(localeName); + final String ammountString = ammountNumberFormat.format(ammount); + + return 'Kredit: $ammountString Kč'; + } + @override String get dateFormat => 'Formát dat'; diff --git a/lib/src/ui/pages/more_page.dart b/lib/src/ui/pages/more_page.dart index 9cc22e27..107ec695 100644 --- a/lib/src/ui/pages/more_page.dart +++ b/lib/src/ui/pages/more_page.dart @@ -3,6 +3,7 @@ import 'package:autojidelna/src/_conf/notifications.dart'; import 'package:autojidelna/src/_routing/app_router.gr.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/more/account_overview_card.dart'; import 'package:autojidelna/src/ui/widgets/more/location_picker_card.dart'; import 'package:autojidelna/src/ui/widgets/scroll_view_column.dart'; import 'package:flutter/material.dart'; @@ -19,6 +20,7 @@ class MorePage extends StatelessWidget { return ScrollViewColumn( children: [ + const AccountOverviewCard(), const CustomDivider(), const LocationPickerCard(), const CustomDivider(height: 38), diff --git a/lib/src/ui/widgets/more/account_overview_card.dart b/lib/src/ui/widgets/more/account_overview_card.dart new file mode 100644 index 00000000..128df56b --- /dev/null +++ b/lib/src/ui/widgets/more/account_overview_card.dart @@ -0,0 +1,36 @@ +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/configured_bottom_sheet.dart'; +import 'package:autojidelna/src/ui/widgets/lined_card.dart'; +import 'package:canteenlib/canteenlib.dart'; +import 'package:flutter/material.dart'; + +class AccountOverviewCard extends StatelessWidget { + const AccountOverviewCard({super.key}); + + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + Uzivatel? user = Uzivatel(); + + return LinedCard( + title: user!.uzivatelskeJmeno ?? '', + footer: lang.changeAccount, + // onPressed: () => configuredBottomSheet(context, builder: (context) => const SwitchAccountPanel()), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Icon(Icons.account_circle, size: 75), + const VerticalDivider(color: Colors.transparent), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(lang.credit(user.kredit), style: Theme.of(context).textTheme.titleMedium), + if (user.kategorie != null) Text(user.kategorie!), + ], + ), + ], + ), + ); + } +} From 3f581696d57d28ed08505a36479f58a23ec8788f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sun, 6 Oct 2024 13:19:54 +0200 Subject: [PATCH 50/57] add locations to accountProvider --- lib/src/_global/providers/account.provider.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/src/_global/providers/account.provider.dart b/lib/src/_global/providers/account.provider.dart index 665c9ab5..384b7894 100644 --- a/lib/src/_global/providers/account.provider.dart +++ b/lib/src/_global/providers/account.provider.dart @@ -5,10 +5,12 @@ class AccountProvider extends ChangeNotifier { int? _loggedInID; Uzivatel? _uzivatel; List _usernames = []; + Map _locations = {}; int? get loggedInID => _loggedInID; Uzivatel? get uzivatel => _uzivatel; List get usernames => _usernames; + Map get locations => _locations; void setLoggedInID(int? id) { _loggedInID = id; @@ -24,4 +26,9 @@ class AccountProvider extends ChangeNotifier { _usernames = List.from([..._usernames, username]); notifyListeners(); } + + void setLocations(Map locations) { + _locations = Map.from(locations); + notifyListeners(); + } } From 0c208ed6eae8fadde59cc9e6e307cc9c74d28923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sun, 6 Oct 2024 13:28:47 +0200 Subject: [PATCH 51/57] add Account Provider to MultiProvider() --- lib/src/ui/material_app.dart | 8 +++++--- lib/src/ui/theme/app_themes.dart | 2 +- lib/src/ui/widgets/theme_style_picker.dart | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/src/ui/material_app.dart b/lib/src/ui/material_app.dart index 3de0c17d..fd0b630b 100644 --- a/lib/src/ui/material_app.dart +++ b/lib/src/ui/material_app.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:autojidelna/src/_conf/hive.dart'; import 'package:autojidelna/src/_global/app.dart'; +import 'package:autojidelna/src/_global/providers/account.provider.dart'; import 'package:autojidelna/src/_global/providers/settings.provider.dart'; import 'package:autojidelna/src/_global/providers/theme.provider.dart'; import 'package:autojidelna/src/_sentry/sentry.dart'; @@ -59,8 +60,8 @@ class _MyAppState extends State { return MaterialApp.router( debugShowCheckedModeBanner: false, themeMode: theme.themeMode, - theme: AppThemes.theme(theme.colorSchemeLight(theme.themeStyle), theme.amoledMode), - darkTheme: AppThemes.theme(theme.colorSchemeDark(theme.themeStyle), theme.amoledMode), + theme: AppThemes.theme(theme.colorSchemeLight(theme.themeStyle)), + darkTheme: AppThemes.theme(theme.colorSchemeDark(theme.themeStyle), amoledMode: theme.amoledMode), locale: _locale, supportedLocales: Texts.supportedLocales, localizationsDelegates: Texts.localizationsDelegates, @@ -83,8 +84,9 @@ class MyAppWrapper extends StatelessWidget { return MultiProvider( providers: [ ChangeNotifierProvider.value(value: App.remoteConfigProvider), + ChangeNotifierProvider(create: (_) => AccountProvider()), ChangeNotifierProvider(create: (_) => ThemeProvider()), - ChangeNotifierProvider(create: (_) => Settings()) + ChangeNotifierProvider(create: (_) => Settings()), ], child: const MyApp(), ); diff --git a/lib/src/ui/theme/app_themes.dart b/lib/src/ui/theme/app_themes.dart index 5873174c..05ad99e8 100644 --- a/lib/src/ui/theme/app_themes.dart +++ b/lib/src/ui/theme/app_themes.dart @@ -96,7 +96,7 @@ class AppThemes { onInverseSurface: Colors.black, ); - static ThemeData theme(ColorScheme colorScheme, bool amoledMode) => ThemeData( + static ThemeData theme(ColorScheme colorScheme, {bool amoledMode = false}) => ThemeData( useMaterial3: true, applyElevationOverlayColor: true, materialTapTargetSize: MaterialTapTargetSize.padded, diff --git a/lib/src/ui/widgets/theme_style_picker.dart b/lib/src/ui/widgets/theme_style_picker.dart index 7a03aa6e..c941ecc8 100644 --- a/lib/src/ui/widgets/theme_style_picker.dart +++ b/lib/src/ui/widgets/theme_style_picker.dart @@ -20,7 +20,10 @@ class ThemeStylePicker extends StatelessWidget { ThemeStyle themeStyle = ThemeStyle.values[index]; final bool isBright = MediaQuery.platformBrightnessOf(context) == Brightness.light || prov.themeMode == ThemeMode.light; - ThemeData theme = AppThemes.theme(isBright ? prov.colorSchemeLight(themeStyle) : prov.colorSchemeDark(themeStyle), prov.amoledMode); + ThemeData theme = AppThemes.theme( + isBright ? prov.colorSchemeLight(themeStyle) : prov.colorSchemeDark(themeStyle), + amoledMode: prov.amoledMode, + ); ButtonStyle style = OutlinedButton.styleFrom( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), From e05ed0b97ac68df5dabcb47ea4fd07673cc98a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sun, 6 Oct 2024 14:02:47 +0200 Subject: [PATCH 52/57] use account provider in AccountOverviewCard() & LocationPickerCard() --- .../_global/providers/account.provider.dart | 11 ++++- .../widgets/more/account_overview_card.dart | 41 +++++++++------- .../ui/widgets/more/location_picker_card.dart | 48 +++++++++++-------- 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/lib/src/_global/providers/account.provider.dart b/lib/src/_global/providers/account.provider.dart index 384b7894..3221c87c 100644 --- a/lib/src/_global/providers/account.provider.dart +++ b/lib/src/_global/providers/account.provider.dart @@ -2,16 +2,23 @@ import 'package:canteenlib/canteenlib.dart'; import 'package:flutter/material.dart'; class AccountProvider extends ChangeNotifier { + String? _url; int? _loggedInID; - Uzivatel? _uzivatel; + Uzivatel _uzivatel = Uzivatel(); List _usernames = []; Map _locations = {}; + String? get url => _url; int? get loggedInID => _loggedInID; - Uzivatel? get uzivatel => _uzivatel; + Uzivatel get uzivatel => _uzivatel; List get usernames => _usernames; Map get locations => _locations; + void setUrl(String url) { + _url = url; + notifyListeners(); + } + void setLoggedInID(int? id) { _loggedInID = id; notifyListeners(); diff --git a/lib/src/ui/widgets/more/account_overview_card.dart b/lib/src/ui/widgets/more/account_overview_card.dart index 128df56b..e251e596 100644 --- a/lib/src/ui/widgets/more/account_overview_card.dart +++ b/lib/src/ui/widgets/more/account_overview_card.dart @@ -1,8 +1,11 @@ +import 'package:autojidelna/src/_global/providers/account.provider.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/theme/app_themes.dart'; import 'package:autojidelna/src/ui/widgets/configured_bottom_sheet.dart'; import 'package:autojidelna/src/ui/widgets/lined_card.dart'; import 'package:canteenlib/canteenlib.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class AccountOverviewCard extends StatelessWidget { const AccountOverviewCard({super.key}); @@ -10,27 +13,31 @@ class AccountOverviewCard extends StatelessWidget { @override Widget build(BuildContext context) { final Texts lang = context.l10n; - Uzivatel? user = Uzivatel(); - return LinedCard( - title: user!.uzivatelskeJmeno ?? '', - footer: lang.changeAccount, - // onPressed: () => configuredBottomSheet(context, builder: (context) => const SwitchAccountPanel()), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Icon(Icons.account_circle, size: 75), - const VerticalDivider(color: Colors.transparent), - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.end, + return Selector( + selector: (_, p1) => p1.uzivatel, + builder: (context, user, ___) { + return LinedCard( + title: user.uzivatelskeJmeno ?? '', + footer: lang.changeAccount, + // onPressed: () => configuredBottomSheet(context, builder: (context) => const SwitchAccountPanel()), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(lang.credit(user.kredit), style: Theme.of(context).textTheme.titleMedium), - if (user.kategorie != null) Text(user.kategorie!), + const Icon(Icons.account_circle, size: 75), + const VerticalDivider(color: Colors.transparent), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(lang.credit(user.kredit), style: AppThemes.textTheme.titleMedium), + if (user.kategorie != null) Text(user.kategorie!), + ], + ), ], ), - ], - ), + ); + }, ); } } diff --git a/lib/src/ui/widgets/more/location_picker_card.dart b/lib/src/ui/widgets/more/location_picker_card.dart index 422eb2f0..b42da6e3 100644 --- a/lib/src/ui/widgets/more/location_picker_card.dart +++ b/lib/src/ui/widgets/more/location_picker_card.dart @@ -1,10 +1,12 @@ import 'package:autojidelna/src/_conf/hive.dart'; +import 'package:autojidelna/src/_global/providers/account.provider.dart'; import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/widgets/dialogs/configured_alert_dialog.dart'; import 'package:autojidelna/src/ui/widgets/dialogs/configured_dialog.dart'; import 'package:autojidelna/src/ui/widgets/lined_card.dart'; import 'package:flutter/material.dart'; import 'package:hive_flutter/adapters.dart'; +import 'package:provider/provider.dart'; // TODO: IMPLEMENT class LocationPickerCard extends StatefulWidget { @@ -15,8 +17,8 @@ class LocationPickerCard extends StatefulWidget { } class _LocationPickerCardState extends State { - final bool hasMoreLocations = true; int selectedLocation = 1; + void updatePicked(int i) => setState(() { selectedLocation = i; }); @@ -24,24 +26,28 @@ class _LocationPickerCardState extends State { @override Widget build(BuildContext context) { final Texts lang = context.l10n; - final Map locations = /*loggedInCanteen.canteenDataUnsafe?.vydejny ?? */ {}; - return Stack( - alignment: AlignmentDirectional.center, - children: [ - LinedCard( - smallButton: false, - title: lang.location, - footer: locations.length > 1 ? lang.pickLocation : null, - footerTextAlign: TextAlign.end, - onPressed: locations.length < 2 ? null : () => pickerDialog(context, locations), - child: ListTile( - contentPadding: EdgeInsets.zero, - visualDensity: const VisualDensity(vertical: -4), - title: Text(locations[selectedLocation + 1] ?? locations[1] ?? ''), - ), - ), - if (locations.isEmpty) lockedCover(context), - ], + return Selector>( + selector: (_, p1) => p1.locations, + builder: (context, locations, ___) { + return Stack( + alignment: AlignmentDirectional.center, + children: [ + LinedCard( + smallButton: false, + title: lang.location, + footer: locations.length > 1 ? lang.pickLocation : null, + footerTextAlign: TextAlign.end, + onPressed: locations.length < 2 ? null : () => pickerDialog(context, locations), + child: ListTile( + contentPadding: EdgeInsets.zero, + visualDensity: const VisualDensity(vertical: -4), + title: Text(locations[selectedLocation + 1] ?? locations[1] ?? ''), + ), + ), + if (locations.isEmpty) lockedCover(context), + ], + ); + }, ); } @@ -67,8 +73,8 @@ class _LocationPickerCardState extends State { updatePicked(i); // loggedInCanteen.zmenitVydejnu(i + 1); Navigator.of(context).popUntil((route) => route.isFirst); - Hive.box(Boxes.appState) - .put(HiveKeys.location(/*loggedInCanteen.uzivatel?.uzivatelskeJmeno ?? '', loggedInCanteen.canteenDataUnsafe!.url*/ '', ''), i); + AccountProvider account = context.read(); + Hive.box(Boxes.appState).put(HiveKeys.location(account.uzivatel.uzivatelskeJmeno ?? '', account.url ?? ''), i); }, ), ), From 608e969c57e44b25e960157e5e549e6c5c56a9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sun, 6 Oct 2024 14:24:40 +0200 Subject: [PATCH 53/57] migrate Switch Account UI --- lib/src/lang/app_cs.arb | 2 + lib/src/lang/output/texts.dart | 12 +++ lib/src/lang/output/texts_cs.dart | 6 ++ lib/src/ui/widgets/switch_account_panel.dart | 89 ++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 lib/src/ui/widgets/switch_account_panel.dart diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index 4327fbf7..be80a6c6 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -2,6 +2,8 @@ "@@locale": "cs", "about": "O aplikaci", "account": "Účet", + "accounts": "Účty", + "addAccount": "Přidat účet", "amoledMode": "AMOLED mód", "amoledModeSubtitle": "Přidej se k temné straně síly!", "analytics": "Shromažďování údajů", diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 39cdcb5f..57a51c4a 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -103,6 +103,18 @@ abstract class Texts { /// **'Účet'** String get account; + /// No description provided for @accounts. + /// + /// In cs, this message translates to: + /// **'Účty'** + String get accounts; + + /// No description provided for @addAccount. + /// + /// In cs, this message translates to: + /// **'Přidat účet'** + String get addAccount; + /// No description provided for @amoledMode. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index d49db547..88c2c22b 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -12,6 +12,12 @@ class TextsCs extends Texts { @override String get account => 'Účet'; + @override + String get accounts => 'Účty'; + + @override + String get addAccount => 'Přidat účet'; + @override String get amoledMode => 'AMOLED mód'; diff --git a/lib/src/ui/widgets/switch_account_panel.dart b/lib/src/ui/widgets/switch_account_panel.dart new file mode 100644 index 00000000..0015c989 --- /dev/null +++ b/lib/src/ui/widgets/switch_account_panel.dart @@ -0,0 +1,89 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_global/providers/account.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class SwitchAccountPanel extends StatefulWidget { + const SwitchAccountPanel({super.key}); + + @override + State createState() => _SwitchAccountPanelState(); +} + +class _SwitchAccountPanelState extends State { + @override + Widget build(BuildContext context) { + final Texts lang = context.l10n; + + return Column( + children: [ + SectionTitle(lang.accounts), + Selector usernames})>( + selector: (_, p1) => (id: p1.loggedInID, usernames: p1.usernames), + builder: (context, prov, ___) { + List accounts = []; + for (int i = 0; i < prov.usernames.length; i++) { + accounts.add(accountRow(context, i, username: prov.usernames[i], currentAccount: i == prov.id)); + } + + return Flexible( + child: ListView.builder( + itemCount: accounts.length, + itemBuilder: (context, index) => accounts[index], + ), + ); + }, + ), + const CustomDivider(height: 0, isTransparent: false), + addAccountButton(context), + ], + ); + } + + Widget addAccountButton(BuildContext context) { + final Texts lang = context.l10n; + return ListTile( + leading: const Icon(Icons.add), + title: Text(lang.addAccount, style: Theme.of(context).textTheme.bodyLarge), + //onTap: () async => context.router.push(const LoginPage), + ); + } + + Widget accountRow(BuildContext context, int id, {String username = '', bool currentAccount = false}) { + return ListTile( + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(username, style: currentAccount ? const TextStyle(fontWeight: FontWeight.w600) : null), + if (currentAccount) const Icon(Icons.check, size: 30), + ], + ), + trailing: IconButton( + padding: EdgeInsets.zero, + icon: Icon(Icons.logout, size: 30, color: Theme.of(context).colorScheme.onSurface), + onPressed: () async { + if (currentAccount && context.mounted) { + /*configuredDialog( + context, + builder: (BuildContext context) => logoutDialog(context, currentAccount: currentAccount, id: id), + );*/ + } else if (context.mounted) { + // TODO: await loggedInCanteen.logout(id: id); + setState(() {}); + } + }), + onTap: () async { + if (!currentAccount) { + // TODO: await loggedInCanteen.switchAccount(id); + if (context.mounted) { + // Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => const LoggingInWidget()), (route) => false); + } + } + }, + ); + } +} From db6aa1682310d09407f7a7981f4cfe5079edca07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Sun, 6 Oct 2024 14:50:11 +0200 Subject: [PATCH 54/57] migrate AccountPage() UI --- lib/src/lang/app_cs.arb | 7 ++ lib/src/lang/output/texts.dart | 42 +++++++++++ lib/src/lang/output/texts_cs.dart | 21 ++++++ lib/src/ui/pages/more/account_page.dart | 69 ++++++++++++++++++- .../widgets/more/account_overview_card.dart | 3 +- 5 files changed, 140 insertions(+), 2 deletions(-) diff --git a/lib/src/lang/app_cs.arb b/lib/src/lang/app_cs.arb index be80a6c6..fc551f27 100644 --- a/lib/src/lang/app_cs.arb +++ b/lib/src/lang/app_cs.arb @@ -26,6 +26,7 @@ }, "calendarBigMarkers": "Velké ukazatele v kalendáři", "cancel": "Zrušit", + "category": "Kategorie", "changeAccount": "Změnit účet", "convenience": "Pohodlí", "credit": "Kredit: {ammount} Kč", @@ -61,12 +62,16 @@ "menu": "Jídelníček", "navigationRailExpantionButtonTitle": "Menu", "more": "Více", + "name": "Jméno", "noFood": "Žádná jídla pro tento den.", "noThankYou": "Ne, děkuji", "notifications": "Oznámení", "orders": "Objednávky", "password": "Heslo", "patch": "patch", + "paymentInfo": "Platební Údaje", + "paymentAccountNumber": "Číslo účtu", + "personalInfo": "Osobní Údaje", "pickLocation": "Vyberte výdejnu:", "privacyPolicy": "Zásady ochrany osobních údajů", "requestNotificationPermission": "Požádat o povolení notifikací", @@ -74,12 +79,14 @@ "shareApp": "Sdílet aplikaci", "signOut": "Odhlásit se", "skipWeekends": "Přeskakovat víkendy", + "specificSymbol": "Specifický symbol", "stopAnalytics": "Zastavit sledování analytických služeb", "theme": "Schéma", "themeModeSystem": "Systém", "themeModeLight": "Světlý", "themeModeDark": "Tmavý", "typeCrash": "Napište \"crash\" pro pád aplikace", + "variableSymbol": "Variabilní symbol", "version": "Verze", "versionSubtitle": "{arg, select, true{Debug} other{Stable}} {version}", "@versionSubtitle": { diff --git a/lib/src/lang/output/texts.dart b/lib/src/lang/output/texts.dart index 57a51c4a..4e3ca670 100644 --- a/lib/src/lang/output/texts.dart +++ b/lib/src/lang/output/texts.dart @@ -193,6 +193,12 @@ abstract class Texts { /// **'Zrušit'** String get cancel; + /// No description provided for @category. + /// + /// In cs, this message translates to: + /// **'Kategorie'** + String get category; + /// No description provided for @changeAccount. /// /// In cs, this message translates to: @@ -301,6 +307,12 @@ abstract class Texts { /// **'Více'** String get more; + /// No description provided for @name. + /// + /// In cs, this message translates to: + /// **'Jméno'** + String get name; + /// No description provided for @noFood. /// /// In cs, this message translates to: @@ -337,6 +349,24 @@ abstract class Texts { /// **'patch'** String get patch; + /// No description provided for @paymentInfo. + /// + /// In cs, this message translates to: + /// **'Platební Údaje'** + String get paymentInfo; + + /// No description provided for @paymentAccountNumber. + /// + /// In cs, this message translates to: + /// **'Číslo účtu'** + String get paymentAccountNumber; + + /// No description provided for @personalInfo. + /// + /// In cs, this message translates to: + /// **'Osobní Údaje'** + String get personalInfo; + /// No description provided for @pickLocation. /// /// In cs, this message translates to: @@ -379,6 +409,12 @@ abstract class Texts { /// **'Přeskakovat víkendy'** String get skipWeekends; + /// No description provided for @specificSymbol. + /// + /// In cs, this message translates to: + /// **'Specifický symbol'** + String get specificSymbol; + /// No description provided for @stopAnalytics. /// /// In cs, this message translates to: @@ -415,6 +451,12 @@ abstract class Texts { /// **'Napište \"crash\" pro pád aplikace'** String get typeCrash; + /// No description provided for @variableSymbol. + /// + /// In cs, this message translates to: + /// **'Variabilní symbol'** + String get variableSymbol; + /// No description provided for @version. /// /// In cs, this message translates to: diff --git a/lib/src/lang/output/texts_cs.dart b/lib/src/lang/output/texts_cs.dart index 88c2c22b..d116c156 100644 --- a/lib/src/lang/output/texts_cs.dart +++ b/lib/src/lang/output/texts_cs.dart @@ -64,6 +64,9 @@ class TextsCs extends Texts { @override String get cancel => 'Zrušit'; + @override + String get category => 'Kategorie'; + @override String get changeAccount => 'Změnit účet'; @@ -133,6 +136,9 @@ class TextsCs extends Texts { @override String get more => 'Více'; + @override + String get name => 'Jméno'; + @override String get noFood => 'Žádná jídla pro tento den.'; @@ -151,6 +157,15 @@ class TextsCs extends Texts { @override String get patch => 'patch'; + @override + String get paymentInfo => 'Platební Údaje'; + + @override + String get paymentAccountNumber => 'Číslo účtu'; + + @override + String get personalInfo => 'Osobní Údaje'; + @override String get pickLocation => 'Vyberte výdejnu:'; @@ -172,6 +187,9 @@ class TextsCs extends Texts { @override String get skipWeekends => 'Přeskakovat víkendy'; + @override + String get specificSymbol => 'Specifický symbol'; + @override String get stopAnalytics => 'Zastavit sledování analytických služeb'; @@ -190,6 +208,9 @@ class TextsCs extends Texts { @override String get typeCrash => 'Napište \"crash\" pro pád aplikace'; + @override + String get variableSymbol => 'Variabilní symbol'; + @override String get version => 'Verze'; diff --git a/lib/src/ui/pages/more/account_page.dart b/lib/src/ui/pages/more/account_page.dart index b7bf348a..27f84f5c 100644 --- a/lib/src/ui/pages/more/account_page.dart +++ b/lib/src/ui/pages/more/account_page.dart @@ -1,5 +1,13 @@ import 'package:auto_route/auto_route.dart'; +import 'package:autojidelna/src/_global/providers/account.provider.dart'; +import 'package:autojidelna/src/lang/l10n_context_extension.dart'; +import 'package:autojidelna/src/ui/widgets/custom_divider.dart'; +import 'package:autojidelna/src/ui/widgets/dialogs/configured_dialog.dart'; +import 'package:autojidelna/src/ui/widgets/more/account_overview_card.dart'; +import 'package:autojidelna/src/ui/widgets/section_title.dart'; +import 'package:canteenlib/canteenlib.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; @RoutePage() class AccountPage extends StatelessWidget { @@ -7,6 +15,65 @@ class AccountPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Placeholder(); + final Texts lang = context.l10n; + final Uzivatel user = context.read().uzivatel; + + bool firstName = user.jmeno != null && user.jmeno!.trim().isNotEmpty; + bool lastName = user.prijmeni != null && user.prijmeni!.trim().isNotEmpty; + bool category = user.kategorie != null && user.kategorie!.trim().isNotEmpty; + bool bankAccount = user.ucetProPlatby != null && user.ucetProPlatby!.trim().isNotEmpty; + bool varSymbol = user.varSymbol != null && user.varSymbol!.trim().isNotEmpty; + bool specSymbol = user.specSymbol != null && user.specSymbol!.trim().isNotEmpty; + + return Scaffold( + appBar: AppBar( + title: Text(lang.account), + actions: [_appBarLogoutButton(context)], + ), + body: ListView( + children: [ + const CustomDivider(height: 30), + const AccountOverviewCard(), + const CustomDivider(height: 38), + if ((firstName && lastName) || category) SectionTitle(lang.personalInfo), + if (firstName && lastName) + ListTile( + title: Text('${user.jmeno!} ${user.prijmeni!}'), + subtitle: Text(lang.name), + ), + if (lastName) + ListTile( + title: Text(user.kategorie!), + subtitle: Text(lang.category), + ), + if (bankAccount || varSymbol || specSymbol) SectionTitle(lang.paymentInfo), + if (bankAccount) + ListTile( + title: Text(user.ucetProPlatby!), + subtitle: Text(lang.paymentAccountNumber), + ), + if (varSymbol) + ListTile( + title: Text(user.varSymbol!), + subtitle: Text(lang.variableSymbol), + ), + if (specSymbol) + ListTile( + title: Text(user.specSymbol!), + subtitle: Text(lang.specificSymbol), + ), + ], + ), + ); + } + + Padding _appBarLogoutButton(BuildContext context) { + return const Padding( + padding: EdgeInsets.only(right: 8.0), + child: IconButton( + onPressed: null /* TODO: () => configuredDialog(context, builder: (BuildContext context) => logoutDialog(context))*/, + icon: Icon(Icons.logout), + ), + ); } } diff --git a/lib/src/ui/widgets/more/account_overview_card.dart b/lib/src/ui/widgets/more/account_overview_card.dart index e251e596..2c3aaad8 100644 --- a/lib/src/ui/widgets/more/account_overview_card.dart +++ b/lib/src/ui/widgets/more/account_overview_card.dart @@ -3,6 +3,7 @@ import 'package:autojidelna/src/lang/l10n_context_extension.dart'; import 'package:autojidelna/src/ui/theme/app_themes.dart'; import 'package:autojidelna/src/ui/widgets/configured_bottom_sheet.dart'; import 'package:autojidelna/src/ui/widgets/lined_card.dart'; +import 'package:autojidelna/src/ui/widgets/switch_account_panel.dart'; import 'package:canteenlib/canteenlib.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -20,7 +21,7 @@ class AccountOverviewCard extends StatelessWidget { return LinedCard( title: user.uzivatelskeJmeno ?? '', footer: lang.changeAccount, - // onPressed: () => configuredBottomSheet(context, builder: (context) => const SwitchAccountPanel()), + onPressed: () => configuredBottomSheet(context, builder: (context) => const SwitchAccountPanel()), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ From eaf387da1350e38325e83c7ecc158f7ca8374e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Wed, 9 Oct 2024 19:08:29 +0200 Subject: [PATCH 55/57] fix clipping in themestylepicker --- lib/src/ui/widgets/theme_style_picker.dart | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/src/ui/widgets/theme_style_picker.dart b/lib/src/ui/widgets/theme_style_picker.dart index c941ecc8..ef6a1ed2 100644 --- a/lib/src/ui/widgets/theme_style_picker.dart +++ b/lib/src/ui/widgets/theme_style_picker.dart @@ -25,8 +25,10 @@ class ThemeStylePicker extends StatelessWidget { amoledMode: prov.amoledMode, ); + BorderRadius radius = BorderRadius.circular(16); + ButtonStyle style = OutlinedButton.styleFrom( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + shape: RoundedRectangleBorder(borderRadius: radius), fixedSize: const Size.fromWidth(125), padding: EdgeInsets.zero, side: BorderSide( @@ -40,16 +42,20 @@ class ThemeStylePicker extends StatelessWidget { data: theme, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 5), - child: OutlinedButton( - style: style, - onPressed: () => prov.setThemeStyle(ThemeStyle.values[index]), - child: Column( - children: [ - SizedBox(height: 35, child: AppBar(automaticallyImplyLeading: false)), - const Divider(color: Colors.transparent), - foodTileColorSchemePreview(context, theme.colorScheme.primary), - foodTileColorSchemePreview(context, theme.colorScheme.secondary), - ], + child: ClipRRect( + borderRadius: radius, + clipBehavior: Clip.hardEdge, + child: OutlinedButton( + style: style, + onPressed: () => prov.setThemeStyle(ThemeStyle.values[index]), + child: Column( + children: [ + SizedBox(height: 35, child: AppBar(automaticallyImplyLeading: false)), + const Divider(color: Colors.transparent), + foodTileColorSchemePreview(context, theme.colorScheme.primary), + foodTileColorSchemePreview(context, theme.colorScheme.secondary), + ], + ), ), ), ), From e9fea7886392b4650fdb8765bad420f5798d496a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 10 Oct 2024 08:27:57 +0200 Subject: [PATCH 56/57] add lincense --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 2ce70ede419f6689c966e20e1b7e3f78076b9f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Verhaegen?= Date: Thu, 10 Oct 2024 08:28:31 +0200 Subject: [PATCH 57/57] migrate readme --- README.md | 46 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 42bc70ac..e38eaaa0 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,17 @@ -# APPE Core +# Autojidelna -Core pro aplikace. Obsahuje template pro aplikace vytvořené v App Elevate. +Aplikace pro objednávání ze systému Icanteen. Cíl této aplikace je zjednodušit, zrychlit, (případně i zautomatizovat) objednávání obědů. -## Doporučený environment +## Kód pro přistup do Icanteen -- macOS má aktuálně implementované všechny skripty, ale pro windows uživatele nebude náročné si je upravit. Na linuxu by mělo vše fungovat bez problémů. -- Doporučený editor je Visual Studio Code s rozšířeními [Flutter](https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter), [Arb-files](https://marketplace.visualstudio.com/items?itemName=Google.arb-editor), [Run on save](https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave) a [Build Runner](https://marketplace.visualstudio.com/items?itemName=GaetSchwartz.build-runner&ssr=false#review-details). Run on save je pro automatické formátování arb souborů (překlady) a build runner je pro automatické generování kódu. -- tyto extensiony nepotřebují žádné další konfigurace. -- macOS má zároveň podporu kompilace pro iOS a macOS. +Aplikace používá package [canteenlib](https://github.com/App-Elevate/AUT.canteenlib), ve které se nachází všechen kód ohledně přihlašování, objednávání obědů apod. Pokud by vás zajímalo jak aplikace ukládá vaše údaje podívejte se do [canteenwrapper.dart](./lib/src/logic/canteenwrapper.dart) -## Vývojářské nástroje +## Podporované platformy -- Tento projekt používá build_runner pro automatické generování kódu. Pro spuštění je potřeba spustit `dart run build_runner watch` nebo `dart run build_runner build` pro jednorázový build. Toto je potřeba spustit pokaždé, co upravíte freezed soubory, nebo router. (např `@RoutePage` nebo `@freezed`) -- Doporučuji to mít zapnuté jako `watch` dole, když máte build runner extension ve Visual Studio Code. Pokud se vás to zeptá na složku, ve které to spusti, zvolte `lib`. +Aktuálně je podporován pouze Android, ale je v plánu podporovat i IOS. Ostatní systémy není v plánu podporovat. -# [Spouštění aplikace](docs/spousteni_aplikace.md) +## Kompilování -# [Distribuce](docs/automaticky_deployment.md) +Odstraňte klíče originálního autora tím, že přepíšete ['signingConfig signingConfigs.release'](https://github.com/App-Elevate/AUT.aplikace/blob/28096713e958f0e1e4f3cf8e49aaefbeeedbb5f2/android/app/build.gradle#L71-L72) na `signingConfig signingConfigs.debug`, odstraněním [signing Keys](https://github.com/tpkowastaken/autojidelna/blob/5d0587befd74fd58315ccc131894feb8588b09fe/android/app/build.gradle#L27-L31) a odstraněním [signing Configs](https://github.com/tpkowastaken/autojidelna/blob/5d0587befd74fd58315ccc131894feb8588b09fe/android/app/build.gradle#L60-L67). -# Omezení implementace CORU - -1. firebase_options.dart MUSÍ být v /lib/firebase_options.dart - -## iOS - -1. Je potřeba po každém přidání entitlementu zapnout automatické podepisování v Xcode a následně ho vypnout. Potom už stačí jen regenerovat certifikáty pomocí fastlane match: - -```bash -cd ios && bundle install && bundle exec fastlane match appstore --force && bundle exec fastlane match development --force && cd .. -``` - -a následně znovu buildnout aplikaci. Toto musí udělat Tom, protože je potřeba mít přístup k certifikátům. - -## macOS - -1. Je potřeba po každém přidání entitlementu zapnout automatické podepisování v Xcode a následně ho vypnout. Potom už stačí jen regenerovat certifikáty pomocí fastlane match: - -```bash -cd macos && bundle install && bundle exec fastlane match appstore --additional-cert-types=mac_installer_distribution --force --platform=macos && bundle exec fastlane match development --force --platform=macos && cd .. -``` - -a následně znovu buildnout aplikaci. Toto musí udělat Tom, protože je potřeba mít přístup k certifikátům. - -# [Vytváření nové aplikace](docs/novy_projekt.md) +Pro systém android stačí mít nainstalovaný [Flutter](https://docs.flutter.dev/get-started/install) a poté `flutter build apk` pro android na windows nebo `flutter build ipa` pro ios na macbooku. Aplikaci na IOS můžete nainstalovat pomocí [tohoto návodu](https://chrunos.com/install-ipa-on-iphone/)