From 2aecb9d431440c5283d1c59eca6eaedc7014bf47 Mon Sep 17 00:00:00 2001 From: bossanyit Date: Tue, 29 Dec 2020 13:20:35 +0100 Subject: [PATCH] WT1.1.0+41 error fixing --- i18n/en.json | 21 ++- i18n/hu.json | 22 ++- ios/Runner.xcodeproj/project.pbxproj | 12 +- lib/bloc/menu/menu_bloc.dart | 6 +- lib/main.dart | 4 + lib/model/cache.dart | 4 +- .../customer_exercise_device_service.dart | 1 + lib/service/purchase.dart | 14 +- lib/util/session.dart | 4 - lib/view/exercise_execute_page.dart | 3 +- lib/view/exercise_execute_plan_add_page.dart | 1 + lib/view/exercise_log_page.dart | 14 +- lib/view/gdpr.dart | 11 +- lib/view/mydevelopment_body_page.dart | 9 +- lib/view/mydevelopment_muscle_page.dart | 8 +- lib/view/mydevelopment_page.dart | 9 +- lib/view/myexcercise_plan_page.dart | 24 +-- lib/view/sales_page.dart | 45 +---- lib/widgets/bottom_nav.dart | 3 +- lib/widgets/dialog_common.dart | 176 ++++++++++++++++++ lib/widgets/dialog_premium.dart | 140 +++++++++++--- lib/widgets/menu_page_widget.dart | 98 +++++++++- 22 files changed, 492 insertions(+), 137 deletions(-) create mode 100644 lib/widgets/dialog_common.dart diff --git a/i18n/en.json b/i18n/en.json index 855f830..3916e3c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -21,7 +21,7 @@ "Settings": "Settings", "Profile": "Profile", "Selected Language": "Selected Language", - "gdpr_text": "Kik vagyunk\nA weboldalunk a https://andio.biz (blogbejegyzések) és https://natur-haztartas.hu webáruház.\n\nCélunk a természetes és natúr életmód népszerűsítése, hogy az vásárlóinkat és érdeklődőinket segítsünk a vegyszermentes és natúr életmód felé vezető úton.\n\nMelyek azok a személyes adatok amiket gyűjtünk, és milyen céllal gyűjtjük azokat\nVásárlás\nMegrendelés esetén elkérjük a következő adatokat:\n\na nevet: hogy azonosítsunk csomagszállítás esetén, illetve a számlára is rákerül a vásárló neve\nemail címet: megrendelés visszaigazoláshoz, a csomag állapotának a közléséhez. Emellett, ha engedélyt kapunk, hírleveleket is küldünk natúr életmód tippekről, ajánlatokról. Ezekről a levelekről bármikor, egy kattintással le tudsz iratkozni, a levél alján.\ncímet: A csomag szállításához fontos a pontos cím. A számlára is ez a cím kerül, de lehetőséged van itt egy másik, csak számlázási címet megadni.\ntelefonszámot: SMS értesítőt küldünk a csomag kiszállítása előtt egy munkanappal. Ha valamilyen más probléma merül fel a csomag összeállításakor, akkor lehetséges, hogy telefonon megkeresünk és tisztázzuk a problémákat (pl. áruhiány, rosszul megadott adatok kijavítása, stb).\nHozzászólások\nHozzászólás beküldésekor a hozzászólási űrlapban megadottakon kívül begyűjtésre kerül a hozzászóló IP címe és a böngészőazonosító karakterlánc a kéretlen tartalmak kiszűrése céljából.\n\nEgy személytelenített, az e-mail címből előállított karakterlánc (hashnek szokás nevezni) kerül továbbításra a Gravatar szolgáltatás felé, ha ez az oldalon használatban van. A Gravatar szolgáltatás feltételei az alábbi címen tekinthetőek meg: https://automattic.com/privacy/. A hozzászólás elfogadása után, a hozzászólásunk tartalma és a profil képünk is megjelenik nyilvánosan.\n\nKapcsolatfelvételi űrlapok\nAmennyiben szeretnél, feliratkozhatsz hírlevelünkre weboldalunkon az ott található regisztrációs űrlap kitöltésével. (pl: https://natur-haztartas.hu/login?back=my-account)\n\nHa kitöltöd a regisztrációs űrlapot és rendelkezésünkre bocsátod személyes adataidat vagy a vevőként történő regisztrációjakor hozzájárultál ahhoz, hogy hírlevelet küldjünk az számodra, e-mailt fogsz kapni tőlünk a megadott e-mail címre.\n\nA regisztrációs űrlapon megadott személyes adatok kezelésére kizárólag a hírlevélnek az e-mail címre történő küldése céljából kerül.\n\nA hírleveleinkben található linkek nyomon követési információkat tartalmaznak, melyek segítségével megállapíthatjuk, hogy különösen mely linkek érdekeltek téged, amelyekre rákattintottál.\n\nA nyomon követési link segítségével a következő adatok tárolása történik a hírlevélkezelő rendszerünkbe: e-mail cím, hírlevél, link, dátum és idő. Az személyes adataidat csak addig tároljuk, amíg a „leiratkozás” linkre kattintva le nem iratkozol a hírlevélről. E link megtalálható minden egyes tőlünk kapott hírlevél alján. Amennyiben leiratkozol személyes adataid késedelem nélkül törlésre kerülnek. Felhívjuk a figyelmed arra, hogy személyes adatok törlését követően nem fogsz tőlünk több hírlevelet vagy kupont kapni.\n\nHa üzenetet küldesz az Andió Facebook messengerére, akkor jogosultak vagyunk az Andió által viszontüzenetet küldeni a Te messengeredre. Ezekről az üzeneteket bármikor leállíthatod, ha a messengerbe beírod a STOP szót és utána megnyomod a „leiratkozok” gombot.\n\nSütik és nyomon követés\nHozzászólás írása után a honlap a megadott nevet, e-mail és web címet sütiben eltárolja. A tárolás csak kényelmi célokat szolgál, hogy a következő hozzászóláskor ne kelljen automatikusan kitölteni. A sütik lejárati ideje 1 év.\n\nHa rendelkezel felhasználói fiókkal és be is vagy jelentkezve erre a honlapra, akkor átmeneti sütiket állítunk be, annak érdekében, hogy megállapítsuk, hogy a böngésző elfogadja-e a sütiket. Ezek a sütik nem tartalmaznak személyes információt, és törlődnek, ahogy bezárjuk a böngészőt.\n\nA honlapra történő bejelentkezéskor több sütit hozunk létre, amely elmenti a bejelentkezési információt és a szerkesztőfelület megjelenítési opcióit. A bejelentkezési sütik két napig érvényesek, a szerkesztőfelület megjelenítési opcióit tároló süti egy évig. Amennyiben az “Emlékezz rám” opciót bejelöljük, a bejelentkezés két hétig folytatódik. Kijelentkezéskor a bejelentkezési sütik eltávolításra kerülnek.\n\nHa a webáruházban jársz, akkor a kosarad tartalmát és a bejelentkezési állapotodat is a süti tartalmazza. Így ha kikapcsolod a sütiket a böngésződben, akkor nem tudsz a honlapon rendelni, így azt ímélen vagy telefonon tudod megtenni.\n\nA Google Inc. („Google”) által biztosított Google Analytics internetes elemző szolgáltatást is igénybe vesszük. A Google Analytics szintén sütiket használ. A sütik által a weboldalhasználattal kapcsolatban létrehozott információk általában egy USA-beli Google-szerverre kerülnek, és ott tárolják őket. Ezt megelőzően a Google lerövidíti az IP-címedet az Európai Unió tagállamain és az Európai Gazdasági Térségről szóló megállapodás részes államain belül. Teljes IP-címet csak kivételes esetekben továbbítanak lerövidítés céljából a Google USA-ban található szervereire. A Google a weboldal üzemeltetője megbízásából ezen információk alapján értékeli az weboldalhasználatod, és weboldalaktivitással kapcsolatos jelentéseket készít, valamint további weboldal- és internethasználattal kapcsolatos szolgáltatásokat nyújt a weboldal üzemeltetője számára. Az böngésződ által a Google Analytics szolgáltatása révén továbbított IP-címet nem kapcsolják össze a Google más adataival. A böngésződ megfelelő beállításainak kiválasztásával elutasíthatod a sütik használatát. Megtilthatod azt is, hogy a Google gyűjtse és feldolgozza a sütik által létrehozott és a weboldalhasználatodra vonatkozó adatokat (beleértve az IP-címet). Ehhez töltsd le és telepítse a következő linken található beépülő böngészőmodult: https://tools.google.com/dlpage/gaoptout?hl=en\n\nA Facebook által biztosított adatelemzést és követést is használjuk. Így ha a honlapon jársz, később találkozhatsz egy hirdetéssel, amely a meglátogatott honlap oldalról szól, mert feltételezzük, hogy érdekel Téged a téma, és még többet szeretnél megtudni róla.\n\nVásárlás után véleményt kérünk a vásárolt termékről a Yotpo.com szolgáltatásán keresztül. Itt megírhatod a véleményed, amely kikerül a termék weboldalára esetleg az Andió facebook oldalára is. A vásárlás után kb. 2 héttel egy emailt kapsz, hogy írd meg a véleményed. Erről a véleménykérő emailről is leiratkozhatsz a levél alján látható leiratkozási linkkel.\n\nNéhány weboldalunkat elemezzük, hogy minél jobban követhető, olvasható és használható legyen. Ez az elemzés a Hotjar.com szolgáltatásával személyes adatok gyűjtése és felhasználása nélkül rögzíti a tevékenységedet az oldalon és a sok látogató össztevékenységét összevetve tudjuk az oldal minőségét javítani.\n\nMás honlapokról származó beágyazott tartalmak\nA honlapon elérhető bejegyzések külső forrásból származó beágyazott tartalmakat (pl. videók, képek, cikkek stb.) használhatnak. A külső forrásból származó beágyazott tartalmak pontosan úgy viselkednek, mintha meglátogattunk volna egy másik honlapot.\n\nEzek a webhelyek lehetséges, hogy adatot gyűjtenek a látogatókról, sütiket vagy harmadik féltől származó követőkódot használnak, figyelik a beágyazott tartalommal kapcsolatos felhasználói viselkedést, ha rendelkezünk felhasználói fiókkal és be vagyunk jelentkezve az oldalra.\n\nKivel osztjuk meg és hová továbbítjuk a felhasználói adatokat\nAz elkért és tárolt adatokat a webtárhelyen adatbázisban őrizzük. A webtárhely tulajdonosa a Magyar Hosting Kft (Székhely: 1132 Budapest, Victor Hugo u. 18, Postacím: ua. Telefon: (1) 700 2323 Web: https://www.mhosting.hu/ )\n\nA nevet és a címet csomagszállítás esetén továbbítjuk a futárszolgálat felé, amely kiszállítja a címedre a csomagot.\n\nBelföldi szállítás esetén: Complexpress Logisztika Kft.,1033 Budapest, Szentendrei út 89-95. Telefon: 06-1-203-4681\n\nKülföldi szállítás esetén: GLS General Logistics Systems Hungary Csomag-Logisztikai Kft. 2351 Alsónémedi GLS Európa u. 2. info@gls-hungary.com.\n\nA vásárláshoz minden esetben számlát adunk ki, amelyet bármikor letölthetsz a webáruház felhasználó fiókodból: https://natur-haztartas.hu/ugyfelfiok. A számlán levő adatokat (név és cím) elküldjük a könyvelőirodának, amelyet törvényi kötelezettségünk 8 évig megőrizni.\n\nA könyvelőiroda: Adókalkulátor Kft. Cím: Budapest, Szigligeti u. 44, 1205 Telefon: (20) 292 1072\n\nMennyi ideig őrizzük a személyes adatot\nHa hozzászólsz egy blogbejegyzéshez, hozzászólás és annak metaadatai nem meghatározható ideig a rendszerben maradnak. Ennek célja, hogy az összes ezt követő bármely hozzászólás általunk megismertté és jóváhagyottá váljon, azaz ne kerüljön fel a moderálandó hozzászólások listájára.\n\nA honlapon regisztrált felhasználók személyes adatai a felhasználói profiljukban is tárolásra kerülnek. (https://natur-haztartas.hu/ugyfelfiok)\n\nA vásárláskor megadott adatokat a törvény szerint 8 év őrizzük.\n\nA hírlevél feliratkozáskor ill. kapcsolati űrlapon megadott adatokat nem töröljük, csak kérésre. Ezt egy kattintással megteheted minden hírlevél alján, ill. az ügyfelszolgálati email címen is kérheted a törlést.\n\nMilyen jogokkal rendelkezik a felhasználó a saját adatai kapcsán\nA weboldalon regisztrált fiók vagy hozzászólás írása esetén kérhető a személyes adatok export fájlban történő megküldése, amely bármilyen adatot tartalmaz, amit korábban a felhasználó rendelkezésünkre bocsátott.\n\nKérhető továbbá, hogy bármilyen korábban megadott személyes adatot töröljük. Ezt megteheted minden hírlevél alján levő leiratkozás gombbal, vagy ügyfélszolgálati elérhetőségeink egyikén. A törlés nem vonatkozik azokra az adatokra, amelyeket adminisztrációs, jogi vagy biztonsági okokból kötelező megőriznünk.\n\nAdathelyesbítés: ha pontatlanok az adataid (név, email cím, szállítási cím), megteheted az ugyfelszolgalat@andio.biz email címen keresztül\n\nKapcsolati adatok\nÜgyfélszolgálat:\n\nemail: ugyfelszolgalat@andio.biz\n\ntelefon munkaidőben: +36 30 580 0499", + "gdpr_text": "", "Please log in": "Please log in", "Exception: Customer does not exist or the password is wrong": "The email does not exist or the password is wrong", @@ -151,7 +151,7 @@ "Edit My Custom Plan": "Edit My Custom Plan", "Suggested Training Plan": "Suggested Training Plan", "My Special Plan": "My Special Plan", - "My Arnold's Plan":"Stars Exercise Plan", + "Star's Exercise Plan":"Star's Exercise Plan", "My Trainee's Plan": "My Trainee's Plan", "Execute My Trainee's Training Plan": "Execute My Trainee's Training Plan", @@ -249,6 +249,21 @@ "Min BPM":"Min BPM", "Average BPM":"Average BPM", "Fatburn %":"Fatburn %", - "Health Data Summary":"Health Data Summary" + "Health Data Summary":"Health Data Summary", + + "Congratulation!":"Congratulation!", + "You have achieved to first 100% test-round!":"You have achieved to first 100% test round!", + "Now you unlocked: Development By Muscles and the Suggested Trainings Plan":"Now you have unlocked: Development By Muscles and the Suggested Trainings Plan", + + "The": "The", + "the first":"the first", + "the second":"the second", + "Go Premium":"Go Premium", + "Unleash your potential with WorkoutTest Premium!":"Unleash your potential with WorkoutTest Premium!", + "feature is reachable after you finished":"feature is reachable after you finished", + "100% test circles":"100% test circles", + + "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises." + } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index e9a009b..ec9c37b 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -73,7 +73,7 @@ "repeat": "ismétlés", - "meter": "meter", + "meter": "méter", "percent": "százalék", "kg": "kg", "kilogram": "kilogramm", @@ -148,7 +148,7 @@ "Edit My Custom Plan": "Egyéni edzésterv", "Suggested Training Plan": "Javasolt edzésterv", "My Special Plan": "Speciális edzésterv", - "My Arnold's Plan": "Sztárok edzésterves", + "Star's Exercise Plan": "Sztárok edzésterve", "My Trainee's Plan" : "Kliensem edzésterve", "Execute My Trainee's Training Plan": "Kliensem edzéstervének végrehajtása", @@ -250,6 +250,22 @@ "Min BPM":"Min pulzus", "Average BPM":"Átl pulzus", "Fatburn %":"Zsírégetés %", - "Health Data Summary":"Egészségadatok összefoglalás" + "Health Data Summary":"Egészségadatok összefoglalás", + + "Congratulation!":"Gratulálok!", + "You have achieved to first 100% test-round!":"Teljesítetted az első 100%-os tesztköröd!", + "Now you unlocked: Development By Muscles and the Suggested Trainings Plan":"Mostantól elérheted az 'Izomcsoportok fejlődése' és a 'Javasolt edzésterv' kategóriákat.", + + "The": "A", + "the first":"az első", + "the second":"a második", + "Go Premium":"Válts Prémiumra", + "Unleash your potential with WorkoutTest Premium!":"Bontakoztasd ki az erősségeidet WorkoutTest Prémiummal!", + "feature is reachable after you finished":"funkció elérhető számodra, miután teljesítetted", + "100% test circles":"100%-os teszt-köröd", + + "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését" + + } \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7e6a778..59208eb 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -366,7 +366,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 40; + CURRENT_PROJECT_VERSION = 41; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -388,7 +388,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -509,7 +509,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 40; + CURRENT_PROJECT_VERSION = 41; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -532,7 +532,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -544,7 +544,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 40; + CURRENT_PROJECT_VERSION = 41; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -566,7 +566,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/lib/bloc/menu/menu_bloc.dart b/lib/bloc/menu/menu_bloc.dart index 025d2e2..bd17683 100644 --- a/lib/bloc/menu/menu_bloc.dart +++ b/lib/bloc/menu/menu_bloc.dart @@ -49,7 +49,7 @@ class MenuBloc extends Bloc with Trans, Logging { } if (context == null) return; percent = percent * 100; - log("Percent " + percent.toString()); + //log("Percent " + percent.toString()); if (percent == -1 || percent == 0) { infoTitle = t("Greetings!"); infoText = t("The purpose is to measure you physical condition") + @@ -66,6 +66,10 @@ class MenuBloc extends Bloc with Trans, Logging { infoTitle = t("Persistence!") + " " + t("Not so much left"); } else if (percent > 80 && percent < 100) { infoTitle = t("Almost!") + " " + t("You have only 1-2 exercise left to finish!"); + } else { + infoTitle = t("Congratulation!"); + infoText2 = t("You have achieved to first 100% test-round!"); + infoText3 = t("Now you unlocked: Development By Muscles and the Suggested Trainings Plan"); } menuTreeRepository.sortByMuscleType(); diff --git a/lib/main.dart b/lib/main.dart index f7e42d8..5acb312 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:aitrainer_app/bloc/sales/sales_bloc.dart'; import 'package:aitrainer_app/push_notifications.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; +import 'package:aitrainer_app/service/firebase_api.dart'; import 'package:aitrainer_app/util/session.dart'; import 'package:aitrainer_app/view/account.dart'; import 'package:aitrainer_app/view/custom_exercise_page.dart'; @@ -117,6 +118,9 @@ Future main() async { // - https://www.dartlang.org/articles/libraries/zones runZonedGuarded>(() async { final WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository(); + WidgetsFlutterBinding.ensureInitialized(); + print(" -- FireBase init.."); + await FirebaseApi().initializeFlutterFire(); runApp(MultiBlocProvider( providers: [ BlocProvider( diff --git a/lib/model/cache.dart b/lib/model/cache.dart index 493aaa6..310bdef 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -424,11 +424,11 @@ class Cache with Logging { await CustomerApi().getCustomer(customerId); Cache().startPage = "home"; Flurry.setUserId(customerId.toString()); + final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); + Cache().setCustomerDevices(customerDevices); await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); await ExerciseDeviceApi().getDevices(); - final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); - Cache().setCustomerDevices(customerDevices); ExerciseRepository exerciseRepository = ExerciseRepository(); await exerciseRepository.getExercisesByCustomer(customerId); diff --git a/lib/service/customer_exercise_device_service.dart b/lib/service/customer_exercise_device_service.dart index d08a84a..71022be 100644 --- a/lib/service/customer_exercise_device_service.dart +++ b/lib/service/customer_exercise_device_service.dart @@ -11,6 +11,7 @@ class CustomerExerciseDeviceApi with Logging { Future> getDevices(int customerId) async { List devices; try { + log(" --- get customer_exercise_devices: "); final body = await _client.get("customer_exercise_device/customer/" + customerId.toString(), ""); final Iterable json = jsonDecode(body); devices = json.map((device) => CustomerExerciseDevice.fromJson(device)).toList(); diff --git a/lib/service/purchase.dart b/lib/service/purchase.dart index c805a44..594947a 100644 --- a/lib/service/purchase.dart +++ b/lib/service/purchase.dart @@ -1,6 +1,7 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/purchase.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/not_found_exception.dart'; import 'dart:convert'; import 'api.dart'; @@ -8,10 +9,15 @@ class PurchaseApi with Logging { final APIClient _client = new APIClient(); Future> getPurchasesByCustomer(int customerId) async { - final body = await _client.get("purchase/customer/" + customerId.toString(), ""); - final Iterable json = jsonDecode(body); - final List purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList(); - Cache().setPurchases(purchases); + List purchases = List(); + try { + final body = await _client.get("purchase/customer/" + customerId.toString(), ""); + final Iterable json = jsonDecode(body); + final List purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList(); + Cache().setPurchases(purchases); + } on NotFoundException catch (e) { + log("No purchases found"); + } return purchases; } diff --git a/lib/util/session.dart b/lib/util/session.dart index b6995e0..1edd1fe 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -1,13 +1,11 @@ import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/service/api.dart'; -import 'package:aitrainer_app/service/firebase_api.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/product_service.dart'; import 'package:aitrainer_app/service/property_service.dart'; import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/services.dart'; -import 'package:mockito/mockito.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/cache.dart'; @@ -28,8 +26,6 @@ class Session with Logging { Cache().setServerAddress(_sharedPreferences); Cache().getHardware(_sharedPreferences); await _fetchToken(_sharedPreferences); - log(" -- FireBase init.."); - await FirebaseApi().initializeFlutterFire(); //initDeviceLocale(); // Create the initialization Future outside of `build`: diff --git a/lib/view/exercise_execute_page.dart b/lib/view/exercise_execute_page.dart index 2d6f4b1..82d80e0 100644 --- a/lib/view/exercise_execute_page.dart +++ b/lib/view/exercise_execute_page.dart @@ -7,7 +7,6 @@ import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; -import 'package:aitrainer_app/widgets/splash.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -155,7 +154,7 @@ class _ExerciseExecutePage extends State with Trans { child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [ IconButton( icon: element.executed - ? Icon(Icons.check_box, color: Colors.green) + ? Icon(Icons.check_box, color: Colors.green[200]) : Icon( Icons.indeterminate_check_box, color: Colors.blue.shade800, diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index afb08d0..27803b7 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -79,6 +79,7 @@ class _ExerciseExecuteAddPage extends State with Tra padding: const EdgeInsets.only(top: 25, left: 25, right: 25), child: SingleChildScrollView( scrollDirection: Axis.vertical, + physics: BouncingScrollPhysics(), controller: ScrollController( initialScrollOffset: exerciseBloc.scrollOffset, ), diff --git a/lib/view/exercise_log_page.dart b/lib/view/exercise_log_page.dart index eb96053..faa91c4 100644 --- a/lib/view/exercise_log_page.dart +++ b/lib/view/exercise_log_page.dart @@ -239,10 +239,12 @@ class _ExerciseLogPage extends State with Trans, Common { context: context, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.", - text: "OK", + unlocked: true, + unlockRound: 1, + unlockedText: t("Enjoy also this premium fetaure to show all old evaluation data of your successful exercises."), + function: "My Exercise Logs", + onTap: () => {Navigator.of(context).pop()}, + onCancel: () => {Navigator.of(context).pop()}, ); }); } @@ -255,6 +257,8 @@ class _ExerciseLogPage extends State with Trans, Common { ? "on the " + DateFormat(DateFormat.YEAR_MONTH_DAY, AppLanguage().appLocal.toString()).format(exercise.dateAdd.toUtc()) : DateFormat(DateFormat.YEAR_MONTH_DAY, AppLanguage().appLocal.toString()).format(exercise.dateAdd.toUtc()) + "-n"; + final String unitQuantity = exercise.unitQuantity == null ? "" : "x" + exercise.unitQuantity.toStringAsFixed(0); + showCupertinoDialog( useRootNavigator: true, context: context, @@ -268,7 +272,7 @@ class _ExerciseLogPage extends State with Trans, Common { style: (TextStyle(color: Colors.blue)), ), Text( - exercise.quantity.toStringAsFixed(0) + "x" + exercise.unitQuantity.toStringAsFixed(0) + " ", + exercise.quantity.toStringAsFixed(0) + unitQuantity + " ", //+ //exerciseType.unitQuantityUnit == null // ? "" diff --git a/lib/view/gdpr.dart b/lib/view/gdpr.dart index 3e005d9..4d9f5bd 100644 --- a/lib/view/gdpr.dart +++ b/lib/view/gdpr.dart @@ -1,4 +1,5 @@ import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -6,17 +7,19 @@ class Gdpr extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + appBar: AppBarMin( + back: true, + ), body: Container( padding: const EdgeInsets.only(left: 15, right: 15), child: ListView( children: [ - new InkWell( - child: new Text( + InkWell( + child: Text( AppLocalizations.of(context).translate('gdpr_text'), ), - customBorder: Border.all(color: Colors.teal, width: 1), + customBorder: Border.all(color: Colors.orange, width: 1), ), - Spacer(flex: 2), ], ))); } diff --git a/lib/view/mydevelopment_body_page.dart b/lib/view/mydevelopment_body_page.dart index 7aadbbb..8786295 100644 --- a/lib/view/mydevelopment_body_page.dart +++ b/lib/view/mydevelopment_body_page.dart @@ -33,11 +33,12 @@ class _MyDevelopmentBodyPage extends State with Trans, Co context: context, barrierDismissible: false, builder: (BuildContext context) { + setContext(context); return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Body Development feature is reachable if you finished the second 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 2, + function: "My Whole Body Development", + unlockedText: "", onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, ); diff --git a/lib/view/mydevelopment_muscle_page.dart b/lib/view/mydevelopment_muscle_page.dart index 22a7945..03668ee 100644 --- a/lib/view/mydevelopment_muscle_page.dart +++ b/lib/view/mydevelopment_muscle_page.dart @@ -38,10 +38,10 @@ class _MyDevelopmentMuscleState extends State with Comm barrierDismissible: false, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Muscle Development feature is reachable if you finished the first 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 1, + function: "Development Of Muscles", + unlockedText: "", onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, ); diff --git a/lib/view/mydevelopment_page.dart b/lib/view/mydevelopment_page.dart index 1491375..5db7fbd 100644 --- a/lib/view/mydevelopment_page.dart +++ b/lib/view/mydevelopment_page.dart @@ -107,12 +107,11 @@ class _MyDevelopmentPage extends State with Trans { context: context, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Predictions feature is reachable if you finished the second 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 2, + function: "Predictions", + unlockedText: "", onTap: () => {Navigator.of(context).pop()}, - onCancel: () => {Navigator.of(context).pop()}, ); }) }, diff --git a/lib/view/myexcercise_plan_page.dart b/lib/view/myexcercise_plan_page.dart index c6d6bad..7f1982d 100644 --- a/lib/view/myexcercise_plan_page.dart +++ b/lib/view/myexcercise_plan_page.dart @@ -95,10 +95,10 @@ class _MyExercisePlanPage extends State with Trans, Logging context: context, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Suggested Training Plan is reachable if you finished the first 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 1, + function: "Suggested Training Plan", + unlockedText: "", onTap: () => {Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop()}, ); @@ -123,10 +123,10 @@ class _MyExercisePlanPage extends State with Trans, Logging context: context, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Special Plan is reachable if you finished the first 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 1, + function: "My Special Plan", + unlockedText: "", onTap: () => {Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop()}, ); @@ -151,10 +151,10 @@ class _MyExercisePlanPage extends State with Trans, Logging context: context, builder: (BuildContext context) { return DialogPremium( - title: "Go Premium", - descriptions: "Unleash your potential with WorkoutTest Premium!", - description2: "The Star's Exericise Plan is reachable if you finished the second 100% test-circles", - text: "OK", + unlocked: false, + unlockRound: 2, + function: "Star's Exercise Plan", + unlockedText: "", onTap: () => {Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop()}, ); diff --git a/lib/view/sales_page.dart b/lib/view/sales_page.dart index 5a56dd7..c8e7c19 100644 --- a/lib/view/sales_page.dart +++ b/lib/view/sales_page.dart @@ -84,50 +84,7 @@ class SalesPage extends StatelessWidget with Trans { ), ])), SliverGrid( - delegate: SliverChildListDelegate(getButtons(bloc) - /* [ - SalesButton( - title: "Annual", - price: "9970 Ft / év", - desc1: "Development programs", - desc2: "Suggestions based on your actual status", - desc3: "Special customized training plans", - descStyle: GoogleFonts.inter(fontSize: 10, color: Colors.blue[800]), - badgeText: "2 months free", - badgeColor: Colors.orange, - style: GoogleFonts.archivoBlack(fontSize: 14, color: Colors.blue[800]), - onTap: () { - print("1"); - //bloc.sessionBloc.add(event) - }, - ), - SalesButton( - title: "Annual", - price: "10970 Ft / év", - desc1: "Development programs", - desc2: "Suggestions based on your actual status", - desc3: "Special customized training plans", - desc4: "AI driven predictions", - descStyle: GoogleFonts.inter(fontSize: 10, color: Colors.blue[800]), - badgeText: "one month free", - badgeColor: Colors.orange, - style: GoogleFonts.archivoBlack(fontSize: 14, color: Colors.blue[800]), - onTap: () => {print("2")}, - ), - SalesButton( - title: "Monthly", - price: "970 Ft / hó", - desc1: "Development programs", - desc2: "Suggestions based on your actual status", - desc3: "Special customized training plans", - desc4: "AI driven predictions", - descStyle: GoogleFonts.inter(fontSize: 10, color: Colors.blue[800]), - badgeColor: Colors.transparent, - style: GoogleFonts.archivoBlack(fontSize: 14, color: Colors.blue[800]), - onTap: () => {print("3")}, - ), - ] */ - ), + delegate: SliverChildListDelegate(getButtons(bloc)), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 10.0, diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index 8294cf0..b32baae 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -1,5 +1,6 @@ import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:badges/badges.dart'; import 'package:flurry/flurry.dart'; @@ -17,7 +18,7 @@ class BottomNavigator extends StatefulWidget { _NawDrawerWidget createState() => _NawDrawerWidget(); } -class _NawDrawerWidget extends State with Trans { +class _NawDrawerWidget extends State with Trans, Logging { @override void initState() { super.initState(); diff --git a/lib/widgets/dialog_common.dart b/lib/widgets/dialog_common.dart new file mode 100644 index 0000000..45dc8cd --- /dev/null +++ b/lib/widgets/dialog_common.dart @@ -0,0 +1,176 @@ +import 'package:aitrainer_app/util/trans.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +// ignore: must_be_immutable +class DialogCommon extends StatefulWidget { + final String title, descriptions, text; + final VoidCallback onTap; + final VoidCallback onCancel; + String description2; + final Image img; + + DialogCommon({Key key, this.title, this.descriptions, this.description2, this.text, this.img, this.onTap, this.onCancel}) + : super(key: key) { + description2 = description2 ?? ""; + } + + @override + _DialogPremiumState createState() { + return _DialogPremiumState(); + } +} + +class _DialogPremiumState extends State with Trans { + bool isStart = true; + @override + Widget build(BuildContext context) { + setContext(context); + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(31), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Stack(alignment: AlignmentDirectional.topStart, children: [ + Stack( + children: [ + Container( + padding: EdgeInsets.only(left: 20, top: 24, right: 20, bottom: 30), + margin: EdgeInsets.only(top: 30), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], + image: DecorationImage( + image: AssetImage('asset/image/WT_black_G_background.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 5, + ), + Stack( + alignment: AlignmentDirectional.topEnd, + children: [ + Text( + widget.title + " ", + style: GoogleFonts.archivoBlack( + fontSize: 18, + color: Colors.yellow[400], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 35, + ), + Text( + widget.descriptions, + style: GoogleFonts.inter( + fontSize: 14, + color: Colors.white, + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 15, + ), + Text( + widget.description2, + style: GoogleFonts.inter( + fontSize: 14, + color: Colors.white, + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 62, + ), + Align( + alignment: Alignment.center, + child: GestureDetector( + onTap: widget.onTap ?? widget.onTap, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45), + Text( + t("OK"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + ))), + ], + ), + ), + ], + ), + GestureDetector( + onTap: () { + if (widget.onCancel == null) { + Navigator.of(context).pop(); + } else { + widget.onCancel(); + } + }, + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 28, + child: Text( + "X", + style: GoogleFonts.archivoBlack(fontSize: 32, color: Colors.white54), + ), + )), + ]); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/widgets/dialog_premium.dart b/lib/widgets/dialog_premium.dart index b83956d..951e3f4 100644 --- a/lib/widgets/dialog_premium.dart +++ b/lib/widgets/dialog_premium.dart @@ -7,15 +7,26 @@ import 'package:google_fonts/google_fonts.dart'; // ignore: must_be_immutable class DialogPremium extends StatefulWidget { - final String title, descriptions, text; final VoidCallback onTap; final VoidCallback onCancel; - String description2; - final Image img; + String description, function, unlockedText; + final int unlockRound; - DialogPremium({Key key, this.title, this.descriptions, this.description2, this.text, this.img, this.onTap, this.onCancel}) + final bool unlocked; + + DialogPremium( + {Key key, + @required this.unlockRound, + this.description, + this.onTap, + this.onCancel, + @required this.unlocked, + this.unlockedText, + @required this.function}) : super(key: key) { - description2 = description2 ?? ""; + description = description ?? ""; + function = function ?? ""; + unlockedText = unlockedText ?? ""; } @override @@ -77,7 +88,7 @@ class _DialogPremiumState extends State with Trans { alignment: AlignmentDirectional.topEnd, children: [ Text( - widget.title + " ", + t("Go Premium") + " ", style: GoogleFonts.archivoBlack( fontSize: 24, color: Colors.yellow[400], @@ -120,7 +131,7 @@ class _DialogPremiumState extends State with Trans { height: 35, ), Text( - widget.descriptions, + t("Unleash your potential with WorkoutTest Premium!"), style: GoogleFonts.inter( fontSize: 14, color: Colors.white, @@ -142,26 +153,7 @@ class _DialogPremiumState extends State with Trans { SizedBox( height: 15, ), - Text( - widget.description2, - style: GoogleFonts.inter( - fontSize: 14, - color: Colors.white, - shadows: [ - Shadow( - offset: Offset(5.0, 5.0), - blurRadius: 12.0, - color: Colors.black54, - ), - Shadow( - offset: Offset(-3.0, 3.0), - blurRadius: 12.0, - color: Colors.black54, - ), - ], - ), - textAlign: TextAlign.center, - ), + getDescription(), SizedBox( height: 62, ), @@ -185,7 +177,13 @@ class _DialogPremiumState extends State with Trans { ], ), GestureDetector( - onTap: () => widget.onCancel == null ? Navigator.of(context).pop() : widget.onCancel, + onTap: () { + if (widget.onCancel == null) { + Navigator.of(context).pop(); + } else { + widget.onCancel(); + } + }, child: CircleAvatar( backgroundColor: Colors.transparent, radius: 28, @@ -197,6 +195,92 @@ class _DialogPremiumState extends State with Trans { ]); } + RichText getDescription() { + return RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.white, + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + children: getDescriptionText())); + } + + List getDescriptionText() { + List list = List(); + + if (widget.unlocked) { + list.add(TextSpan(text: widget.unlockedText)); + } else { + list.add(TextSpan(text: t("The"))); + list.add(TextSpan(text: t(" "))); + list.add( + TextSpan( + text: t(widget.function), + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + ), + ); + list.add(TextSpan(text: t(" "))); + list.add(TextSpan(text: t("feature is reachable after you finished"))); + list.add(TextSpan(text: t(" "))); + list.add( + TextSpan( + text: widget.unlockRound == 1 ? t("the first") : t("the second"), + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + ), + ); + list.add(TextSpan(text: t(" "))); + list.add(TextSpan(text: t("100% test circles"))); + } + + return list; + } + @override void dispose() { _timer.cancel(); diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index 14e4566..69d98f9 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -1,11 +1,15 @@ +import 'dart:async'; import 'dart:ui'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; +import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; +import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/dialog_common.dart'; import 'package:badges/badges.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -16,13 +20,41 @@ import 'package:google_fonts/google_fonts.dart'; import 'menu_info_widget.dart'; // ignore: must_be_immutable -class MenuPageWidget extends StatelessWidget with Trans { +class MenuPageWidget extends StatefulWidget { int parent; - final double baseWidth = 312; - final double baseHeight = 675.2; MenuPageWidget({this.parent}); + @override + _MenuPageWidgetState createState() => _MenuPageWidgetState(); +} + +class _MenuPageWidgetState extends State with Trans, Logging { + final double baseWidth = 312; + final double baseHeight = 675.2; + bool isFirst = true; + bool wait = false; + Timer _timer, _waitTimer; + + @override + void initState() { + isFirst = true; + _timer = Timer.periodic( + Duration(milliseconds: 800), + (Timer timer) => setState(() { + if (!wait) { + isFirst = !isFirst; + //wait = true; + } + })); + _waitTimer = Timer.periodic( + Duration(milliseconds: 5000), + (Timer timer) => setState(() { + wait = !wait; + })); + super.initState(); + } + @override Widget build(BuildContext context) { MenuBloc menuBloc = BlocProvider.of(context); @@ -30,7 +62,7 @@ class MenuPageWidget extends StatelessWidget with Trans { double cWidth = MediaQuery.of(context).size.width; double cHeight = MediaQuery.of(context).size.height; - return CustomScrollView(scrollDirection: Axis.vertical, slivers: buildMenuColumn(parent, context, menuBloc, cWidth, cHeight)); + return CustomScrollView(scrollDirection: Axis.vertical, slivers: buildMenuColumn(widget.parent, context, menuBloc, cWidth, cHeight)); } List buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc, double cWidth, double cHeight) { @@ -170,7 +202,56 @@ class MenuPageWidget extends StatelessWidget with Trans { return sliverList; } - SliverGrid getInfoWidget(BuildContext context, MenuBloc menuBloc) { + SliverList getInfoWidget(BuildContext context, MenuBloc menuBloc) { + List widgets = List(); + + if (context != null) { + menuBloc.setContext(context); + menuBloc.setMenuInfo(); + widgets.add(SizedBox( + height: 10, + )); + + widgets.add( + GestureDetector( + onTap: () => { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return DialogCommon( + title: menuBloc.infoTitle, + descriptions: menuBloc.infoText2, + description2: menuBloc.infoText3, + text: "OK", + onTap: () => {Navigator.of(context).pop()}, + onCancel: () => {Navigator.of(context).pop()}, + ); + }) + }, + child: Align( + alignment: Alignment.center, + child: SizedBox( + height: 35, + child: AnimatedSwitcher( + duration: Duration(milliseconds: 800), + transitionBuilder: (Widget child, Animation animation) { + return ScaleTransition(child: child, scale: animation); + }, + child: isFirst && !wait + ? Icon( + CustomIcon.question_circle, + color: Colors.yellow[300], + size: 40, + ) + : Offstage())))), + ); + } + SliverList sliverList = SliverList(delegate: SliverChildListDelegate(widgets)); + return sliverList; + } + + SliverGrid getInfoWidget2(BuildContext context, MenuBloc menuBloc) { final List _columnChildren = List(); if (context != null) { menuBloc.setContext(context); @@ -281,4 +362,11 @@ class MenuPageWidget extends StatelessWidget with Trans { child: _getButtonImage(workoutMenuTree, cWidth, cHeight), ); } + + @override + void dispose() { + _timer.cancel(); + _waitTimer.cancel(); + super.dispose(); + } }