diff --git a/assets/fonts/Marhey-Bold.ttf b/assets/fonts/Marhey-Bold.ttf new file mode 100644 index 0000000..eb375d3 Binary files /dev/null and b/assets/fonts/Marhey-Bold.ttf differ diff --git a/assets/fonts/Marhey-Light.ttf b/assets/fonts/Marhey-Light.ttf new file mode 100644 index 0000000..edb49bd Binary files /dev/null and b/assets/fonts/Marhey-Light.ttf differ diff --git a/assets/fonts/Marhey-Medium.ttf b/assets/fonts/Marhey-Medium.ttf new file mode 100644 index 0000000..1a5b780 Binary files /dev/null and b/assets/fonts/Marhey-Medium.ttf differ diff --git a/assets/fonts/Marhey-Regular.ttf b/assets/fonts/Marhey-Regular.ttf new file mode 100644 index 0000000..6ac4483 Binary files /dev/null and b/assets/fonts/Marhey-Regular.ttf differ diff --git a/assets/fonts/Marhey-SemiBold.ttf b/assets/fonts/Marhey-SemiBold.ttf new file mode 100644 index 0000000..00ac38b Binary files /dev/null and b/assets/fonts/Marhey-SemiBold.ttf differ diff --git a/assets/json/levels.json b/assets/json/levels.json deleted file mode 100644 index dcaa6fa..0000000 --- a/assets/json/levels.json +++ /dev/null @@ -1,1181 +0,0 @@ -{ - "result": [ - { - "id": 34, - "order": 1, - "title": "Tooth Brushing Etiquette", - "questions": [ - { - "id": 301, - "title": "Hadi wants her teeth to be clean. Which of her actions do you think is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_UXndIM5.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1192, - "title": "We carefully clean our teeth with a toothbrush", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_iNZMIEt.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1193, - "title": "We walk in the yard with a glass of juice", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_82OrRAN.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1194, - "title": "We eat candy and watch TV", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "hadihoda_user_l7cRKyg.png", - "size": 111332, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1195, - "title": "Take it and throw it away without saying anything", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_w0EyoOQ.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 302, - "title": "What is the best time to brush teeth?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_HXTTczp.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1196, - "title": "Morning after waking up and night before sleeping", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer2_F42cGzw.png", - "size": 346421, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1197, - "title": "Only when we have toothache", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_rzFgkLQ.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1198, - "title": "Only on weekends", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_4bPWCnw.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1199, - "title": "When mom says", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_0fLITwd.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 303, - "title": "How many times a day should Hadi brush her teeth?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_tELeghD.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1200, - "title": "Twice a day", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_KETj6i3.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1201, - "title": "Once a day", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_9VovGd0.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1202, - "title": "Three times a day", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_Dt5fAsU.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1203, - "title": "Only when she remembers", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_o9la4sD.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - }, - { - "id": 35, - "order": 2, - "title": "Eating Etiquette", - "questions": [ - { - "id": 311, - "title": "Hadi wants to eat. Which of her actions is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_Xtv5lSc.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1232, - "title": "She washes her hands before eating", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_C2dAmzG.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1233, - "title": "She eats with dirty hands", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_4oYaj60.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1234, - "title": "She spills food on the ground", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer1_MV4vliK.png", - "size": 320543, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1235, - "title": "She eats with her mouth open", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_Bh6JUWv.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 312, - "title": "What should Hadi say when eating?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_KqNhyXy.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1236, - "title": "Bismillah", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_WnLLPk0.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1237, - "title": "Hello", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_BfJLxDD.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1238, - "title": "Goodbye", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "hadihoda_user_NFZvYz4.png", - "size": 111332, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1239, - "title": "Nothing", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_4pnLURZ.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 313, - "title": "How should Hadi eat?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_yskYwgR.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1240, - "title": "Slowly and calmly", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_gCLGHBG.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1241, - "title": "Very quickly", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_9A6rnMB.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1242, - "title": "Loudly", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_19p9V2Z.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1243, - "title": "While running", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_JzbIvAs.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - }, - { - "id": 36, - "order": 3, - "title": "Sleeping Etiquette", - "questions": [ - { - "id": 321, - "title": "Hadi wants to sleep. Which of her actions is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_j9BlKTe.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1272, - "title": "She washes her hands before sleeping", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer2_nwvb7rC.png", - "size": 346421, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1273, - "title": "She sleeps in dirty clothes", - "image_id": "c290649fdb", - "image_info": { - "filename": "hadihoda_user_bvNH1AC.png", - "size": 111332, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1274, - "title": "She sleeps with shoes on", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_JVVfxGq.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1275, - "title": "She sleeps on the ground", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_rAKoU3L.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 322, - "title": "What should Hadi say before sleeping?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_TEW4rrP.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1276, - "title": "Bismillah and bedtime prayer", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_kxxcuBs.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1277, - "title": "Hello", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_dA1hKmO.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1278, - "title": "Goodbye", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_mOYRhA8.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1279, - "title": "Nothing", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_6cc7bff.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 323, - "title": "What time should Hadi sleep?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_qOceSmr.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1280, - "title": "Regular and early time", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_f54wbXf.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1281, - "title": "Whenever she likes", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_m040LzQ.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1282, - "title": "Midnight", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_uqP0F9g.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1283, - "title": "Morning", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_cBWZXnR.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - }, - { - "id": 37, - "order": 4, - "title": "Dressing Etiquette", - "questions": [ - { - "id": 331, - "title": "Hadi wants to get dressed. Which of her actions is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_ybeoTaj.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1312, - "title": "She wears clean and neat clothes", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer2_A84bsAn.png", - "size": 346421, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1313, - "title": "She wears dirty clothes", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_QM5Wdvi.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1314, - "title": "She wears torn clothes", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_tXODAh2.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1315, - "title": "She doesn't wear any clothes", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer2_whh6588.png", - "size": 346421, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 332, - "title": "What type of clothes should Hadi wear?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_Ykj79Vo.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1316, - "title": "Comfortable and appropriate clothes", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_yPRbPmr.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1317, - "title": "Tight and uncomfortable clothes", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_uRVCkPW.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1318, - "title": "Big and loose clothes", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_CkVrLZ9.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1319, - "title": "Any clothes she likes", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_rAxXEPl.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 333, - "title": "What should Hadi do before getting dressed?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_Vis5bMe.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1320, - "title": "Wash her hands", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_AogGpyQ.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1321, - "title": "Play", - "image_id": "c290649fdb", - "image_info": { - "filename": "hadihoda_user_kpAKrmx.png", - "size": 111332, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1322, - "title": "Eat food", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer1_sLLo3y5.png", - "size": 320543, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1323, - "title": "Do nothing", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer2_K4AErHQ.png", - "size": 346421, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - }, - { - "id": 38, - "order": 5, - "title": "Personal Hygiene", - "questions": [ - { - "id": 341, - "title": "Hadi wants to be clean. Which of her actions is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_ZdQd0iI.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1352, - "title": "Take a bath every day", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_XhWZzwT.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1353, - "title": "Take a bath once a week", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_nImB8qj.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1354, - "title": "Take a bath once a month", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer1_kondYqe.png", - "size": 320543, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1355, - "title": "Never take a bath", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer1_m39DWKt.png", - "size": 320543, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 342, - "title": "How many times a day should Hadi wash her hands?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_59q7VNM.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1356, - "title": "Several times", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_ie6o3M4.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1357, - "title": "Once", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_y1cBc6f.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1358, - "title": "Never", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer1_NoFjFsV.png", - "size": 320543, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1359, - "title": "Only when dirty", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_pdWCd5x.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 343, - "title": "What should Hadi do after using the toilet?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_hg7QbGt.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1360, - "title": "Wash her hands with soap", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_Q128oR0.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1361, - "title": "Do nothing", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_XXPgA9y.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1362, - "title": "Just rinse with water", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "answer2_ppNdIEg.png", - "size": 346421, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1363, - "title": "Wipe her hands", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_7OqltRo.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - }, - { - "id": 39, - "order": 6, - "title": "Playing Etiquette", - "questions": [ - { - "id": 351, - "title": "Hadi wants her teeth to be clean. Which of her actions do you think is correct?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_Ckvo4Qh.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 1, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1392, - "title": "We carefully clean our teeth with a toothbrush", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_bqavfEH.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1393, - "title": "We walk in the yard with a glass of juice", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer1_kqoMwPH.png", - "size": 320543, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1394, - "title": "We eat candy and watch TV", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "hadihoda_user_8L5eRRO.png", - "size": 111332, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1395, - "title": "Take it and throw it away without saying anything", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer2_1gNQBhl.png", - "size": 346421, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 352, - "title": "What is the best time to brush teeth?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_3f98P2I.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 2, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1396, - "title": "Morning after waking up and night before sleeping", - "image_id": "af38813ccc", - "image_info": { - "filename": "hadihoda_user_on4hHkq.png", - "size": 111332, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1397, - "title": "Only when we have toothache", - "image_id": "c290649fdb", - "image_info": { - "filename": "answer2_W5wOqId.png", - "size": 346421, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1398, - "title": "Only on weekends", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "hadihoda_user_AnvL0XG.png", - "size": 111332, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1399, - "title": "When mom says", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "hadihoda_user_iJ1D06B.png", - "size": 111332, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - }, - { - "id": 353, - "title": "How many times a day should Hadi brush her teeth?", - "audio_id": "57fbe036af", - "audio_info": { - "filename": "01_atom_music_audio_-_cheeky_con_lXm4PaK.mp3", - "size": 2418892, - "extension": ".mp3" - }, - "order": 3, - "correct_answer": 1, - "is_active": true, - "answers": [ - { - "id": 1400, - "title": "Twice a day", - "image_id": "af38813ccc", - "image_info": { - "filename": "answer1_YcFpeE7.png", - "size": 320543, - "extension": ".png" - }, - "order": 1, - "is_active": true - }, - { - "id": 1401, - "title": "Once a day", - "image_id": "c290649fdb", - "image_info": { - "filename": "hadihoda_user_MxMcK1o.png", - "size": 111332, - "extension": ".png" - }, - "order": 2, - "is_active": true - }, - { - "id": 1402, - "title": "Three times a day", - "image_id": "d5d36b44e7", - "image_info": { - "filename": "hadihoda_user_2IPJQ7e.png", - "size": 111332, - "extension": ".png" - }, - "order": 3, - "is_active": true - }, - { - "id": 1403, - "title": "Only when she remembers", - "image_id": "f9f0bad05f", - "image_info": { - "filename": "answer2_EpzvwMB.png", - "size": 346421, - "extension": ".png" - }, - "order": 4, - "is_active": true - } - ] - } - ] - } - ] -} - diff --git a/lib/common_ui/resources/my_text_style.dart b/lib/common_ui/resources/my_text_style.dart index 5acd64d..de47e8f 100644 --- a/lib/common_ui/resources/my_text_style.dart +++ b/lib/common_ui/resources/my_text_style.dart @@ -1,28 +1,70 @@ import 'package:flutter/material.dart'; -class MyTextStyle { - static const MyTextStyle _i = MyTextStyle._internal(); - const MyTextStyle._internal(); - factory MyTextStyle() => _i; +class DinoKids { + static const DinoKids _i = DinoKids._internal(); + const DinoKids._internal(); + factory DinoKids() => _i; static const String fontFamily = 'dinokids'; - static const TextStyle normal26 = TextStyle( - fontFamily: fontFamily, - fontSize: 26, - fontWeight: FontWeight.w400, - shadows: [ - Shadow( - color: Color(0XFF5B5B5B), - blurRadius: 2.86, - offset: Offset(0, 2), - ), - ] - ); - - static const TextStyle normal17 = TextStyle( - fontFamily: fontFamily, - fontSize: 17, - fontWeight: FontWeight.w400, + /// Regular + static const TextStyle regular17 = TextStyle( + fontFamily: fontFamily, + fontSize: 17, + fontWeight: FontWeight.w400, + ); + static const TextStyle regular26 = TextStyle( + fontFamily: fontFamily, + fontSize: 26, + fontWeight: FontWeight.w400, + ); +} + +class Marhey { + static const Marhey _i = Marhey._internal(); + const Marhey._internal(); + factory Marhey() => _i; + + static const String fontFamily = 'marhey'; + + /// Medium + static const TextStyle medium12 = TextStyle( + fontFamily: fontFamily, + fontSize: 12, + fontWeight: FontWeight.w500, + ); + static const TextStyle medium16 = TextStyle( + fontFamily: fontFamily, + fontSize: 16, + fontWeight: FontWeight.w500, + ); + + /// Semi Bold + static const TextStyle semiBold17 = TextStyle( + fontFamily: fontFamily, + fontSize: 17, + fontWeight: FontWeight.w600, + ); + static const TextStyle semiBold18 = TextStyle( + fontFamily: fontFamily, + fontSize: 18, + fontWeight: FontWeight.w600, + ); + static const TextStyle semiBold22 = TextStyle( + fontFamily: fontFamily, + fontSize: 22, + fontWeight: FontWeight.w600, + ); + + /// Bold + static const TextStyle bold12 = TextStyle( + fontFamily: fontFamily, + fontSize: 12, + fontWeight: FontWeight.w700, + ); + static const TextStyle bold14 = TextStyle( + fontFamily: fontFamily, + fontSize: 14, + fontWeight: FontWeight.w700, ); } diff --git a/lib/core/constants/my_api.dart b/lib/core/constants/my_api.dart index b1ba034..dd59e1f 100644 --- a/lib/core/constants/my_api.dart +++ b/lib/core/constants/my_api.dart @@ -6,6 +6,10 @@ class MyApi { static const Duration timeOut = Duration(seconds: 30); static const String contentType = 'application/json'; static const String defaultError = 'An unexpected error has occurred.'; + static const String noInternetError = 'Please check your internet connection.'; - static const String baseUrl = 'https://api.BASE_URL.com'; + static const String baseUrl = 'https://hadihoda.newhorizonco.uk/api'; + + static const String levels = '/quiz/optimized/levels/'; + static const String files = '/quiz/optimized/download-all-files/'; } diff --git a/lib/core/constants/my_constants.dart b/lib/core/constants/my_constants.dart index c6e11bb..7772e42 100644 --- a/lib/core/constants/my_constants.dart +++ b/lib/core/constants/my_constants.dart @@ -6,4 +6,6 @@ class MyConstants { static const String token = 'TOKEN'; static const String theme = 'THEME'; static const String levelBox = 'LEVEL_BOX'; + static const String downloadCompleted = 'DOWNLOAD_COMPLETED'; + static const String extractCompleted = 'EXTRACT_COMPLETED'; } \ No newline at end of file diff --git a/lib/core/error_handler/error_handler.dart b/lib/core/error_handler/error_handler.dart index ac586c1..8fbe09d 100644 --- a/lib/core/error_handler/error_handler.dart +++ b/lib/core/error_handler/error_handler.dart @@ -10,7 +10,7 @@ class ErrorHandler { static void handleError(DioException e) { if (e.response == null) { throw MyException( - errorMessage: e.message ?? MyApi.defaultError, + errorMessage: MyApi.noInternetError, statusCode: e.response?.statusCode, ); } else { diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart index f16e532..e7781c5 100644 --- a/lib/core/routers/my_routes.dart +++ b/lib/core/routers/my_routes.dart @@ -32,7 +32,7 @@ GoRouter get appPages => GoRouter( name: Routes.introPage, path: Routes.introPage, builder: (context, state) => BlocProvider( - create: (context) => IntroBloc(locator(), locator(), locator()), + create: (context) => IntroBloc(locator(), locator()), child: const IntroPage(), ), ), diff --git a/lib/core/utils/local_storage.dart b/lib/core/utils/local_storage.dart index baa5e7c..b44e69b 100644 --- a/lib/core/utils/local_storage.dart +++ b/lib/core/utils/local_storage.dart @@ -11,7 +11,7 @@ class LocalStorage { _box = await SharedPreferences.getInstance(); } - static Future saveData({required String key, required dynamic value}) async { + static Future saveData({required String key, required String value}) async { await _box.setString(key, value); } diff --git a/lib/core/utils/storage_path.dart b/lib/core/utils/storage_path.dart index 4ecde62..56a6746 100644 --- a/lib/core/utils/storage_path.dart +++ b/lib/core/utils/storage_path.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:path_provider/path_provider.dart'; class StoragePath { - static Directory applicationDir = Directory(''); + static Directory documentDir = Directory(''); - static Future getApplicationDir() async { - applicationDir = await getApplicationDocumentsDirectory(); + static Future getDocumentDir() async { + documentDir = await getApplicationDocumentsDirectory(); } } \ No newline at end of file diff --git a/lib/core/widgets/about_us_dialog/about_us_dialog.dart b/lib/core/widgets/about_us_dialog/about_us_dialog.dart index 55f5c6e..0817498 100644 --- a/lib/core/widgets/about_us_dialog/about_us_dialog.dart +++ b/lib/core/widgets/about_us_dialog/about_us_dialog.dart @@ -2,8 +2,8 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/check_platform.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; @@ -46,26 +46,14 @@ class AboutUsDialog extends StatelessWidget { children: [ Text( context.translate.about_us, - style: GoogleFonts.marhey( + style: Marhey.semiBold22.copyWith( color: Color(0XFF322386), - fontSize: checkSize( - context: context, - mobile: 22, - tablet: 30, - ), - fontWeight: FontWeight.w600, ), ), Text( context.translate.about_us_desc, - style: GoogleFonts.marhey( + style: Marhey.medium16.copyWith( color: Color(0XFF494178), - fontSize: checkSize( - context: context, - mobile: 16, - tablet: 21, - ), - fontWeight: FontWeight.w500, ), ), MyImage( diff --git a/lib/core/widgets/answer_box/answer_box.dart b/lib/core/widgets/answer_box/answer_box.dart index 5005146..7038487 100644 --- a/lib/core/widgets/answer_box/answer_box.dart +++ b/lib/core/widgets/answer_box/answer_box.dart @@ -3,7 +3,6 @@ import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/picture_box.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/text_box.dart'; import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; -import 'package:path_provider/path_provider.dart'; class AnswerBox extends StatelessWidget { const AnswerBox({super.key, required this.answer,this.selected, this.onTap, required this.index}); @@ -25,7 +24,7 @@ class AnswerBox extends StatelessWidget { AnswerPictureBox( selected: selected ?? false, index: index, - image: '${StoragePath.applicationDir.path}/data/${answer + image: '${StoragePath.documentDir.path}/data/${answer .imageId}${answer.imageInfo?.extension ?? '.png'}', ), Positioned( diff --git a/lib/core/widgets/answer_box/styles/picture_box.dart b/lib/core/widgets/answer_box/styles/picture_box.dart index 201baa2..bef6f28 100644 --- a/lib/core/widgets/answer_box/styles/picture_box.dart +++ b/lib/core/widgets/answer_box/styles/picture_box.dart @@ -1,11 +1,9 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; class AnswerPictureBox extends StatelessWidget { const AnswerPictureBox({super.key, required this.selected, required this.image, required this.index}); @@ -50,9 +48,7 @@ class AnswerPictureBox extends StatelessWidget { ), child: Text( '$index', - style: GoogleFonts.marhey( - fontSize: 17, - fontWeight: FontWeight.w600, + style: Marhey.semiBold17.copyWith( color: context.primaryColor, ), ), diff --git a/lib/core/widgets/answer_box/styles/text_box.dart b/lib/core/widgets/answer_box/styles/text_box.dart index 592237c..b94ea0d 100644 --- a/lib/core/widgets/answer_box/styles/text_box.dart +++ b/lib/core/widgets/answer_box/styles/text_box.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; class AnswerTextBox extends StatelessWidget { const AnswerTextBox({super.key, required this.text}); @@ -26,10 +26,8 @@ class AnswerTextBox extends StatelessWidget { child: Text( text, textAlign: TextAlign.center, - style: GoogleFonts.marhey( - fontSize: 14, - fontWeight: FontWeight.w700, - color: Color(0XFF322386) + style: Marhey.bold14.copyWith( + color: Color(0XFF322386), ), ), ), diff --git a/lib/core/widgets/showcase/question_showcase.dart b/lib/core/widgets/showcase/question_showcase.dart index f6401c0..efc1c2a 100644 --- a/lib/core/widgets/showcase/question_showcase.dart +++ b/lib/core/widgets/showcase/question_showcase.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; @@ -28,9 +28,7 @@ class QuestionShowcase extends StatelessWidget { disableMovingAnimation: true, textColor: context.primaryColor, descriptionTextAlign: TextAlign.center, - descTextStyle: GoogleFonts.marhey( - fontSize: 12, - fontWeight: FontWeight.w700, + descTextStyle: Marhey.bold12.copyWith( color: context.primaryColor, ), disableScaleAnimation: true, diff --git a/lib/features/intro/data/datasource/intro_datasource.dart b/lib/features/intro/data/datasource/intro_datasource.dart index 89ed418..15d4a31 100644 --- a/lib/features/intro/data/datasource/intro_datasource.dart +++ b/lib/features/intro/data/datasource/intro_datasource.dart @@ -1,21 +1,16 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:io'; -import 'package:flutter/services.dart'; import 'package:flutter_archive/flutter_archive.dart'; +import 'package:hadi_hoda_flutter/core/constants/my_api.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/network/http_request.dart'; -import 'package:hadi_hoda_flutter/core/response/base_response.dart'; -import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; -import 'package:hive/hive.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; +import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; abstract class IIntroDatasource { - Future saveLevels(); - Future extractData(); + Future getFiles(); Stream loadingStream(); } @@ -26,64 +21,51 @@ class IntroDatasourceImpl implements IIntroDatasource { IntroDatasourceImpl(this.httpRequest); @override - Future saveLevels() async { - try { - final Box levelBox = Hive.box(MyConstants.levelBox); - if (levelBox.isEmpty) { - final String levelAssets = await rootBundle.loadString( - 'assets/json/levels.json', - ); - final dynamic response = jsonDecode(levelAssets); - final List levelList = BaseResponse.getDataList( - response?['result'], - (json) => LevelModel.fromJson(json), - ); - - await levelBox.addAll(levelList); - } - } catch (e) { - throw MyException(errorMessage: '$e'); - } - } + Future getFiles() async { + final String filePath = '${StoragePath.documentDir.path}/files.zip'; - @override - Future extractData() async { - try { - final Directory dir = await getApplicationDocumentsDirectory(); - final File file = File('${dir.path}/data.zip'); - if (!(await file.exists())) { - final ByteData assetFile = await rootBundle.load('assets/data/data.zip'); - await file.create(recursive: true); - await file.writeAsBytes( - assetFile.buffer.asUint8List( - assetFile.offsetInBytes, - assetFile.lengthInBytes, - ), - flush: true, + if (LocalStorage.readData(key: MyConstants.downloadCompleted) != 'true') { + await httpRequest.download( + urlPath: MyApi.files, + savePath: filePath, + onReceive: (count, total) { + double percent = ((count / total) * 100); + streamController.add(percent); + }, + ).then((value) async { + await LocalStorage.saveData( + key: MyConstants.downloadCompleted, + value: 'true', ); + }); + } + try{ + if (LocalStorage.readData(key: MyConstants.extractCompleted) != 'true') { + final File file = File(filePath); + final Directory directory = Directory('${StoragePath.documentDir.path}/files/'); await ZipFile.extractToDirectory( zipFile: file, - destinationDir: dir, + destinationDir: directory, onExtracting: (zipEntry, progress) { streamController.add(progress); return ZipFileOperation.includeItem; }, - ); - + ).then((value) async { + await Future.wait([ + LocalStorage.saveData( + key: MyConstants.extractCompleted, + value: 'true', + ), + file.delete(recursive: true), + ]); + }); } else { - streamController.add(20); - await Future.delayed(Duration(milliseconds: 150)); - streamController.add(40); - await Future.delayed(Duration(milliseconds: 150)); - streamController.add(60); - await Future.delayed(Duration(milliseconds: 150)); - streamController.add(80); + streamController.add(50); await Future.delayed(Duration(milliseconds: 150)); streamController.add(100); - await Future.delayed(Duration(milliseconds: 150)); } - } catch (e) { + } catch (e){ throw MyException(errorMessage: '$e'); } } diff --git a/lib/features/intro/data/repository_impl/intro_repository_impl.dart b/lib/features/intro/data/repository_impl/intro_repository_impl.dart index 10c458f..9dfa48c 100644 --- a/lib/features/intro/data/repository_impl/intro_repository_impl.dart +++ b/lib/features/intro/data/repository_impl/intro_repository_impl.dart @@ -11,25 +11,9 @@ class IntroRepositoryImpl implements IIntroRepository { const IntroRepositoryImpl(this.datasource); @override - Future> saveLevels() async { + Future> getFiles() async { try { - await datasource.saveLevels(); - return DataState.success(NoParams()); - } on MyException catch (e) { - return DataState.error(e); - } catch (e) { - if (kDebugMode) { - rethrow; - } else { - return DataState.error(MyException(errorMessage: '$e')); - } - } - } - - @override - Future> extractData() async { - try { - await datasource.extractData(); + await datasource.getFiles(); return DataState.success(NoParams()); } on MyException catch (e) { return DataState.error(e); diff --git a/lib/features/intro/domain/repository/intro_repository.dart b/lib/features/intro/domain/repository/intro_repository.dart index 6bff8db..717feb4 100644 --- a/lib/features/intro/domain/repository/intro_repository.dart +++ b/lib/features/intro/domain/repository/intro_repository.dart @@ -3,7 +3,6 @@ import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; abstract class IIntroRepository { - Future> saveLevels(); - Future> extractData(); + Future> getFiles(); Stream loadingStream(); } diff --git a/lib/features/intro/domain/usecases/extract_data_usecase.dart b/lib/features/intro/domain/usecases/extract_data_usecase.dart deleted file mode 100644 index c48e061..0000000 --- a/lib/features/intro/domain/usecases/extract_data_usecase.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; -import 'package:hadi_hoda_flutter/core/params/no_params.dart'; -import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; -import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; -import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; - -class ExtractDataUseCase implements UseCase { - final IIntroRepository repository; - - const ExtractDataUseCase(this.repository); - - @override - Future> call(NoParams params) { - return repository.extractData(); - } -} diff --git a/lib/features/intro/domain/usecases/save_levels_usecase.dart b/lib/features/intro/domain/usecases/get_files_usecase.dart similarity index 76% rename from lib/features/intro/domain/usecases/save_levels_usecase.dart rename to lib/features/intro/domain/usecases/get_files_usecase.dart index 87f385b..ca5c7ea 100644 --- a/lib/features/intro/domain/usecases/save_levels_usecase.dart +++ b/lib/features/intro/domain/usecases/get_files_usecase.dart @@ -4,13 +4,13 @@ import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; -class SaveLevelsUseCase implements UseCase { +class GetFilesUseCase implements UseCase { final IIntroRepository repository; - const SaveLevelsUseCase(this.repository); + const GetFilesUseCase(this.repository); @override Future> call(NoParams params) { - return repository.saveLevels(); + return repository.getFiles(); } } diff --git a/lib/features/intro/presentation/bloc/intro_bloc.dart b/lib/features/intro/presentation/bloc/intro_bloc.dart index 71db678..9ec1665 100644 --- a/lib/features/intro/presentation/bloc/intro_bloc.dart +++ b/lib/features/intro/presentation/bloc/intro_bloc.dart @@ -1,30 +1,26 @@ import 'dart:async'; + import 'package:bloc/bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; +import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; -import 'package:hadi_hoda_flutter/features/intro/domain/usecases/extract_data_usecase.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_files_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart'; -import 'package:hadi_hoda_flutter/features/intro/domain/usecases/save_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; class IntroBloc extends Bloc { /// ------------constructor------------ - IntroBloc( - this._saveLevelsUseCase, - this._extractDataUseCase, - this._loadingStreamUseCase, - ) : super(const IntroState()) { - on(_saveLevelsEvent); - on(_extractDataEvent); + IntroBloc(this._getFilesUseCase, this._loadingStreamUseCase) + : super(const IntroState()) { + on(_getFilesEvent); loadingStream = _loadingStreamUseCase(); } /// ------------UseCases------------ - final SaveLevelsUseCase _saveLevelsUseCase; - final ExtractDataUseCase _extractDataUseCase; + final GetFilesUseCase _getFilesUseCase; final LoadingStreamUseCase _loadingStreamUseCase; /// ------------Variables------------ @@ -35,36 +31,23 @@ class IntroBloc extends Bloc { /// ------------Functions------------ /// ------------Api Calls------------ - FutureOr _saveLevelsEvent(SaveLevelsEvent event, - Emitter emit) async { - await _saveLevelsUseCase(NoParams()).then( - (value) { - value.fold( - (data) async { - - add(ExtractDataEvent()); + FutureOr _getFilesEvent( + GetFilesEvent event, + Emitter emit, + ) async { + await _getFilesUseCase(NoParams()).then((value) { + value.fold( + (data) async { + await Future.delayed( + Duration(milliseconds: 300), () { + ContextProvider.context!.goNamed(Routes.homePage); }, - (error) {}, - ); - }, - ); - } - - FutureOr _extractDataEvent(ExtractDataEvent event, - Emitter emit) async { - await _extractDataUseCase(NoParams()).then( - (value) { - value.fold( - (data) async { - await Future.delayed( - Duration(seconds: 1), () { - ContextProvider.context!.goNamed(Routes.homePage); - }, - ); - }, - (error) {}, - ); - }, - ); + ); + }, + (error) { + emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage))); + }, + ); + }); } } diff --git a/lib/features/intro/presentation/bloc/intro_event.dart b/lib/features/intro/presentation/bloc/intro_event.dart index 81aab0d..70e23cc 100644 --- a/lib/features/intro/presentation/bloc/intro_event.dart +++ b/lib/features/intro/presentation/bloc/intro_event.dart @@ -1,6 +1,4 @@ sealed class IntroEvent { const IntroEvent(); } - -class SaveLevelsEvent extends IntroEvent {} -class ExtractDataEvent extends IntroEvent {} +class GetFilesEvent extends IntroEvent {} diff --git a/lib/features/intro/presentation/bloc/intro_state.dart b/lib/features/intro/presentation/bloc/intro_state.dart index 2c7fd3f..58de6aa 100644 --- a/lib/features/intro/presentation/bloc/intro_state.dart +++ b/lib/features/intro/presentation/bloc/intro_state.dart @@ -1,15 +1,15 @@ import 'package:hadi_hoda_flutter/core/status/base_status.dart'; class IntroState { - final BaseStatus getIntroStatus; + final BaseStatus getFilesStatus; - const IntroState({this.getIntroStatus = const BaseInit()}); + const IntroState({this.getFilesStatus = const BaseInit()}); IntroState copyWith({ - BaseStatus? getIntroStatus, + BaseStatus? getFilesStatus, }) { return IntroState( - getIntroStatus: getIntroStatus ?? this.getIntroStatus, + getFilesStatus: getFilesStatus ?? this.getFilesStatus, ); } } diff --git a/lib/features/intro/presentation/ui/intro_page.dart b/lib/features/intro/presentation/ui/intro_page.dart index 92c0dd5..b874119 100644 --- a/lib/features/intro/presentation/ui/intro_page.dart +++ b/lib/features/intro/presentation/ui/intro_page.dart @@ -16,11 +16,10 @@ class IntroPage extends StatefulWidget { } class _IntroPageState extends State { - @override void initState() { super.initState(); - context.read().add(SaveLevelsEvent()); + context.read().add(GetFilesEvent()); } @override @@ -33,7 +32,10 @@ class _IntroPageState extends State { gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [Color(0XFF00154C), Color(0XFF150532)], + colors: [ + Color(0XFF00154C), + Color(0XFF150532), + ], ), image: DecorationImage( image: AssetImage(MyAssets.pattern), @@ -47,19 +49,26 @@ class _IntroPageState extends State { ), child: Stack( alignment: Alignment.center, - children: [_image(), _loading(context)], + children: [ + _image(), + _loading(context), + ], ), ), ); } - MyImage _image() => MyImage(image: MyAssets.hadiHoda, size: 200); + MyImage _image() { + return MyImage( + image: MyAssets.hadiHoda, + size: 200, + ); + } Positioned _loading(BuildContext context) { return Positioned( - bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s10, + bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16, child: IntroLoadingWidget( - percent: 80, loadingStream: context.read().loadingStream, ), ); diff --git a/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart b/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart index fdd2223..de107f7 100644 --- a/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart +++ b/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart @@ -6,11 +6,9 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; class IntroLoadingWidget extends StatelessWidget { const IntroLoadingWidget({ super.key, - this.percent, this.loadingStream, }); - final double? percent; final Stream? loadingStream; @override @@ -74,7 +72,7 @@ class IntroLoadingWidget extends StatelessWidget { child: Center( child: Text( '${snapshot.data?.toInt() ?? 0}%', - style: MyTextStyle.normal17.copyWith( + style: DinoKids.regular17.copyWith( color: Color(0XFF6E83A8), ), ), diff --git a/lib/features/level/presentation/ui/level_page.dart b/lib/features/level/presentation/ui/level_page.dart index 22335ce..9a9673d 100644 --- a/lib/features/level/presentation/ui/level_page.dart +++ b/lib/features/level/presentation/ui/level_page.dart @@ -6,7 +6,6 @@ import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_bloc.dart'; -import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_state.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/bottom_path.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/hint_level_widget.dart'; diff --git a/lib/features/level/presentation/ui/widgets/hint_level_widget.dart b/lib/features/level/presentation/ui/widgets/hint_level_widget.dart index f1f1312..ad98952 100644 --- a/lib/features/level/presentation/ui/widgets/hint_level_widget.dart +++ b/lib/features/level/presentation/ui/widgets/hint_level_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/text_box.dart'; @@ -37,9 +37,7 @@ class HintLevelWidget extends StatelessWidget { children: [ Text( 'Step ${level.order ?? 0}', - style: GoogleFonts.marhey( - fontSize: 14, - fontWeight: FontWeight.w700, + style: Marhey.bold14.copyWith( color: Color(0xFFD8490B), ), ), @@ -47,9 +45,7 @@ class HintLevelWidget extends StatelessWidget { level.title ?? '', maxLines: 3, overflow: TextOverflow.ellipsis, - style: GoogleFonts.marhey( - fontSize: 18, - fontWeight: FontWeight.w600, + style: Marhey.semiBold18.copyWith( color: Color(0xFF322386), height: 1, ), diff --git a/lib/features/level/presentation/ui/widgets/level_widget.dart b/lib/features/level/presentation/ui/widgets/level_widget.dart index ff5d9a7..ce1e44c 100644 --- a/lib/features/level/presentation/ui/widgets/level_widget.dart +++ b/lib/features/level/presentation/ui/widgets/level_widget.dart @@ -42,7 +42,16 @@ class LevelWidget extends StatelessWidget { MyImage(image: LevelType.image[type] ?? MyAssets.level, size: 46), Text( '$index', - style: MyTextStyle.normal26.copyWith(color: context.primaryColor), + style: DinoKids.regular26.copyWith( + color: context.primaryColor, + shadows: [ + Shadow( + color: Color(0XFF5B5B5B), + blurRadius: 2.86, + offset: Offset(0, 2), + ), + ], + ), ), if(type == LevelType.current) Positioned( diff --git a/lib/features/question/presentation/bloc/question_bloc.dart b/lib/features/question/presentation/bloc/question_bloc.dart index 7d37a36..5c660ea 100644 --- a/lib/features/question/presentation/bloc/question_bloc.dart +++ b/lib/features/question/presentation/bloc/question_bloc.dart @@ -3,7 +3,6 @@ import 'package:bloc/bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:hadi_hoda_flutter/core/params/question_params.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart'; -import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; import 'package:hadi_hoda_flutter/features/question/domain/usecases/get_level_usecase.dart'; import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart'; import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_state.dart'; diff --git a/lib/features/question/presentation/ui/question_page.dart b/lib/features/question/presentation/ui/question_page.dart index 43cfd98..9e68191 100644 --- a/lib/features/question/presentation/ui/question_page.dart +++ b/lib/features/question/presentation/ui/question_page.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/gap.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; @@ -80,10 +81,8 @@ class QuestionPage extends StatelessWidget { BlocBuilder( builder: (context, state) => Text( state.levelEntity?.title ?? '', - style: GoogleFonts.marhey( - fontSize: 14, - fontWeight: FontWeight.w700, - color: Colors.white, + style: Marhey.bold14.copyWith( + color: context.primaryColor, ), ), ), @@ -109,10 +108,8 @@ class QuestionPage extends StatelessWidget { BlocBuilder( builder: (context, state) => Text( 'Question ${state.currentStep} / ${state.levelEntity?.questions?.length ?? 0}', - style: GoogleFonts.marhey( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Colors.white.withValues(alpha: 0.5), + style: Marhey.medium12.copyWith( + color: context.primaryColor.withValues(alpha: 0.5), shadows: [ Shadow( offset: Offset(0, 1), @@ -127,10 +124,8 @@ class QuestionPage extends StatelessWidget { builder: (context, state) => Text( state.levelEntity?.questions?[state.currentStep].title ?? '', textAlign: TextAlign.center, - style: GoogleFonts.marhey( - fontSize: 22, - fontWeight: FontWeight.w600, - color: Colors.white, + style: Marhey.medium12.copyWith( + color: context.primaryColor, shadows: [ Shadow( offset: Offset(0, 1), diff --git a/lib/features/question/presentation/ui/widgets/left_blob.dart b/lib/features/question/presentation/ui/widgets/left_blob.dart index 0964766..66f16f3 100644 --- a/lib/features/question/presentation/ui/widgets/left_blob.dart +++ b/lib/features/question/presentation/ui/widgets/left_blob.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; class LeftBlob extends StatelessWidget { @@ -15,9 +15,7 @@ class LeftBlob extends StatelessWidget { Text( 'Your answer\nwas not correct.', textAlign: TextAlign.center, - style: GoogleFonts.marhey( - fontSize: 12, - fontWeight: FontWeight.w500, + style: Marhey.medium12.copyWith( color: Color(0XFFB5AEEE), ), ), diff --git a/lib/features/question/presentation/ui/widgets/right_blob.dart b/lib/features/question/presentation/ui/widgets/right_blob.dart index b10237a..7ed2aa8 100644 --- a/lib/features/question/presentation/ui/widgets/right_blob.dart +++ b/lib/features/question/presentation/ui/widgets/right_blob.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; class RightBlob extends StatelessWidget { @@ -15,9 +15,7 @@ class RightBlob extends StatelessWidget { Text( 'Be more\ncareful.', textAlign: TextAlign.center, - style: GoogleFonts.marhey( - fontSize: 12, - fontWeight: FontWeight.w500, + style: Marhey.medium12.copyWith( color: Color(0XFFB5AEEE), ), ), diff --git a/lib/init_bindings.dart b/lib/init_bindings.dart index 11a4ef3..c8c7a8c 100644 --- a/lib/init_bindings.dart +++ b/lib/init_bindings.dart @@ -10,9 +10,8 @@ import 'package:hadi_hoda_flutter/features/home/domain/usecases/get_home_usecase import 'package:hadi_hoda_flutter/features/intro/data/datasource/intro_datasource.dart'; import 'package:hadi_hoda_flutter/features/intro/data/repository_impl/intro_repository_impl.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; -import 'package:hadi_hoda_flutter/features/intro/domain/usecases/extract_data_usecase.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_files_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart'; -import 'package:hadi_hoda_flutter/features/intro/domain/usecases/save_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/level/data/datasource/level_datasource.dart'; import 'package:hadi_hoda_flutter/features/level/data/repository_impl/level_repository_impl.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; @@ -47,8 +46,7 @@ void initBindings() { /// Intro Feature locator.registerLazySingleton(() => IntroDatasourceImpl(locator())); locator.registerLazySingleton(() => IntroRepositoryImpl(locator())); - locator.registerLazySingleton(() => SaveLevelsUseCase(locator())); - locator.registerLazySingleton(() => ExtractDataUseCase(locator())); + locator.registerLazySingleton(() => GetFilesUseCase(locator())); locator.registerLazySingleton(() => LoadingStreamUseCase(locator())); /// Home Feature diff --git a/lib/main.dart b/lib/main.dart index 5940746..7740c6e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,8 +14,8 @@ Future main() async { initBindings(); await Future.wait([ LocalStorage.init(), + StoragePath.getDocumentDir(), initDataBase(), - StoragePath.getApplicationDir(), ]); AuthStorage.loadData(); runApp(const MainApp()); diff --git a/pubspec.lock b/pubspec.lock index 5e4c4f8..857e00e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -333,14 +333,6 @@ packages: url: "https://pub.dev" source: hosted version: "16.2.4" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: "517b20870220c48752eafa0ba1a797a092fb22df0d89535fd9991e86ee2cdd9c" - url: "https://pub.dev" - source: hosted - version: "6.3.2" graphs: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 59e9aa3..0061d6c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,6 @@ dependencies: flutter_svg: ^2.2.1 get_it: ^8.2.0 go_router: ^16.1.0 - google_fonts: ^6.3.2 hive: ^2.2.3 intl: ^0.20.2 path_drawing: ^1.0.1 @@ -41,14 +40,31 @@ flutter: generate: true assets: - - assets/audio/ - - assets/data/ - assets/fonts/ - assets/images/ - - assets/json/ fonts: - family: dinokids fonts: - - asset: assets/fonts/dinokids.ttf \ No newline at end of file + - asset: assets/fonts/dinokids.ttf + - family: marhey + fonts: + - asset: assets/fonts/Marhey-Light.ttf + weight: 100 + - asset: assets/fonts/Marhey-Light.ttf + weight: 200 + - asset: assets/fonts/Marhey-Light.ttf + weight: 300 + - asset: assets/fonts/Marhey-Regular.ttf + weight: 400 + - asset: assets/fonts/Marhey-Medium.ttf + weight: 500 + - asset: assets/fonts/Marhey-SemiBold.ttf + weight: 600 + - asset: assets/fonts/Marhey-Bold.ttf + weight: 700 + - asset: assets/fonts/Marhey-Bold.ttf + weight: 800 + - asset: assets/fonts/Marhey-Bold.ttf + weight: 900