Compare commits

...

796 Commits

Author SHA1 Message Date
misha
355ec2df48 feat(video_calls): added phone waking up after it gets call push 2026-10-19 12:49:09 +03:00
misha
da6158625f fix: tests 2026-10-16 16:30:56 +03:00
misha
5a8f8aee3e feat(video_calls): ios repeated call fix 2026-10-16 15:41:13 +03:00
misha
86e9d0cc31 feat(video_calls): android repeated call after hanging up fix and ios repeated calls after call initiation fix 2026-10-16 15:40:41 +03:00
misha
6d2935400a feat(video_calls): ios voip push, mix and crushes fix 2026-10-16 13:49:48 +03:00
misha
ff17b813ac feat(ios): env migration for ios 27 2026-10-16 08:26:26 +03:00
misha
9288a5c849 version changed 2026-10-15 15:22:04 +03:00
misha
4ef174ebde feat(video_calls): repeated calls after call termination fix 2026-10-15 15:21:38 +03:00
misha
1901248539 feat(video_calls): ios mic fix, android call fix. feat(dev_tools): base url caching 2026-10-15 14:06:37 +03:00
b2e700a4eb Merge pull request 'fix: ci/cd' (#1074) from misha/eatvio_app:issue-1062 into main
Reviewed-on: eatvio/eatvio_app#1074
2026-10-14 10:17:37 +00:00
misha
1bbb08f2a2 fix: ci/cd 2026-10-14 13:16:57 +03:00
61f1b76f99 Merge pull request 'issue-1062' (#1068) from misha/eatvio_app:issue-1062 into main
Reviewed-on: eatvio/eatvio_app#1068
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-10-14 09:53:01 +00:00
misha
ef4df92f58 fix: analyzer fixes 2026-10-14 10:53:38 +03:00
misha
dcd343e765 feat(push_notifications): issue-660, fix: issue-908 2026-10-14 08:16:20 +03:00
misha
98c175df44 fix: test fixed 2026-10-12 11:19:18 +03:00
misha
cb312037b2 feat(UGPC): issue-777 2026-10-12 08:50:33 +03:00
572a6f1943 Merge pull request 'update(doc): bug report issue template, desc field added' (#1073) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1073
2026-10-09 09:47:54 +00:00
Anatoliy Poloz
a6ae9abb57 update(doc): bug report issue template, desc field added 2026-10-09 12:47:22 +03:00
431354170e Merge pull request 'description field added to feature issue template' (#1072) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1072
2026-10-09 09:43:28 +00:00
Anatoliy Poloz
c38e82f558 description field added to feature issue template 2026-10-09 12:43:00 +03:00
afd6f9a93a Merge pull request 'update bug issue template' (#1071) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1071
2026-10-09 09:34:46 +00:00
Anatoliy Poloz
641eb4d2e2 update bug issue template 2026-10-09 12:34:08 +03:00
74c66c9600 Merge pull request 'feat(doc): issue templates' (#1070) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1070
2026-10-09 09:12:18 +00:00
Anatoliy Poloz
73e89ff7a9 feat(doc): issue templates 2026-10-09 12:11:30 +03:00
misha
f8e06b6d7a version changed 2026-10-08 07:20:00 +03:00
misha
866ea2fe3b Merge remote-tracking branch 'upstream/main' into issue-1062 2026-10-08 07:18:53 +03:00
d73f68e24b Merge pull request 'video_calls_fixes' (#1066) from misha/eatvio_app:video_calls_fixes into main
Reviewed-on: eatvio/eatvio_app#1066
2026-10-05 11:56:40 +00:00
misha
61cded0081 version cnhanged 2026-10-05 13:13:25 +03:00
misha
df634fedd8 feat(video_calls): incommig call handling fix for ios and anroid 2026-10-05 13:12:55 +03:00
misha
603a158cf2 feat(diary): editing of previous and current finished days 2026-10-01 10:44:52 +03:00
a1bae68307 Merge pull request 'feat(video_calls, welcome_screen): ios mic fix, welcome scrin layoute fix' (#1064) from misha/eatvio_app:video_calls_fixes into main
Reviewed-on: eatvio/eatvio_app#1064
2026-09-28 09:01:24 +00:00
misha
2dce28b196 feat(video_calls, welcome_screen): ios mic fix, welcome scrin layoute fix 2026-09-28 11:20:52 +03:00
ae4f9d2e9b Merge pull request 'fix(chat): ws manager' (#1060) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1060
Reviewed-by: misha <misha@noreply.localhost>
2026-09-25 07:31:28 +00:00
Anatoliy
a00aae36cf update version 2026-09-16 13:50:12 +03:00
Anatoliy
27e98bdb44 fix(chat): ws manager 2026-09-16 00:10:23 +03:00
Anatoliy
8ec6d5b799 refactor(chat): dedup 2026-09-15 23:20:00 +03:00
Anatoliy
077cfb3a67 refactor(chat): message dedup 2026-09-15 23:06:12 +03:00
c4f5cae36d Merge pull request 'fix: issue-942, issue-967, fixed images positioning for blog posts' (#1055) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1055
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-09-15 19:31:06 +00:00
misha
b040c6e020 fix: tests fix 2026-09-02 15:42:17 +03:00
misha
745e77f948 fix: analyer 2026-09-02 09:34:25 +03:00
misha
c6ea1d414d fix: issue-372, issue-227, issue-406 2026-09-02 09:32:14 +03:00
misha
10af279d87 fix: issue-942, issue-967, fixed images positioning for blog posts 2026-08-28 10:05:40 +03:00
d0879e556f Merge pull request 'version changed' (#1054) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1054
2026-08-27 07:21:39 +00:00
misha
8f933118a3 version changed 2026-08-27 08:58:09 +03:00
7dc7eab774 Merge pull request 'issue-1049, issue-1039, issue-1035, issue-1032, issue-995, issue-993' (#1053) from misha/eatvio_app:1-3-42_bug_fixes into main
Reviewed-on: eatvio/eatvio_app#1053
2026-08-26 08:07:39 +00:00
misha
16a13488d1 version changed 2026-08-26 10:27:48 +03:00
misha
de7bf8dc19 fix: issue-1049, issue-1039, issue-1035, issue-1032, issue-995, issue-993 2026-08-26 08:42:47 +03:00
eeb261df0a Merge pull request 'feat(image_validation)' (#1052) from misha/eatvio_app:issue-1037 into main
Reviewed-on: eatvio/eatvio_app#1052
2026-08-24 12:04:37 +00:00
misha
1b03a0d5e1 version changed 2026-08-24 11:55:39 +03:00
misha
0208ed753a feat(image_validation): image validation fix 2026-08-24 11:38:01 +03:00
184f0417a7 Merge pull request 'version changed' (#1051) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1051
2026-08-21 11:22:11 +00:00
misha
6265e865e9 version changed 2026-08-21 14:20:54 +03:00
1550b7ea0b Merge pull request 'fix: fixed domain matching for deeplinks' (#1050) from misha/eatvio_app:marketing_domains into main
Reviewed-on: eatvio/eatvio_app#1050
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-08-21 10:55:11 +00:00
misha
db10895ebb fix: removed path matching to handle links like https://{domain} 2026-08-21 10:25:09 +03:00
misha
a7361d3ab1 fix: fixed domain matching for deeplinks 2026-08-20 13:45:16 +03:00
1c54063a35 Merge pull request 'feat(chat,consultant_registration, portion_input)' (#1045) from chat_messages into main
Reviewed-on: eatvio/eatvio_app#1045
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-08-14 11:51:01 +00:00
efae7fc958 Merge pull request 'portion_input' (#1044) from misha/eatvio_app:chat_messages into chat_messages
Reviewed-on: eatvio/eatvio_app#1044
2026-08-14 10:48:00 +00:00
misha
90ac4e750d feat(portion_input): fixed portion input sizes 2026-08-14 13:46:00 +03:00
misha
6d7419c283 version changed 2026-08-14 12:59:04 +03:00
caf45a9050 Merge pull request 'Scoring validation' (#1043) from misha/eatvio_app:chat_messages into chat_messages
Reviewed-on: eatvio/eatvio_app#1043
2026-08-14 09:20:03 +00:00
misha
0a5e7d95c4 Merge branch 'chat_messages' of ssh://10.55.5.123:222/misha/eatvio_app into chat_messages 2026-08-14 12:16:46 +03:00
misha
85482173ad feat(consultant_scoring): added validation for last first and middle name for scoring 2026-08-14 12:16:03 +03:00
65f7992d40 Merge pull request 'feat(chat_messages): fixed data race for chat mesages state' (#1042) from misha/eatvio_app:chat_messages into chat_messages
Reviewed-on: eatvio/eatvio_app#1042
2026-08-14 08:07:56 +00:00
misha
52a01bee12 feat(chat_messages): fixed data race for chat mesages state 2026-08-14 11:05:03 +03:00
179fc0ad99 Merge pull request 'pasport_data_validation' (#1041) from misha/eatvio_app:pasport_data_validation into main
Reviewed-on: eatvio/eatvio_app#1041
2026-08-13 12:18:35 +00:00
misha
8494e61eec version changed 2026-08-13 12:29:18 +03:00
misha
5c2458ecad feat(consultant_refistration): added explicit validation for scoring data 2026-08-13 12:28:34 +03:00
b63bab8bf5 Merge pull request 'feat(post_creation_with_images)' (#1026) from post_creation_with_images into main
Reviewed-on: eatvio/eatvio_app#1026
2026-08-05 14:07:55 +00:00
7790014726 Merge pull request 'Version changed' (#1029) from misha/eatvio_app:post_creation_with_images into post_creation_with_images
Reviewed-on: eatvio/eatvio_app#1029
2026-08-05 13:33:20 +00:00
misha
0d588bcd57 Version changed 2026-08-05 16:32:14 +03:00
b679e90ba2 Merge pull request 'fix: analyzer fix' (#1027) from misha/eatvio_app:post_creation_with_images into post_creation_with_images
Reviewed-on: eatvio/eatvio_app#1027
2026-08-05 12:34:27 +00:00
misha
6b5442eb87 fix: analyzer fix 2026-08-05 15:33:27 +03:00
2474c5bea3 Merge pull request 'post_creation_with_images' (#1025) from misha/eatvio_app:post_creation_with_images into post_creation_with_images
Reviewed-on: eatvio/eatvio_app#1025
2026-08-05 12:31:23 +00:00
misha
478a53674a feat(post_creatin): fixed animation widget for profile feed 2026-08-05 15:21:23 +03:00
7f278d0f59 Merge pull request 'fix: fixed script run time location' (#1024) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1024
2026-08-04 15:36:07 +00:00
misha
53426c858c fix: fixed script run time location 2026-08-04 18:35:32 +03:00
88f0cde88f Merge pull request 'fix: added pods updating' (#1023) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1023
2026-08-04 15:19:44 +00:00
misha
a5fcf62524 fix: added pods updating 2026-08-04 18:19:10 +03:00
a2e41a2ff5 Merge pull request 'fix: removed SPM' (#1022) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1022
2026-08-04 15:13:32 +00:00
misha
5b1beafbab fix: removed SPM 2026-08-04 18:12:55 +03:00
4eadecd6f2 Merge pull request 'fix: removed spm flag' (#1021) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1021
2026-08-04 14:52:33 +00:00
misha
6292db07a1 fix: removed spm flag 2026-08-04 17:51:58 +03:00
ab29b6b329 Merge pull request 'fix: ci/cd fix' (#1020) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1020
2026-08-04 14:48:54 +00:00
misha
af5d182a79 fix: ci/cd fix 2026-08-04 17:48:08 +03:00
misha
04de956769 feat(post_creation): added multiple image posts creation and validation 2026-08-04 17:47:43 +03:00
191bb74aa4 Merge pull request 'Version changed' (#1018) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1018
2026-08-04 14:35:33 +00:00
misha
3210f38d4a Version changed 2026-08-04 14:22:33 +03:00
27a98a496d Merge pull request 'promo_codes' (#1017) from promo_codes into main
Reviewed-on: eatvio/eatvio_app#1017
2026-08-04 11:14:47 +00:00
d8ecc7f3b1 Merge pull request 'feat(promo_codes)' (#1015) from misha/eatvio_app:promo_codes into promo_codes
Reviewed-on: eatvio/eatvio_app#1015
2026-08-04 11:13:45 +00:00
063da03d7e merge upstream 2026-08-04 10:17:32 +00:00
6b5927a99e Merge pull request 'sync with main' (#1016) from main into promo_codes
Reviewed-on: eatvio/eatvio_app#1016
2026-08-04 10:17:26 +00:00
afab72f7bc merge upstream 2026-08-04 10:16:20 +00:00
2770ff0e80 Merge pull request 'feat(consultant_scoring)' (#1012) from consultant_scoring into main
Reviewed-on: eatvio/eatvio_app#1012
2026-08-04 10:16:09 +00:00
1200021bb6 Merge pull request 'personalized_feed' (#1004) from personalized_feed into main
Reviewed-on: eatvio/eatvio_app#1004
2026-08-04 10:15:25 +00:00
misha
9e8b8b89fc feat(promo_codes): added promo codes handling to app 2026-08-03 18:12:05 +03:00
a24d052193 Merge pull request 'fix: test fixed' (#1014) from misha/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1014
2026-08-03 12:32:07 +00:00
misha
9de0efa28e fix: test fixed 2026-08-03 15:30:54 +03:00
37504aa292 Merge pull request 'fix: removed unused import' (#1013) from misha/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1013
2026-08-03 08:46:16 +00:00
c8588a2e1f Merge pull request 'consultant_scoring' (#1011) from misha/eatvio_app:consultant_scoring into consultant_scoring
Reviewed-on: eatvio/eatvio_app#1011
2026-07-31 10:45:21 +00:00
misha
e0cab89126 Merge branch 'consultant_scoring' of ssh://10.55.5.123:222/misha/eatvio_app into consultant_scoring 2026-07-30 17:42:30 +03:00
misha
954d4955da feat(consultant_scoring): added validation errors, fixed scoring flow, updating flow 2026-07-30 17:41:30 +03:00
e5086d7fbc Merge pull request 'feat(consultant_scoring)' (#1005) from misha/eatvio_app:consultant_scoring into consultant_scoring
Reviewed-on: eatvio/eatvio_app#1005
2026-07-29 11:09:30 +00:00
0d93768dc3 Merge branch 'consultant_scoring' into consultant_scoring 2026-07-29 11:09:10 +00:00
misha
8c5fc8d827 feat(consultant_scoring): fixed registration update flow 2026-07-29 14:08:13 +03:00
misha
2d6b042d45 fix: removed unused import 2026-07-28 12:00:03 +03:00
d56aa45c92 Merge pull request 'personalized_feed' (#1009) from misha/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1009
2026-07-23 13:37:00 +00:00
misha
b3d0a26667 Merge remote-tracking branch 'upstream/main' into personalized_feed 2026-07-23 15:40:57 +03:00
8835d65944 Merge pull request 'version changed' (#1007) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1007
2026-07-23 12:37:37 +00:00
misha
cc9aa6bffb version changed 2026-07-23 15:36:02 +03:00
a15e8b78a5 Merge pull request 'Info plist + version fix' (#1006) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#1006
2026-07-23 12:32:14 +00:00
misha
0667ab81a8 Merge remote-tracking branch 'upstream/main' 2026-07-23 15:31:23 +03:00
misha
1dc60eec64 version changed 2026-07-23 15:29:47 +03:00
misha
69f0f1e919 fix: removed unused info plist key 2026-07-23 15:27:49 +03:00
misha
a6fe6afb80 feat(personalized_feed): fixed photos rendering and fixed profile posts rendering 2026-07-23 15:17:01 +03:00
misha
c8c8ade083 Merge remote-tracking branch 'upstream/main' into personalized_feed 2026-07-23 15:15:59 +03:00
misha
037f153273 feat(consultant_scoring): adjusted data for new registration, added sbp banks endpoint 2026-07-22 17:58:02 +03:00
6a17bf3a95 Merge pull request 'feat(personalized_feed): added video and multiple images handling to detailed blog post screen' (#1003) from misha/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1003
2026-07-22 11:53:41 +00:00
misha
2cccc9e253 feat(personalized_feed): added video and multiple images handling to detailed blog post screen 2026-07-22 14:41:26 +03:00
dcf7b25989 Merge pull request 'пофиксили отображение коунтера карусели при переключении картинок, при посте с одной картинкой и одним видео. добавили таймер на видео.' (#1002) from Hasan/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1002
2026-07-22 07:26:28 +00:00
163f56ff61 Merge pull request 'feat(vidoe_calls)' (#983) from misha/eatvio_app:issue-975 into main
Reviewed-on: eatvio/eatvio_app#983
2026-07-22 07:25:32 +00:00
d6b57ef34d пофиксили отображение коунтера карусели при переключении картинок, при посте с одной картинкой и одним видео. добавили таймер на видео. 2026-07-21 16:50:06 +03:00
45f20cc903 Merge pull request 'personalized_feed' (#1) from eatvio/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: Hasan/eatvio_app#1
2026-07-21 12:43:51 +00:00
746b9b6d28 Merge pull request 'feat(personalized_feed): added vk player state handling, separeted player logic' (#1001) from misha/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1001
2026-07-21 12:41:33 +00:00
misha
2dbd4a455f feat(personalized_feed): added vk player state handling, separeted player logic 2026-07-21 15:15:28 +03:00
c7514e2cbf Merge pull request 'fix fixtures' (#1000) from Hasan/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#1000
2026-07-21 11:26:44 +00:00
f1abea70c5 fix fixtures 2026-07-21 14:22:45 +03:00
e4d397b478 Merge pull request 'personalized_feed with video and multiple images' (#999) from apoloz/eatvio_app:personalized_feed into personalized_feed
Reviewed-on: eatvio/eatvio_app#999
2026-07-21 08:08:19 +00:00
9c5c6df751 refactor(video,webview): webview lib replaced on feed 2026-07-20 18:15:25 +03:00
misha
48a984f5e9 feat(personalized_feed): added fixtures for new feed, added new feed parsing and layout, added webview player for post videos 2026-07-20 16:47:19 +03:00
misha
5dc1f48fd1 feat(ci/cd): added api key for tf 2026-07-15 17:31:32 +03:00
misha
5ec877ef72 version changed 2026-07-15 15:19:56 +03:00
misha
dbaf639ac6 fix: analyzer fix 2026-07-15 15:18:53 +03:00
misha
2a07ed596b Merge remote-tracking branch 'upstream/main' into issue-975 2026-07-15 15:17:44 +03:00
bd2de07b8f Merge pull request 'sbp-alfa-bank-payment' (#998) from misha/eatvio_app:sbp_payments into main
Reviewed-on: eatvio/eatvio_app#998
2026-07-15 12:06:00 +00:00
misha
eee912f05b fix: pub cache cleaning 2026-07-14 16:57:32 +03:00
misha
e316bf1e0e version changed 2026-07-14 16:12:43 +03:00
misha
de19af14bf fix: fixed analyzer and test 2026-07-14 16:11:56 +03:00
Anatoliy
b064c7016e feat(payment, chat): promo code mocked BottomSheet added 2026-07-14 15:50:44 +03:00
misha
e94681266a feat(sbp_payments): added new layoute for sbp banks and rederict to chosen bank, and added tests for layoute 2026-07-14 13:43:46 +03:00
misha
0ca2d1a1cc feat(sbp_payments): added banks deep link handling to chat screen 2026-07-14 13:09:18 +03:00
misha
be924265a1 feat(sbp_payments): added cubit layer for sbp payments with tests 2026-07-09 18:35:09 +03:00
a0edfe942b feat(payments): phase 3 test added 2026-07-09 16:21:53 +03:00
misha
51397003b5 feat(sbp_payments): added tests for new chosen_plan_state fixtures and new tests for chat repo and service 2026-07-08 15:07:36 +03:00
misha
e10610d93c feat(sbp_payments): added new chosen_plan fixtures with chosen_plan states and fixed chat tests 2026-07-08 14:28:08 +03:00
Anatoliy Poloz
d21cc46558 feat(payments): phase #1 tests and part of implementation 2026-07-08 13:31:55 +03:00
Anatoliy Poloz
2ab26bbda5 feat(chat): reorganize test fixtures 2026-07-08 12:31:06 +03:00
misha
41e556d172 feat(sbp_payments): fixtures and dio excp type added 2026-07-08 12:20:11 +03:00
Anatoliy Poloz
6d920857f6 fix(gradle) 2026-07-08 11:02:58 +03:00
Anatoliy
7183fc5d7d feat(sbp-payin): fixtures and banks assets added 2026-07-08 10:50:12 +03:00
Anatoliy
3852a06ab4 feat(payment): new sbp payment fixture added 2026-07-07 12:22:05 +03:00
misha
219908684f feat(video_calls): fixed naviagtion from push notification to call and added wake lock 2026-07-06 11:18:05 +03:00
misha
9ce7b035ff feat(video_calls): fixed call ended push handling 2026-06-30 18:48:45 +03:00
misha
c8ad600d97 fix: analyzer 2026-06-30 17:17:58 +03:00
misha
f493e07f9f feat(video_calls): call ended push, recall button for message 2026-06-30 16:11:18 +03:00
misha
c0c7e2e658 version changed 2026-06-29 12:15:34 +03:00
misha
f913ae60fa feat(vide_calls): added tokens clearing 2026-06-29 12:12:53 +03:00
misha
2100e5ca02 fix: analyzer fix 2026-06-26 11:30:49 +03:00
misha
10b36117a6 version changed 2026-06-26 08:57:31 +03:00
misha
bde4eea7d1 feat(video_calls): fixed recinnecting logic, added consultant bage 2026-06-26 08:56:57 +03:00
misha
59f42c9b1e fix: test fixed 2026-06-24 09:35:04 +03:00
misha
c5bf5acfe7 feat(video_calls): fixed online indicator and in app notifications for video call 2026-06-24 08:26:16 +03:00
7db9af9894 merge upstream 2026-06-23 08:56:24 +00:00
misha
8ff826fa3e fix: analyzer fix 2026-06-23 09:08:04 +03:00
misha
1e29cda65c Version changed 2026-06-23 08:43:40 +03:00
misha
ed72ed9799 feat(video_calls): changed accept flow, fixed ui bugs for PIP and video render sizes 2026-06-23 08:42:55 +03:00
misha
8920fc280f feat(ci/cd): version changed, anroind action runs only on main branch 2026-06-18 15:02:53 +03:00
misha
7493870a3d feat(video_calls): removed system ui, fixed wrong app initializing 2026-06-18 15:01:21 +03:00
misha
e3c22f8ac8 Revert "feat(video_calls): added system ui for call and navigation to the app"
This reverts commit ea5fced456.
2026-06-18 14:41:56 +03:00
misha
ea5fced456 feat(video_calls): added system ui for call and navigation to the app 2026-06-17 16:47:51 +03:00
misha
e3dd8162fa fix: ci/cd error fixed 2026-06-17 11:33:17 +03:00
misha
90e5c7e58d fix: ci/cd error fixed 2026-06-17 11:17:37 +03:00
misha
65d529b0af feat(video_calls): fixed navigation from voip push 2026-06-17 11:06:22 +03:00
misha
95c1d40c79 feat(video_calls): fixed nullable overlay state handling 2026-06-16 22:57:17 +03:00
misha
895443e747 feat(video_calls): added more logs for sentry 2026-06-16 21:11:45 +03:00
misha
367753d409 Version change 2026-06-16 19:30:01 +03:00
misha
e82866f936 feat(video_calls): voip push handling fix 2026-06-16 19:28:16 +03:00
misha
b13ff74220 fix: added NSLocationAlwaysAndWhenInUseUsageDescription key description 2026-06-16 18:33:21 +03:00
misha
e0d697e8d0 feat(video_calls): fixed ios push UI 2026-06-16 18:30:16 +03:00
misha
705538ac85 fix: added NSLocationWhenInUseUsageDescription key description 2026-06-16 17:56:59 +03:00
misha
03f037518e feat(video_calls): fixed ios and HMS pushes for calls 2026-06-16 15:01:46 +03:00
misha
a07565fca9 feat(ci/cd): removed pods updating 2026-06-15 16:47:17 +03:00
misha
b9cb4eeb84 feat(video_calls): app delegate fix 2026-06-15 16:27:24 +03:00
misha
4d531036fa Version changed 2026-06-15 14:12:37 +03:00
misha
1cafb4b05a feat(video_calls): changed chat button layoute 2026-06-15 14:07:56 +03:00
misha
5daa187045 feat(ci/cd): fixed app delegate for ios 2026-06-11 12:14:42 +03:00
misha
f4f884484d feat(ci/cd): separeted code sign from build_app 2026-06-11 11:55:43 +03:00
misha
4dd32e1a42 feat(ci/cd): fixed team id 2026-06-10 17:21:40 +03:00
misha
3e89bb5ca9 feat(ci/cd): added team id to build_app for ios 2026-06-10 17:14:15 +03:00
misha
885c6f66f9 feat(ci/cd): added gitea token for fastlane url 2026-06-10 16:39:06 +03:00
misha
9dc568ceab feat(ci/cd): removed flutter updating 2026-06-10 14:35:20 +03:00
misha
6fb151ef32 feat(ci/cd): added pods updating 2026-06-10 14:19:21 +03:00
misha
5fa024a7a8 feat(ci/cd): changed repositories for ci/cd 2026-06-10 14:09:54 +03:00
misha
de795c5274 feat(video_calls): added system android pip for calls 2026-06-10 09:32:43 +03:00
misha
27fe4afd81 feat(video_calls): added new incomng push impl, fixed mic and video sharing while connecting to call 2026-06-09 09:55:20 +03:00
misha
8e2b7147d5 Merge branch 'issue-975' of ssh://10.55.5.123:222/misha/eatvio_app into issue-975 2026-06-04 14:39:30 +03:00
misha
f51a68324b feat(video_calls): ios voip pushes handling 2026-06-04 14:38:27 +03:00
8a0d51add9 merge upstream 2026-06-02 11:43:59 +00:00
misha
634d83fd61 feat(tests): fixed tests 2026-05-28 12:11:29 +03:00
misha
9e9f2a9f45 feat(analyzer): fixed analyzer issue 2026-05-28 10:56:07 +03:00
misha
a495f98f30 feat(ci/cd): api key for matching 2026-05-27 16:32:33 +03:00
misha
9f8f9a7aaa feat(ci/cd): location fixes 2026-05-27 13:13:42 +03:00
misha
af1980930b feat(ci/cd): pods 403 error fix 2026-05-27 13:11:09 +03:00
misha
1c262da81a feat(ci/cd): make fstlane to update the certificates and profiles 2026-05-27 13:03:34 +03:00
misha
8a617509de version changed 2026-05-25 08:10:10 +03:00
misha
73cec1a01e feat(vide_calls): gms calls handling 2026-05-25 08:07:20 +03:00
fb99a42115 Merge pull request 'feat(video_calls)' (#980) from misha/eatvio_app:issue-974 into main
Reviewed-on: eatvio/eatvio_app#980
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-05-25 02:22:48 +00:00
misha
1acb158f36 feat(vidoe_calls): global cideo call state, connection, loading and error screens for video calls 2026-05-12 07:47:41 +03:00
misha
54c27c28cd feat(test): updated tests to increase tests coverage 2026-05-06 14:12:34 +03:00
misha
fe243965e3 feat(test): 70% tests coverage 2026-05-06 05:27:25 +03:00
misha
56313a4fcc Merge branch 'issue-974' of ssh://10.55.5.123:222/misha/eatvio_app into issue-974 2026-05-05 10:52:00 +03:00
misha
cb36ef8e07 Merge remote-tracking branch 'upstream/main' into issue-974 2026-05-05 10:51:20 +03:00
misha
b2072ab626 feat(video_calls): fixed falling test 2026-05-05 10:40:11 +03:00
5b72684c95 merge upstream 2026-05-05 05:17:22 +00:00
misha
91ad51d340 feat(video_calls): first impl for main video calls screen 2026-05-05 08:09:24 +03:00
01282a35cb merge upstream 2026-04-19 17:51:49 +00:00
5d86b7c71b Merge pull request 'version changed' (#971) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#971
2026-04-17 14:17:46 +00:00
misha
50aefde842 version changed 2026-04-17 17:17:04 +03:00
0991ac555e merge upstream 2026-04-17 14:13:58 +00:00
5fbd578463 Merge pull request 'ci/cd: fastlane version' (#970) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#970
2026-04-17 11:13:08 +00:00
misha
426bd49aa1 ci/cd: fastlane version 2026-04-17 14:12:10 +03:00
c6fc20d217 Merge pull request 'version changed' (#968) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#968
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-04-17 08:30:02 +00:00
misha
17e18dc68b version changed 2026-04-17 11:08:18 +03:00
b5a889cbb0 merge upstream 2026-04-16 17:22:23 +00:00
d483295aab Merge pull request 'feat(pushNotifications): fixed push notifications navigation' (#948) from misha/eatvio_app:push-notifications-navigation into main
Reviewed-on: eatvio/eatvio_app#948
Reviewed-by: Анатолий Полоз <t0ly.od@ya.ru>
2026-04-16 09:38:30 +00:00
misha
c8284338aa feat(image_compress_utility): adde test for corupted images 2026-04-15 16:27:27 +03:00
misha
03ec91a595 feat(image_compress_utility): improved compressing logic 2026-04-15 15:50:09 +03:00
misha
e814683984 version changed 2026-04-14 09:44:12 +03:00
misha
684415ef5b feat(setting): added profile data apdating for sttings screen, added validation for general info form 2026-04-14 09:28:02 +03:00
misha
631ceb2b7a version changed 2026-04-08 12:47:07 +03:00
misha
71a405c63f feat(notifications): changed navigation flow from Cancelled diet and started diet notifications 2026-04-08 12:43:15 +03:00
misha
4ca90eb2df feat(push_navigation): fixed navigation to chat screen 2026-04-08 12:14:43 +03:00
misha
f17f1ecb57 version changed 2026-04-07 10:32:10 +03:00
misha
a71bcc752d feat(fixes): fixed analyzer issue 2026-04-07 10:06:04 +03:00
misha
aac085def4 feat(app): refactoring of sentry using, feat(become_consultant): fixed possible infinite loading, feat(push_notifications): fixed push navigation from paid plan push 2026-04-07 10:05:11 +03:00
985154c863 merge upstream 2026-04-01 16:15:21 +00:00
misha
b6b13b1db5 version update 2026-04-01 13:21:19 +03:00
misha
6629286bf1 feat(CI/CD): changed gitea user token name 2026-04-01 10:59:54 +03:00
misha
966bc23f0b feat(CI/CD): removed proxy server 2026-04-01 10:49:50 +03:00
misha
a13b623ca2 feat(feed): fixed comments state updating in feed, feat(consultantRegistration): fixed registration flow for users with unverified phone, feat(tests): fixed tests coverage 2026-04-01 10:37:59 +03:00
misha
ee2dd75a94 feat(ci/cd): added test coverage verification 2026-03-31 10:20:43 +03:00
misha
c450a41715 feat(ci/cd): added token for repo 2026-03-30 10:33:46 +03:00
misha
55b6b75134 feat(ci/cd): env repo changed 2026-03-30 10:16:13 +03:00
misha
335e36dd18 feat(pushNotifications): fixed push notifications navigation 2026-03-26 18:06:20 +03:00
7106bde4ae Merge pull request 'fix 939, 927' (#940) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#940
Reviewed-by: misha <misha@noreply.localhost>
2026-03-26 08:58:17 +00:00
mso7nueh
4f241f7db6 feat: try push handling 2026-03-18 15:39:13 +03:00
mso7nueh
3d7755a9a2 feat: Introduce AppRouter for centralized application routing and deep link handling, and create push_navigation_handler for push notification navigation. 2026-03-17 16:33:54 +03:00
mso7nueh
decc8c63e6 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2026-03-17 12:32:31 +03:00
mso7nueh
ad5b48ef1b Fix merge conflicts with upstream main by retaining list refresh logic 2026-03-17 12:32:02 +03:00
mso7nueh
e8dc0138e2 Merge pull request 'feat(recipes, diets)' (#938) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#938
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-03-17 09:19:25 +00:00
mso7nueh
96896671b6 merge upstream 2026-03-17 09:18:48 +00:00
mso7nueh
5e2f0430d9 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2026-03-17 12:18:25 +03:00
mso7nueh
2da3b10e63 feat: Implement 'My Recipes' feature, add diary moderation request modal, and introduce diary repository. 2026-03-17 12:18:17 +03:00
misha
5cb121d733 fat(recipes, diets): added list refreshing 2026-03-16 10:32:12 +03:00
f1e07b3d86 merge upstream 2026-03-12 14:13:03 +00:00
mso7nueh
109013c25c Merge pull request 'feat(diary)' (#931) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#931
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-03-12 13:49:32 +00:00
misha
f5d14d213f Merge remote-tracking branch 'upstream/main' 2026-03-12 16:04:58 +03:00
misha
26ae28a705 feat(tests): fixed test errors 2026-03-12 14:41:16 +03:00
mso7nueh
7672477c03 Merge pull request 'Обновить pubspec.yaml' (#932) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#932
2026-03-11 12:15:49 +00:00
mso7nueh
07277d6e48 Обновить pubspec.yaml 2026-03-11 12:15:33 +00:00
misha
9d1bedff26 feat(diary): fixed consultant portion comments and day finishing errors handling 2026-03-11 11:55:10 +03:00
062079e7f1 merge upstream 2026-03-10 04:16:36 +00:00
misha
e39638be7f feat(notifications): removed unknown notification from layoute 2026-03-05 13:44:33 +03:00
442fc0ec14 Merge pull request 'feat(consultant_registration)' (#924) from misha/eatvio_app:issue-914 into main
Reviewed-on: eatvio/eatvio_app#924
2026-03-04 07:56:21 +00:00
a8f8cc8eb0 Merge pull request 'feat(notifications)' (#921) from misha/eatvio_app:issue-911 into main
Reviewed-on: eatvio/eatvio_app#921
2026-03-04 07:55:58 +00:00
misha
3892bf00aa fix: analizer 2026-03-04 09:25:11 +03:00
misha
a492c2d964 Merge remote-tracking branch 'upstream/main' into issue-914 2026-03-04 09:21:45 +03:00
misha
89268e1132 Merge remote-tracking branch 'upstream/main' into issue-911 2026-03-04 09:08:17 +03:00
60753a13d2 Merge pull request 'Рецепты и мелкие правки' (#920) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#920
2026-03-04 06:07:24 +00:00
misha
08eeea6ba4 feat(notifications): added push notifications navigation handling and fixed ws notification parsing 2026-03-04 09:05:00 +03:00
misha
58d99424a0 Merge remote-tracking branch 'upstream/main' into issue-911 2026-02-27 13:15:09 +03:00
misha
c6cdb5bf01 Merge branch 'main' of ssh://10.55.5.123:222/misha/eatvio_app into issue-911 2026-02-27 13:14:47 +03:00
mso7nueh
50deaeddd1 feat: Add Android CI workflow for testing and building APKs 2026-02-27 12:23:32 +03:00
mso7nueh
56fb2f1bac feat: Add Android CI workflow for testing and building APKs 2026-02-27 12:10:43 +03:00
mso7nueh
24185cc875 feat: Implement Gitea Actions CI/CD workflows for Android app testing, building, and deployment. 2026-02-26 16:34:45 +03:00
mso7nueh
9e7bf258d0 feat: Add Gitea workflow for Android app testing and APK build. 2026-02-26 16:18:56 +03:00
mso7nueh
098633b3ac Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2026-02-26 16:15:32 +03:00
mso7nueh
c3aa77b02d feat: Add GitHub Actions workflow for Android app testing, coverage analysis, and release APK building. 2026-02-26 16:14:55 +03:00
Username1548
2d5384f2ec fix: ci/cd 2026-02-26 14:10:41 +03:00
Username1548
1c7e494f90 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2026-02-26 14:00:52 +03:00
Username1548
8bbe2613d2 fix: ci/cd 2026-02-26 14:00:14 +03:00
mso7nueh
5f6ceab6a1 feat: Add Gitea CI/CD workflows for Android build, test, and coverage analysis. 2026-02-26 13:59:19 +03:00
Username1548
250a3f5d73 fix: CI/CD 2026-02-26 13:46:16 +03:00
mso7nueh
3e0d8b6c27 feat: Add GitHub Actions workflow for Android app testing and APK build. 2026-02-26 13:15:55 +03:00
mso7nueh
9ed3b37272 feat: Add Gitea Actions workflow for Flutter Android testing and building with coverage analysis. 2026-02-26 13:12:07 +03:00
mso7nueh
ae628a6ecc feat: Add Gitea workflows for Android APK build and comprehensive testing. 2026-02-26 13:04:20 +03:00
mso7nueh
88d8ec52d9 feat: add Android CI workflow for testing, coverage analysis, and APK build 2026-02-26 13:02:26 +03:00
mso7nueh
937921e26f feat: Add Gitea Actions workflow for Android app testing, building, and artifact upload. 2026-02-26 12:27:14 +03:00
mso7nueh
d324bd6540 feat: Add Gitea workflow files for Android testing and building. 2026-02-26 11:57:29 +03:00
mso7nueh
5766e216c8 feat: Add Gitea CI/CD workflows for Android app building and comprehensive testing with coverage. 2026-02-26 11:38:59 +03:00
mso7nueh
ee9b97b694 feat: Add Gitea Actions workflow for Flutter Android testing and release APK building. 2026-02-26 11:35:23 +03:00
mso7nueh
31eec6c9d7 feat: Implement Gitea Actions CI/CD workflows for Flutter Android app testing, building, and TestFlight deployment. 2026-02-26 11:21:48 +03:00
mso7nueh
5fae3eb5e8 feat: Add CI/CD workflows for building, testing, and deploying Android and iOS applications. 2026-02-26 11:18:51 +03:00
mso7nueh
b0a167b9e9 feat: Add MyRecipesScreen to display user's recipes, manage active/drafted states, and navigate to recipe creation. 2026-02-26 03:00:32 +03:00
mso7nueh
0b2e026d1d feat: Introduce user-generated content features, including recipe creation and management, and blog post creation. 2026-02-26 02:52:08 +03:00
mso7nueh
0641513ebe feat: Add user recipe management and creation functionality, including models, widgets, cubits, repositories, and tests. 2026-02-25 13:10:07 +03:00
misha
be0a99b164 fix: ci/cd 2026-02-25 13:02:28 +03:00
misha
8b1d08b2aa fix: ci/cd 2026-02-25 13:00:38 +03:00
misha
6dab0d159b feat(consultant_registration): added new consultant registration flow 2026-02-25 07:08:05 +03:00
24652884ee merge upstream 2026-02-24 11:02:11 +00:00
mso7nueh
5167766dbf merge upstream 2026-02-24 09:22:15 +00:00
cc79e40df9 Merge pull request 'feat(my_diets): draft diets fixes' (#901) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#901
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-02-24 07:52:31 +00:00
misha
cdc5936d3c analizer: fixed analizer issues 2026-02-20 13:22:16 +03:00
misha
67e770f5d0 review: fixed review issues 2026-02-20 13:20:17 +03:00
misha
6f666a8859 feat(tests): fixed notifications tests 2026-02-18 20:19:23 +03:00
misha
c540cbe6df feat(notifications): added navigation from different types of notifications 2026-02-18 19:45:32 +03:00
mso7nueh
6c4104e9ea feat: Issue-919 2026-02-18 18:08:00 +03:00
mso7nueh
6d1bcb85fb feat(plans): Issue-918 2026-02-18 18:05:59 +03:00
mso7nueh
9753644570 feat(recipe): drafts 2026-02-18 18:04:01 +03:00
mso7nueh
75983818d1 chore: Remove temporary test and analysis output files. 2026-02-16 18:20:00 +03:00
mso7nueh
5b149e2fd2 refactor: Corrected typo in MyRecipesCubit filename and updated related tests, widgets, services, and DI registrations. 2026-02-16 18:16:26 +03:00
misha
699148b202 feat(my_diets): fixed navigation to diet creation screen 2026-02-16 15:33:15 +03:00
mso7nueh
6e7894b911 build: Remove eatvio/ from .gitignore. 2026-02-16 12:49:09 +03:00
mso7nueh
d4f41fe6cf feat: implement recipe drafting functionality and refactor MyRecipesTab to be stateless 2026-02-16 12:49:09 +03:00
mso7nueh
bb97c395dd feat: Implement comprehensive navigation logic for various notification types within the NotificationWidget. 2026-02-12 15:55:11 +03:00
ea9cdb93d4 merge upstream 2026-02-11 17:26:07 +00:00
misha
b7804db49d feat(my_diets): merge conflict fix 2026-02-11 16:54:08 +03:00
misha
e90a466a5b Merge remote-tracking branch 'upstream/main' 2026-02-11 16:26:08 +03:00
misha
5f30aaeb2a feat(my_diets): merge conflict fixes 2026-02-11 16:23:48 +03:00
mso7nueh
516dfa4158 Merge pull request 'Улучшение валидации и пользовательского опыта в регистрациях и создании диет' (#910) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#910
Reviewed-by: misha <misha@noreply.localhost>
2026-02-11 09:45:19 +00:00
mso7nueh
ae07851396 test: update OAuth verification mock to use anyNamed arguments for email and phone. 2026-02-10 18:47:53 +03:00
mso7nueh
34eccb7db5 feat: Enhance OAuth error state to include specific registration validation errors and pass email in the verification request. 2026-02-10 18:36:18 +03:00
misha
042cc0ea20 Merge remote-tracking branch 'upstream/main' 2026-02-10 12:38:08 +03:00
misha
f81aebe9d8 feat(tests): added new tests and updated fixtures 2026-02-10 08:02:50 +03:00
mso7nueh
d70aaf955f feat: Implement auto-scrolling to the first validation error in the create diet form and refine image validation logic. 2026-02-09 23:15:12 +03:00
misha
c91e83adaf feat(my_diets): fixed draft, active and personal diets creation, updating 2026-02-09 10:39:51 +03:00
mso7nueh
531f732b1a Merge pull request 'feat: enhance BottomNavigationBarWidget with DEV logo display and refactor page list initialization' (#907) from mso7nueh/eatvio_app:feat_add_dev_marker_logo into main
Reviewed-on: eatvio/eatvio_app#907
Reviewed-by: misha <misha@noreply.localhost>
2026-02-06 09:54:34 +00:00
mso7nueh
d10f2f1356 Merge pull request 'feat: update add product modal to reflect selection state with icons' (#906) from mso7nueh/eatvio_app:feat_add_product_modal into main
Reviewed-on: eatvio/eatvio_app#906
Reviewed-by: misha <misha@noreply.localhost>
2026-02-06 09:54:25 +00:00
7c4010b275 merge upstream 2026-02-06 07:09:12 +00:00
mso7nueh
bf110b70c1 feat: enhance BottomNavigationBarWidget with DEV logo display and refactor page list initialization 2026-02-05 14:41:25 +03:00
mso7nueh
97418e11d4 feat: update add product modal to reflect selection state with icons 2026-02-05 14:40:55 +03:00
mso7nueh
225077907f Merge pull request 'build: bump version to 1.3.17+97' (#903) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#903
2026-02-04 12:50:52 +00:00
mso7nueh
296adc8229 build: bump version to 1.3.17+97 2026-02-04 15:50:28 +03:00
mso7nueh
7dd7e3b488 Merge pull request 'feat: Integrate Huawei Mobile Services (HMS) by updating configuration, adding manifest metadata, and differentiating Huawei devices for token submission.' (#902) from mso7nueh/eatvio_app:fix_hms_push_token into main
Reviewed-on: eatvio/eatvio_app#902
Reviewed-by: misha <misha@noreply.localhost>
2026-02-04 12:49:13 +00:00
mso7nueh
a496edaf4c feat: Integrate Huawei Mobile Services (HMS) by updating configuration, adding manifest metadata, and differentiating Huawei devices for token submission. 2026-02-04 13:23:58 +03:00
misha
400cc004ef fix: analizer fixed 2026-02-04 12:21:09 +03:00
misha
beda152df0 fix: temporary removed tests from ci/cd 2026-02-04 11:46:47 +03:00
misha
42ffde820d feat(my_diets): draft diets fixes 2026-02-04 11:38:53 +03:00
4458aaf74f merge upstream 2026-02-04 07:52:24 +00:00
mso7nueh
adb7b0bd74 Merge pull request 'chore: update project version' (#898) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#898
2026-02-03 12:12:43 +00:00
mso7nueh
a768eefed0 chore: update project version 2026-02-03 15:12:07 +03:00
mso7nueh
0ac50d6d18 Merge pull request 'feat: Add local Mulish font family and remove Google Fonts dependency.' (#897) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#897
2026-02-03 11:50:27 +00:00
mso7nueh
a0d8fda50d feat: Add local Mulish font family and remove Google Fonts dependency. 2026-02-03 14:49:49 +03:00
mso7nueh
1d286fa8d9 Merge pull request 'feat: introduce My Diets and Create Diet features with associated UI, state management, and data handling.' (#889) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#889
Reviewed-by: misha <misha@noreply.localhost>
2026-02-03 08:16:56 +00:00
mso7nueh
c2a5e7305e feat: add a customizable FeedIconButton widget that supports text, IconData, or SvgPicture. 2026-02-02 15:32:10 +03:00
mso7nueh
bbb1b28692 merge upstream 2026-02-02 12:12:12 +00:00
mso7nueh
21a65caea9 Обновить .gitea/workflows/build.yml 2026-02-02 12:09:13 +00:00
mso7nueh
eac366e9ae Обновить .gitea/workflows/test.yml 2026-02-02 12:09:00 +00:00
mso7nueh
278f4d7e10 feat: Add numerous repository implementations, cubits, and core utilities across various features, and update dependencies. 2026-02-02 14:24:17 +03:00
mso7nueh
ac5504a514 feat: Implement FeedScreen with dynamic content display, search functionality, and filtering options. 2026-01-30 14:05:45 +03:00
mso7nueh
843e1ce4dd test: add unit tests for ValidationUtils covering email, phone, URL, password, username, text, title, and description length validations, along with phone normalization and error message generation. 2026-01-29 16:01:18 +03:00
mso7nueh
db6db89567 feat: add unit tests for TokenInterceptor's request and error handling logic. 2026-01-29 15:57:11 +03:00
mso7nueh
044d86e710 fix mask formatter in phone 2026-01-29 15:49:13 +03:00
mso7nueh
4ff880e079 feat: add register via social screen 2026-01-29 15:42:02 +03:00
mso7nueh
05b9ca17c7 feat: Introduce token interceptor for authentication, WebSocket manager for real-time updates, and a new menu screen. 2026-01-29 15:00:04 +03:00
f20f871c88 merge upstream 2026-01-28 15:45:54 +00:00
mso7nueh
a1c0c2694b test: Add basic widget tests for MyDietsTab and MyDietWidget, and integration tests for create_diet. 2026-01-28 18:16:24 +03:00
mso7nueh
2d7407ce99 feat: introduce My Diets and Create Diet features with associated UI, state management, and data handling. 2026-01-28 17:32:29 +03:00
62fe5ebfa0 Merge pull request 'feat(consultant)' (#888) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#888
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-01-28 13:31:42 +00:00
misha
3dc36ab52d feat(consultants): fixed infinite loading after verifying phone 2026-01-28 12:56:04 +03:00
190e212eb4 Merge pull request 'feat(tests)' (#876) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#876
2026-01-28 09:44:50 +00:00
misha
cf3d1a945c Merge remote-tracking branch 'upstream/main' 2026-01-28 11:52:38 +03:00
mso7nueh
c54915f45d Обновить .gitea/workflows/test-flight-cd.yaml 2026-01-27 15:17:51 +00:00
mso7nueh
b188570882 Обновить .gitea/workflows/test-flight-cd.yaml 2026-01-27 15:14:00 +00:00
mso7nueh
d0794670f6 Обновить .gitea/workflows/test-flight-cd.yaml 2026-01-27 15:07:38 +00:00
mso7nueh
3b53ed6f7d Merge pull request 'Some fixes' (#873) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#873
Reviewed-by: misha <misha@noreply.localhost>
2026-01-27 14:57:23 +00:00
mso7nueh
a003814265 chore: update Huawei dependencies in build.gradle to latest versions for improved functionality 2026-01-27 16:56:22 +03:00
mso7nueh
e99465a550 chore: add kotlin-parcelize plugin to build.gradle for improved parceling support 2026-01-27 16:29:17 +03:00
mso7nueh
a01f3914c4 fix: update file_picker dependency version format in pubspec.yaml 2026-01-27 15:50:11 +03:00
mso7nueh
15f9149cfd feat: Introduce Gitea workflows for Android testing, coverage analysis, and build environment setup. 2026-01-27 15:14:38 +03:00
mso7nueh
79df8c5f9a feat: introduce DiaryCubit for managing user diary and diet plans, and add new unit tests for various features. 2026-01-27 14:33:21 +03:00
mso7nueh
a93da1b505 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2026-01-27 13:44:39 +03:00
mso7nueh
8144013747 feat: diary add modal and error dialogs 2026-01-27 13:44:35 +03:00
misha
7bac2a13ac Merge remote-tracking branch 'upstream/main' 2026-01-26 16:55:08 +03:00
misha
29589ef6fd feat(tests): test coverage is 70.5 2026-01-26 16:38:15 +03:00
mso7nueh
97a6fe57e9 merge upstream 2026-01-26 12:30:55 +00:00
mso7nueh
8309498d9e feat: Increment app version and add tests for glossary moderation request modal widget. 2026-01-26 14:51:22 +03:00
mso7nueh
aa098b31bc feat: add glossary moderation request modal widget to handle new product submissions. 2026-01-26 14:42:43 +03:00
mso7nueh
7a85c65918 feat: add smoke tests for the DietPreviewScreen to verify rendering and information display 2026-01-26 14:39:24 +03:00
mso7nueh
6ff35fd162 feat: Implement DietPreviewScreen to display comprehensive diet details including schedule and nutritional information. 2026-01-26 14:34:38 +03:00
mso7nueh
6811b325be feat: Implement core authentication logic with AuthCubit and introduce a comprehensive email verification flow. 2026-01-26 14:31:39 +03:00
misha
92205c09d6 feat(tests): test coverage is 70.4 2026-01-23 12:40:17 +03:00
008dba9fed Merge pull request 'feat(tests)' (#867) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#867
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-01-23 09:20:37 +00:00
f61fb8c6b3 merge upstream 2026-01-23 07:40:43 +00:00
mso7nueh
55ca558bfb fix: analyzer 2026-01-22 12:26:57 +03:00
mso7nueh
91499ae207 feat: implement diary repository and cubit for managing daily food entries, nutritional data, and user interactions. 2026-01-22 00:58:56 +03:00
mso7nueh
4bacdf5e76 feat: implement UI for managing recipe ingredients with glossary search, nutritional calculation, and moderation request functionality. 2026-01-22 00:50:20 +03:00
mso7nueh
e76c1aed20 feat: implement recipe creation feature including state management, ingredient/step management, image handling, and validation. 2026-01-22 00:42:30 +03:00
mso7nueh
de8f879f59 feat: Implement social authentication facade for VK, OK.ru, Mail.ru, and Yandex. 2026-01-21 23:54:08 +03:00
misha
f6809a06b3 feat(tests): test coverage is 69.2 2026-01-21 09:19:41 +03:00
misha
775d4fb80f Merge remote-tracking branch 'upstream/main' 2026-01-20 12:00:44 +03:00
mso7nueh
64e9df69f7 Merge pull request 'feat: Implement glossary moderation, notifications, product modals, social authentication, and internationalization.' (#868) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#868
Reviewed-by: misha <misha@noreply.localhost>
2026-01-19 18:46:05 +00:00
3d14dee4e9 merge upstream 2026-01-19 13:07:28 +00:00
mso7nueh
6ccfcdedda feat: create AddProductModal for adding and editing diary product portions with glossary search functionality. 2026-01-19 16:06:19 +03:00
mso7nueh
d3c8034b8f feat: Implement glossary moderation, notifications, product modals, social authentication, and internationalization. 2026-01-19 16:00:30 +03:00
misha
44ede73ceb feat(tests): tests coverage 67.2 2026-01-19 12:32:11 +03:00
2c63990afc Merge pull request 'feat(tests)' (#864) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#864
Reviewed-by: mso7nueh <mso7nueh@mail.ru>
2026-01-19 09:12:46 +00:00
38647b4ac6 merge upstream 2026-01-15 22:01:54 +00:00
mso7nueh
eb69b253bc Merge pull request 'chore: enhance markdown processing and UI adjustments in comments input' (#852) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#852
Reviewed-by: misha <misha@noreply.localhost>
2026-01-15 10:28:12 +00:00
mso7nueh
f26886a7c5 Merge pull request 'fix: splash screen stuck' (#861) from mso7nueh/eatvio_app:fix_splash_stuck into main
Reviewed-on: eatvio/eatvio_app#861
Reviewed-by: misha <misha@noreply.localhost>
2026-01-15 10:27:57 +00:00
misha
13ccf56df0 feat(tests): updated tests coverage to 66.5% 2026-01-14 18:47:11 +03:00
mso7nueh
c0032f7a95 feat: enhance Firebase messaging error logging and simplify BottomNavigationBarWidget by removing profileModel dependency 2026-01-14 16:09:07 +03:00
mso7nueh
4852d2cf10 refactor: replace HTML rendering with MarkdownHtmlWidget across various components for consistent markdown processing 2026-01-14 14:48:32 +03:00
mso7nueh
41e96c63c6 feat(token_storage): add clearCache method for testing and ensure fresh state in tests 2026-01-14 13:02:24 +03:00
mso7nueh
c786821275 fix: handle null context in MarkdownHtmlWidget and improve test stability with pumpAndSettle calls 2026-01-13 13:03:58 +03:00
mso7nueh
7b425e56f1 chore: remove unused markdown_utils import from expandable_text.dart 2026-01-13 12:37:10 +03:00
mso7nueh
bf2ba1fbda feat: integrate MarkdownHtmlWidget for improved markdown rendering in blog and diet components 2026-01-13 12:36:12 +03:00
c836b600c6 merge upstream 2026-01-13 09:25:36 +00:00
mso7nueh
d206e7ec12 refactor: implement lazy initialization for global BlocProviders and enhance Firebase initialization with timeout handling 2026-01-13 12:22:22 +03:00
mso7nueh
a778257215 chore: enhance markdown processing and UI adjustments in comments input 2026-01-12 16:31:22 +03:00
mso7nueh
497ff19cfa Merge pull request 'fix(registration): update navigation to verify email screen and streamline error message display' (#845) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#845
2025-12-26 13:26:04 +00:00
mso7nueh
bb59552e3e fix(registration): update navigation to verify email screen and streamline error message display 2025-12-26 16:17:34 +03:00
mso7nueh
55b2bb0436 Merge pull request 'refactor(tests): update password and sex widget tests to use const constructors for RegistrationStateV2' (#841) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#841
2025-12-26 10:54:42 +00:00
mso7nueh
90746d0be7 refactor(tests): update password and sex widget tests to use const constructors for RegistrationStateV2 2025-12-26 13:54:10 +03:00
mso7nueh
d70d172c69 chore: update version to 1.3.11+91 in pubspec.yaml; clean up whitespace in various files 2025-12-26 13:51:44 +03:00
mso7nueh
4e23992d22 chore: bump version number to 1.3.11+91 in pubspec.yaml 2025-12-26 13:37:41 +03:00
mso7nueh
7a846ed218 chore: add blank lines for improved readability in multiple files 2025-12-26 13:35:08 +03:00
mso7nueh
fcc2936c22 Merge pull request 'feat(tests), feat(registration), feat(diary), feat(oAuth)' (#835) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#835
2025-12-25 14:19:38 +00:00
misha
b11cf2c0b0 Merge remote-tracking branch 'upstream/main' 2025-12-25 16:36:23 +03:00
misha
0ead14bca5 feat(registration): added email verification, feat(diary): fixed moderation request, feat(oauth): fixed email and phone verification 2025-12-25 16:31:52 +03:00
mso7nueh
08e56d9777 Merge pull request 'chore: update Flutter version in CI workflow from 3.38.1 to 3.38.5' (#831) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#831
2025-12-25 12:55:49 +00:00
misha
99659f7ea1 feat(tests): increased tests coverage 2025-12-25 12:56:38 +03:00
mso7nueh
e158d812e4 refactor: clean up imports and improve code readability across various files 2025-12-24 17:54:35 +03:00
mso7nueh
3d774267ca chore: update pubspec.yaml dependencies and Flutter SDK version; add blank lines in various files for improved readability 2025-12-24 14:52:51 +03:00
mso7nueh
aeb89a9aba merge upstream 2025-12-23 13:01:33 +00:00
mso7nueh
a4f5bfdb4d Merge pull request 'feat(tests)' (#832) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#832
2025-12-23 13:01:15 +00:00
misha
5b705dfb72 feat(tests): test coverage 60% 2025-12-23 10:59:56 +03:00
mso7nueh
a792dcd163 chore: update dependencies in pubspec.yaml for retrofit and development tools 2025-12-23 10:37:41 +03:00
mso7nueh
9c7ca14017 chore: update Flutter version in CI workflow from 3.38.1 to 3.38.5 2025-12-23 10:21:15 +03:00
mso7nueh
38118055a5 Merge pull request 'fix: ui overflow nav-bar, name files in chat, qr-code scanner in dev-tools, message field size, keyboard type' (#830) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#830
2025-12-22 13:53:25 +00:00
mso7nueh
5d6e25858b test(chat): update chat service test to validate message response and ensure correct message model handling 2025-12-22 16:52:40 +03:00
mso7nueh
42b443c3ba fix: ui overflow nav-bar, name files in chat, qr-code scanner in dev-tools, message field size, keyboard type 2025-12-22 16:48:13 +03:00
mso7nueh
21f7c40cde Merge pull request 'feat(chat): enhance chat message model and repository to support improved message handling and parsing' (#816) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#816
2025-12-19 12:36:00 +00:00
mso7nueh
f56092d88f feat(chat): enhance chat message model and repository to support improved message handling and parsing 2025-12-19 15:35:37 +03:00
mso7nueh
2b97c0f57d Merge pull request 'feat(router): enhance deep link handling with logging and support for various content types' (#815) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#815
2025-12-19 12:16:12 +00:00
mso7nueh
a1304e4612 feat(router): enhance deep link handling with logging and support for various content types 2025-12-19 15:15:54 +03:00
mso7nueh
7b534cf891 Merge pull request 'feat(chat): add plan order message widget and enhance chat bubble to support message types' (#814) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#814
2025-12-19 12:15:42 +00:00
mso7nueh
22b2e5f249 feat(chat): add plan order message widget and enhance chat bubble to support message types 2025-12-19 15:08:11 +03:00
mso7nueh
5dfdbe4543 Merge pull request 'feat(ios): read and set Flutter build number in Fastfile for app store deployment' (#813) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#813
2025-12-17 12:52:57 +00:00
mso7nueh
5c9a9c22ba feat(ios): read and set Flutter build number in Fastfile for app store deployment 2025-12-17 15:52:34 +03:00
mso7nueh
4f920359c8 Merge pull request 'implement OAuth verification request and confirmation flow with error handling and UI updates' (#811) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#811
2025-12-17 12:42:26 +00:00
mso7nueh
2ab3bc1cf0 feat(auth): implement OAuth verification request and confirmation flow with error handling and UI updates 2025-12-17 15:41:38 +03:00
mso7nueh
91bd8f9d68 merge upstream 2025-12-17 07:48:37 +00:00
9c6f6bdfb1 Merge pull request 'feat(diary): meal summary fix' (#810) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#810
2025-12-17 07:33:36 +00:00
misha
fe1e81e455 feat(diary): meal summary fix 2025-12-17 08:38:13 +03:00
mso7nueh
b7e064a560 test(tests): add whitespace to multiple test files for consistency and improved readability 2025-12-16 14:18:25 +03:00
mso7nueh
f1b7a24044 feat(coverage): enhance coverage analysis script to filter generated files and generate detailed markdown report for files with less than 100% coverage 2025-12-15 23:37:17 +03:00
dfe11a6df2 merge upstream 2025-12-12 09:55:45 +00:00
mso7nueh
cb441b4027 Merge branch 'mso7nueh-main' 2025-12-12 11:38:22 +03:00
7282fea59a Merge pull request 'changed version' (#807) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#807
2025-12-12 07:52:00 +00:00
misha
4adec4dbbc changed version 2025-12-12 10:50:37 +03:00
mso7nueh
d5b0e972a5 chore(version): update app version to 1.3.7+87 and adjust related iOS project settings 2025-12-12 10:43:26 +03:00
mso7nueh
391efeb8dd fix(chat): initialize startDate to current date when personal diet is not enabled and streamline widget layout for improved readability 2025-12-12 10:38:53 +03:00
d115af6f8e Merge pull request 'feat(tests)' (#805) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#805
2025-12-12 07:15:24 +00:00
mso7nueh
2408443a26 test(tests): add whitespace to multiple test files for consistency and improved readability 2025-12-11 21:43:36 +03:00
mso7nueh
c378c7fc16 test(tests): add extensive widget tests for MarkdownEditor and CommentsActionsBottomSheet, improving test coverage and functionality validation 2025-12-11 21:19:41 +03:00
misha
070a3e39e7 feat(tests): added services tests and fixtures 2025-12-11 15:53:35 +03:00
mso7nueh
d1753e99f8 Merge pull request 'tests' (#804) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#804
2025-12-11 11:13:28 +00:00
mso7nueh
960afbd6ed chore(dependencies): add webview_flutter_platform_interface package to pubspec.yaml and clean up test files by removing unnecessary whitespace 2025-12-11 14:12:41 +03:00
mso7nueh
70e4a42e98 test(tests): add comprehensive unit tests for various models and repositories, enhancing test coverage and ensuring correct functionality 2025-12-09 16:19:48 +03:00
mso7nueh
04061cb4c1 Merge pull request 'chore(version): update app version to 1.3.6+86 and filter active plans in PlansRepository' (#802) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#802
2025-12-08 09:11:29 +00:00
mso7nueh
edd064d20d chore(version): update app version to 1.3.6+86 and filter active plans in PlansRepository 2025-12-08 12:10:19 +03:00
mso7nueh
cdb7378265 Merge pull request 'chore(version): update app version to 1.3.5+85 and improve test coverage reporting in CI' (#801) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#801
2025-12-08 08:55:58 +00:00
mso7nueh
746d366c18 refactor(tests): replace 'final' with 'const' for improved performance in various test files 2025-12-08 11:32:40 +03:00
mso7nueh
c2a506cdbf chore(version): update app version to 1.3.5+85 and improve test coverage reporting in CI 2025-12-08 11:19:08 +03:00
mso7nueh
abe4985f0e Merge pull request 'main' (#800) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#800
2025-12-04 13:14:34 +00:00
mso7nueh
ca06b2bd0f chore(tests): remove unused tests and clean up test files for MyDietsRepository and MyPlansCubit 2025-12-04 16:13:36 +03:00
mso7nueh
04c932646d Merge resolve-conflicts into main 2025-12-04 16:13:30 +03:00
mso7nueh
3d4363185b Resolve merge conflicts: add network_image_mock to pubspec.yaml 2025-12-04 15:50:53 +03:00
mso7nueh
953230b387 feat(dependencies): add rxdart package and improve string extension methods for better handling of empty strings and gender parsing 2025-12-04 15:45:54 +03:00
mso7nueh
9d845e1264 chore(dependencies): add gpassword package to pubspec.yaml 2025-12-03 18:42:48 +03:00
mso7nueh
32de60742e Merge mso7nueh-main into main: resolve conflicts in pubspec.yaml and feed_repository_test.dart 2025-12-03 18:38:37 +03:00
mso7nueh
3923b61c67 Merge mso7nueh-main into main: resolve conflicts 2025-12-03 18:34:25 +03:00
mso7nueh
0cd8e662d9 feat(blog): enhance markdown processing in blog, diet, plan, recipe, and my diet widgets to auto-convert URLs to markdown links and improve link handling 2025-12-03 18:20:44 +03:00
89ea73fc59 Merge pull request 'feat(tests): widget and unit tests for chat' (#796) from misha/eatvio_app:issue-795 into main
Reviewed-on: eatvio/eatvio_app#796
2025-12-03 15:18:49 +00:00
misha
9e33063c30 feat(tests): widget and unit tests for chat 2025-12-03 18:12:17 +03:00
mso7nueh
f3d4478c65 refactor(tests): update model instantiation to use const for improved performance 2025-12-03 06:16:34 +03:00
673aa86370 Merge pull request 'feat(tests): widget and unit tests for diets, plans and recipes' (#794) from misha/eatvio_app:issue-793 into main
Reviewed-on: eatvio/eatvio_app#794
2025-12-02 12:15:07 +00:00
misha
1738d27b82 added widget and unit tests for plans, diets, recipes 2025-12-02 12:34:13 +03:00
mso7nueh
d0becb9e11 feat(test): enhance internet connection tests with dotenv integration and async handling 2025-12-01 23:54:41 +03:00
mso7nueh
965ae2f02b feat(test): update oauth handling and improve preferences management 2025-12-01 23:51:40 +03:00
mso7nueh
9fcfac87d4 feat(test): oauth, prefs, credentials 2025-11-28 14:22:05 +03:00
mso7nueh
2a25be5aa4 feat(test): comments, auth, feed 2025-11-28 14:13:05 +03:00
b420d11996 Merge pull request 'feat(tests)' (#792) from misha/eatvio_app:issue-791 into main
Reviewed-on: eatvio/eatvio_app#792
2025-11-28 07:55:06 +00:00
misha
cbeb91a9f0 fix: analyzer issue 2025-11-28 01:00:56 +03:00
misha
9ca09e8137 Remove unwanted file 2025-11-28 00:49:38 +03:00
misha
8917f54e7b feat(tests): fixed feed tests failing and added tests for my_diets, my_plans and recipes 2025-11-28 00:46:25 +03:00
misha
626f74d20d Merge remote-tracking branch 'upstream/main' into issue-791 2025-11-27 23:50:39 +03:00
mso7nueh
7df32dabd2 feat(tests): menu, settings, remove icov, remove generated files from % tests 2025-11-27 08:18:23 +03:00
mso7nueh
2e57cd9519 feat(consultant): Issue-420 + Tests 2025-11-25 15:52:41 +03:00
misha
c6c42b0525 feat(test): repostory, cubit and widget tests for feed 2025-11-25 11:13:37 +03:00
mso7nueh
58bb766721 feat(tests): profile tests 2025-11-21 23:31:13 +03:00
mso7nueh
0be7392a39 feat(tests): add fixtures 2025-11-21 23:24:49 +03:00
35cad4e05e Merge pull request 'sync upsteam' (#3) from eatvio/eatvio_app:main into main
Reviewed-on: apoloz/eatvio_app#3
2025-11-20 17:24:29 +00:00
mso7nueh
4deda92c5e feat(tests): add fixtures 2025-11-20 16:58:56 +03:00
misha
b83d91e7f2 feat(tests): feed service tests 2025-11-20 09:54:12 +03:00
e5029f581d Merge pull request 'Updated app version' (#780) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#780
2025-11-19 13:57:51 +00:00
misha
c69fe7f0a6 Updated app version 2025-11-19 16:57:17 +03:00
fc0e9b1063 Merge pull request 'Update proj version' (#778) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#778
2025-11-19 13:48:20 +00:00
misha
453f119317 Merge remote-tracking branch 'upstream/main' 2025-11-19 16:47:43 +03:00
misha
6d0bee4da8 set build type to prod 2025-11-19 16:46:18 +03:00
misha
04d4be38d4 Update proj version 2025-11-19 16:45:08 +03:00
fa22cf5d36 Merge pull request 'feat(personalDiets)' (#760) from misha/eatvio_app:issue-756 into main
Reviewed-on: eatvio/eatvio_app#760
2025-11-19 09:58:07 +00:00
91e8348015 Merge pull request 'feat(registration): fixed registration on android devices, feat(leaders): fixed diet creation loader' (#776) from misha/eatvio_app:issue-738 into main
Reviewed-on: eatvio/eatvio_app#776
2025-11-19 08:17:36 +00:00
misha
1b948b99e3 Merge remote-tracking branch 'upstream/main' into issue-738 2025-11-19 11:16:45 +03:00
misha
b6eac3c46f feat(registration): fixed registration on android devices, feat(leaders): fixed diet creation loader 2025-11-19 11:07:16 +03:00
mso7nueh
6fa944b3df Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-11-19 04:49:05 +03:00
mso7nueh
c31411c4a2 fix: analyzer 2025-11-19 04:48:35 +03:00
mso7nueh
6214d19a14 feat(auth): tests Issue-761 2025-11-19 04:47:30 +03:00
mso7nueh
db5dddff86 feat(barcode): add scanner, upd flutter version in ci 2025-11-17 20:25:52 +03:00
mso7nueh
39775cd7a8 Merge pull request 'updated app version' (#774) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#774
2025-11-17 10:22:48 +00:00
Username1548
36e2f12e3f updated app version 2025-11-17 12:01:31 +03:00
mso7nueh
66d2533add Merge pull request 'fix: Issue-752' (#769) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#769
2025-11-14 10:34:42 +00:00
mso7nueh
425f16bfc9 fix(consultation): Issue-752 2025-11-13 19:17:28 +03:00
mso7nueh
c5e30d8f00 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-11-13 18:59:48 +03:00
mso7nueh
d0935fbaae feat: upd flutter 2025-11-13 18:58:56 +03:00
dda0aa7440 Merge pull request 'fix: tests fix' (#768) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#768
2025-11-13 08:21:48 +00:00
misha
c81327b895 fix: tests fix 2025-11-13 11:21:02 +03:00
732d667ac1 Merge pull request 'improvements: added loaders' (#766) from misha/eatvio_app:issue-580 into main
Reviewed-on: eatvio/eatvio_app#766
2025-11-13 07:13:00 +00:00
misha
ba9f4a3584 improvements: added loaders 2025-11-13 10:12:11 +03:00
mso7nueh
f63d901a55 Merge pull request 'feat(ci/cd): add coverage test' (#764) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#764
2025-11-12 11:03:23 +00:00
mso7nueh
9148a4c668 feat(ci/cd): add coverage test 2025-11-12 13:34:55 +03:00
mso7nueh
a3f0aa3e67 Merge pull request 'feat(oauth): Issue-691+180' (#762) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#762
2025-11-11 14:40:09 +00:00
mso7nueh
8a390c2a9b Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-11-11 17:38:23 +03:00
mso7nueh
92b37e77b1 fix(socail,diets): Issue-180+691 2025-11-11 17:38:15 +03:00
101c1e15af Merge pull request 'feat(registration)' (#739) from misha/eatvio_app:issue-738 into main
Reviewed-on: eatvio/eatvio_app#739
2025-11-11 07:24:37 +00:00
mso7nueh
172c05ac69 merge upstream 2025-11-10 21:16:17 +00:00
misha
4eecc458f8 fix: formatting 2025-11-10 18:59:03 +03:00
misha
4b781adb79 feat(registration): added api integration for short registration 2025-11-10 18:55:55 +03:00
misha
dc400ef5b7 feat(personalDiets): fixed notification and chat banner 2025-11-10 13:50:06 +03:00
mso7nueh
d1160ba35f feat(oauth): Issue-691 2025-11-07 01:38:00 +03:00
mso7nueh
a46ac5bb4c Merge pull request 'feat(diary_test): Issue-755' (#759) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#759
2025-11-06 19:05:03 +00:00
misha
992cb38cdd feat(personalDiets): fixed ui bugs and added new notification type for personal diet 2025-11-06 08:00:30 +03:00
mso7nueh
2a06a5476a feat(diary_test): Issue-755 2025-11-06 00:38:08 +03:00
mso7nueh
f3853b58d9 Merge pull request 'fix: Issue-757' (#758) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#758
2025-11-05 21:17:36 +00:00
mso7nueh
bbc99ec9f4 fix(settings): Issue-757 2025-11-05 23:55:48 +03:00
ff946a5938 Merge pull request 'feat(personalDiets)' (#561) from misha/eatvio_app:personalDiets into main
Reviewed-on: eatvio/eatvio_app#561
2025-10-31 10:27:20 +00:00
misha
a72c40d8ee Merge remote-tracking branch 'upstream/main' into personalDiets 2025-10-31 13:26:05 +03:00
misha
6ed7faed15 feat(personalDiets): addde base url from app config for consultation widget 2025-10-31 13:23:13 +03:00
mso7nueh
12f51d49ea fix(profile): subs screen and blog post padding 2025-10-31 12:59:02 +03:00
misha
16fccaea8e Merge remote-tracking branch 'upstream/main' into personalDiets 2025-10-31 12:41:36 +03:00
Username1548
a723673d23 Merge branch 'main' of http://gitea.office.local:3000/eatvio/eatvio_app 2025-10-31 12:39:49 +03:00
Username1548
89f697f7a6 changed app version 2025-10-31 12:38:02 +03:00
d883c9e19a Merge pull request 'feat(marketing)' (#745) from misha/eatvio_app:issue-689 into main
Reviewed-on: eatvio/eatvio_app#745
2025-10-31 09:10:18 +00:00
misha
884830f232 Merge remote-tracking branch 'upstream/main' into issue-689 2025-10-31 12:08:02 +03:00
mso7nueh
7b297f954e Merge pull request 'Issue-746' (#747) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#747
2025-10-31 08:59:06 +00:00
mso7nueh
dbd92a65ea feat(md): Issue-746 2025-10-31 00:20:21 +03:00
mso7nueh
f3af743487 merge upstream 2025-10-30 19:27:36 +00:00
Username1548
c95f1988ae commit to create new build 2025-10-30 17:13:58 +03:00
mso7nueh
35a5e6d6be merge upstream 2025-10-30 09:13:28 +00:00
mso7nueh
977b7150fe feat(md): Issue-746 2025-10-29 17:27:05 +03:00
5b81014e72 Merge pull request 'feat(InfoByOrder)' (#750) from misha/eatvio_app:issue-681 into main
Reviewed-on: eatvio/eatvio_app#750
2025-10-29 01:39:05 +00:00
misha
563d84ca12 feat(InfoByOrder): added user info to InfoByOrderScreen author card 2025-10-29 04:38:04 +03:00
06cafb4257 Merge pull request 'feat(profile)' (#749) from misha/eatvio_app:issue-742 into main
Reviewed-on: eatvio/eatvio_app#749
2025-10-29 01:02:36 +00:00
misha
a34cb01c1f feat(profile): changed profile bages layout 2025-10-29 04:01:27 +03:00
mso7nueh
8799375880 feat(md): Issue-746 2025-10-27 17:07:20 +03:00
mso7nueh
fb5a0d52bc feat(feed): mdToHtml 2025-10-24 18:55:01 +03:00
misha
2e3172bc45 Merge remote-tracking branch 'upstream/main' into personalDiets 2025-10-24 13:21:03 +03:00
misha
41313f09af feat(marketing): added marketing bottom sheet 2025-10-23 17:25:12 +03:00
mso7nueh
ce0099c385 Merge pull request 'feat(tests): blog post create' (#744) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#744
2025-10-22 15:42:27 +00:00
mso7nueh
14e4d7973e feat(tests): blog post create 2025-10-22 18:42:01 +03:00
mso7nueh
a138707111 Merge pull request 'feat(test): diet, plan, registration' (#741) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#741
2025-10-22 13:48:38 +00:00
mso7nueh
4c7dd4a12a Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-10-22 16:48:14 +03:00
mso7nueh
c2eda628dd WIP: feat(tests): blog post create 2025-10-22 16:48:08 +03:00
mso7nueh
53f2b78dfa Merge pull request 'feat(test): diet, plan, registration' (#741) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#741
2025-10-22 13:47:07 +00:00
misha
e147f6e182 feat(registration): finished layout for new registration screen 2025-10-22 15:27:02 +03:00
mso7nueh
ed612aa019 feat(test): diet, plan, registration 2025-10-21 21:02:17 +03:00
mso7nueh
1f4c450ce7 Merge pull request 'feat(tests): recipe create, fix oauth' (#737) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#737
2025-10-21 11:38:31 +00:00
mso7nueh
1841199291 fix: analyzer 2025-10-21 14:07:12 +03:00
mso7nueh
4c5532ff32 fix: upd ver 2025-10-21 14:00:40 +03:00
mso7nueh
c1cbf1658b fix(oauth): sex=null 2025-10-21 13:59:19 +03:00
misha
2440204294 feat(registration): added base layout for new registration page, and a bit of state managment 2025-10-20 17:55:56 +03:00
mso7nueh
e7ab43c845 feat(tests): recipe create widget test 2025-10-20 12:04:53 +03:00
mso7nueh
b9136a80de feat(tests); recipe create 2025-10-17 17:11:27 +03:00
bb68ea963c Merge pull request 'feat(tests)' (#736) from misha/eatvio_app:tests into main
Reviewed-on: eatvio/eatvio_app#736
2025-10-17 13:14:20 +00:00
misha
228ea7c902 feat(tests): added sign in skip 2025-10-17 16:13:34 +03:00
8c85d1837a Merge pull request 'feat(deepLinks)' (#692) from misha/eatvio_app:deepLinks into main
Reviewed-on: eatvio/eatvio_app#692
2025-10-17 13:04:11 +00:00
misha
1d8f414672 Merge remote-tracking branch 'upstream/main' into deepLinks 2025-10-17 16:03:35 +03:00
49453c8b31 Merge pull request 'feat(pushNotifications)' (#708) from misha/eatvio_app:issue-707 into main
Reviewed-on: eatvio/eatvio_app#708
2025-10-17 12:25:36 +00:00
misha
138e2c1073 Merge remote-tracking branch 'upstream/main' into issue-707 2025-10-17 15:24:21 +03:00
eb39ae5e7c Merge pull request 'feat(diary)' (#705) from misha/eatvio_app:issue-701 into main
Reviewed-on: eatvio/eatvio_app#705
2025-10-17 11:52:09 +00:00
misha
250d9614e3 Merge remote-tracking branch 'upstream/main' into issue-701 2025-10-17 11:50:36 +03:00
b9b06f11a6 Merge pull request 'feat(glossary)' (#711) from misha/eatvio_app:issue-710 into main
Reviewed-on: eatvio/eatvio_app#711
2025-10-16 15:24:56 +00:00
misha
12ca205515 Merge remote-tracking branch 'upstream/main' into issue-710 2025-10-16 18:23:04 +03:00
mso7nueh
d8e7464c37 Merge pull request 'build 80 (android), 81 ios' (#734) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#734
2025-10-16 14:39:17 +00:00
mso7nueh
e0c90bcb21 fix: upd ver to 80 2025-10-16 17:38:23 +03:00
4a96390839 Merge pull request 'doc(readme): README.md update' (#731) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#731
2025-10-16 14:36:34 +00:00
a3b25270ac Merge pull request 'fix: merge conflict' (#733) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#733
2025-10-16 14:34:30 +00:00
misha
c72b3e77c6 fix: merge conflict 2025-10-16 17:33:52 +03:00
35f2c0f30a Merge pull request 'feat(social)' (#732) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#732
2025-10-16 14:20:46 +00:00
misha
9e43be5b4e feat(social): added validation for social media registration 2025-10-16 17:18:45 +03:00
4db5dda3ce doc(readme): README.md update 2025-10-16 14:22:23 +03:00
87d5e0bc23 Merge pull request 'docs and rules added' (#730) from apoloz/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#730
2025-10-16 08:22:11 +00:00
fa3cf297a3 doc(project): project brief docs added 2025-10-16 11:01:37 +03:00
7b08560257 merge upstream 2025-10-16 07:28:06 +00:00
efd6cca87d Merge pull request 'CI\CD fix' (#729) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#729
2025-10-15 11:50:06 +00:00
misha
05bf90a3cf fixed pipline 2025-10-15 14:47:46 +03:00
misha
feee814bbb pod repod update for ci cd 2025-10-15 14:43:21 +03:00
mso7nueh
d871fdc084 Merge pull request 'build 80' (#726) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#726
2025-10-15 11:26:30 +00:00
misha
e865a11d14 fix: fixed proj version 2025-10-15 14:25:27 +03:00
misha
b242eaa027 fix: fixed base url 2025-10-15 14:22:45 +03:00
misha
e073bd3f97 feat(socail): finished registration and ligin via social media 2025-10-15 14:21:43 +03:00
9281213ea1 Merge pull request 'feat(dairy): navigation to diet from diary' (#723) from misha/eatvio_app:issue-720 into main
Reviewed-on: eatvio/eatvio_app#723
2025-10-15 09:38:06 +00:00
misha
d0ac156307 Merge remote-tracking branch 'upstream/main' into issue-720 2025-10-15 12:35:47 +03:00
mso7nueh
4a9d45a18d Merge pull request 'Issue-691' (#725) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#725
2025-10-15 09:35:33 +00:00
misha
65fabefdb9 Merge remote-tracking branch 'upstream/main' into issue-720 2025-10-15 12:35:05 +03:00
mso7nueh
f573bb28f8 feat(oauth): Issue-691 2025-10-14 19:25:26 +03:00
mso7nueh
20aca4b9a4 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-10-14 12:16:23 +03:00
mso7nueh
5354c3f517 feat(auth): Issue-691 2025-10-14 12:16:20 +03:00
17dbc1d5bf Merge pull request 'feat(social)' (#724) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#724
2025-10-14 09:11:22 +00:00
misha
09a00a41ad added scopes for yandex id 2025-10-14 12:09:26 +03:00
misha
24675714e0 feat(social): added vk client id for ios 2025-10-10 17:02:08 +03:00
misha
21492a1ad9 fix: removed wrong code 2025-10-10 15:18:25 +03:00
misha
239ff675db fix: fixed author card image url handling 2025-10-10 14:58:24 +03:00
misha
fa6c2f9000 Merge remote-tracking branch 'upstream/main' into issue-720 2025-10-10 14:51:41 +03:00
misha
ae0c3a53be Merge remote-tracking branch 'upstream/main' into issue-720 2025-10-10 14:50:37 +03:00
21555bfb10 Merge pull request 'feat(social)' (#721) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#721
2025-10-10 11:46:01 +00:00
misha
f90f1d3284 feat(social): fixed baseUrl for RegisterViaSocialScreen 2025-10-10 14:45:15 +03:00
f9fed539c2 Merge pull request 'feat(tests)' (#718) from misha/eatvio_app:tests into main
Reviewed-on: eatvio/eatvio_app#718
2025-10-10 11:38:03 +00:00
misha
654edc5457 fix: analyzer issues 2025-10-10 14:37:27 +03:00
928a55ae93 Merge pull request 'Issue-691' (#719) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#719
2025-10-10 11:25:00 +00:00
misha
b2433b87b6 feat(diary): added navigation to detailed diet screen form diary 2025-10-10 14:08:21 +03:00
mso7nueh
183fa012d2 feat(auth): Issue-691 2025-10-09 17:24:36 +03:00
misha
9ac576221a feat(tests): changed base url handling logic, added build type checking for push permission 2025-10-08 17:23:51 +03:00
misha
5013ffe06b Merge remote-tracking branch 'upstream/main' into tests 2025-10-08 14:33:47 +03:00
2993c05dd1 Merge pull request 'feat(internetConnection)' (#714) from misha/eatvio_app:issue-712 into main
Reviewed-on: eatvio/eatvio_app#714
2025-10-08 11:18:29 +00:00
misha
87c0d4ec2a feat(analyzer): fixed issues 2025-10-08 14:04:25 +03:00
misha
17be198a23 Merge remote-tracking branch 'upstream/main' into issue-712 2025-10-08 14:03:05 +03:00
mso7nueh
79de6ee6fa feat(registration): Issue-691 register_via_social_screen.dart 2025-10-07 22:01:44 +03:00
misha
b0d2d86a18 feat(tests): added 2 e2e tests 2025-10-07 18:03:36 +03:00
mso7nueh
03448ebd2d feat(oauth): Issue-691 2025-10-06 17:27:11 +03:00
d87d0e5e2a Merge pull request 'feat(socialAuth)' (#717) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#717
2025-10-06 13:48:47 +00:00
misha
5275273830 feat(socialAuth): added profile data fetching for social aunthentication 2025-10-06 16:46:59 +03:00
misha
f35cdd26a3 feat(diary): fexed wrong day selecting logic 2025-10-06 13:33:12 +03:00
mso7nueh
584f00a1ea Merge pull request 'Issue-691 + Issue-513' (#713) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#713
2025-10-06 10:31:47 +00:00
mso7nueh
37cedb2238 fix(rating_consultant): Issue-513 2025-10-03 16:57:22 +03:00
misha
5ee86ddc92 feat(diary): fixed wrong cpfc loading after changing a portion 2025-10-03 15:40:05 +03:00
misha
fceaf3d162 Merge remote-tracking branch 'upstream/main' into issue-701 2025-10-02 14:03:14 +03:00
misha
46841fb502 feat(personalDiets): fixed PlanState widget in order to show personal diet state 2025-10-02 13:49:58 +03:00
misha
8e72350152 Merge remote-tracking branch 'upstream/main' into personalDiets 2025-10-02 12:25:40 +03:00
misha
8816b67ff5 Merge remote-tracking branch 'upstream/main' into issue-710 2025-10-02 10:27:45 +03:00
misha
09d025252d feat(fixes): fixed analyzer issue 2025-10-02 10:25:10 +03:00
misha
ca3bd7cc0d Merge remote-tracking branch 'upstream/main' into issue-707 2025-10-02 10:21:04 +03:00
mso7nueh
086e6cf94e fix: recipe 2025-10-02 00:13:35 +03:00
mso7nueh
766d5ba248 fix: cubit 2025-10-02 00:07:28 +03:00
mso7nueh
e7ce9d8f90 fix: refactor 2025-10-02 00:05:25 +03:00
mso7nueh
7861cdce3c fix: refactor 2025-10-01 23:59:34 +03:00
mso7nueh
2865852124 fix: refactor 2025-10-01 23:59:19 +03:00
misha
d18ad86590 feat(internetConnection): fixed yandex sign in compilation 2025-10-01 17:24:48 +03:00
misha
f1945202fe feat(internetConnection): changed logic for internet connection checking and displaying state 2025-09-30 17:33:30 +03:00
mso7nueh
b65fca8116 feat(auth): Issue-691 2025-09-30 16:11:30 +03:00
mso7nueh
27376ca54d feat(auth): Issue-691 2025-09-30 00:39:21 +03:00
mso7nueh
01f1c39450 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-09-29 23:45:24 +03:00
mso7nueh
24fe984e6b feat(auth): Issue-691 2025-09-29 23:45:18 +03:00
mso7nueh
053cf781c3 Merge pull request 'Issue-691, 660' (#709) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#709
2025-09-29 10:31:10 +00:00
mso7nueh
46d0e31f5f fix(huawei-push): Issue-660 2025-09-29 13:29:39 +03:00
misha
782f75d26b feat(diary): fixed cpfc for v2 diary 2025-09-29 09:49:59 +03:00
misha
c88b010cc5 feat(glossary): added pass key for glossary 2025-09-29 09:13:45 +03:00
mso7nueh
a0b29f42df feat(hp): Issue-660 2025-09-26 10:31:34 +03:00
misha
79dc590beb Merge remote-tracking branch 'upstream/main' into issue-701 2025-09-25 15:14:25 +03:00
mso7nueh
96b3bd1637 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-09-24 23:47:19 +03:00
mso7nueh
fc09fa36b8 feat(auth): Issue-691 2025-09-24 23:47:11 +03:00
misha
517e493b5e feat(pushNotifications): added anonymous token for push notifications 2025-09-24 15:23:01 +03:00
misha
1bc0ab3237 fixed profile back button 2025-09-24 10:01:06 +03:00
mso7nueh
68ea8da6e3 Merge pull request 'fix(profile): Issue-523 + 591 + 393 + 660' (#704) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#704
2025-09-23 20:50:00 +00:00
mso7nueh
052c4fedca feat(hms): Issue-660 2025-09-23 23:47:38 +03:00
mso7nueh
ad777c695b fix(consultations): Issue-393 2025-09-22 17:08:41 +03:00
misha
a8994eecf4 feat(diary): fixed bugs fod diary with v2 methods 2025-09-22 10:52:29 +03:00
mso7nueh
e6df89c98a fix(feed): Issue-591 2025-09-19 15:55:07 +03:00
misha
8d3ae15112 feat(diary): added v2 methods for diary 2025-09-18 18:47:07 +03:00
mso7nueh
fef4451f4e fix(profile): Issue-523 2025-09-17 17:00:44 +03:00
mso7nueh
c68f86eeb7 Merge pull request 'fix: upd ver to 73' (#702) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#702
2025-09-17 13:32:52 +00:00
mso7nueh
fafc2aa1f7 fix: upd ver to 73 2025-09-17 16:32:24 +03:00
mso7nueh
ca49415ef6 Merge pull request 'Issue-372, 582, 189, 691' (#700) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#700
2025-09-17 13:28:36 +00:00
mso7nueh
2600b8cc79 fix(auth): hide social buttons 2025-09-17 16:28:13 +03:00
e1f25a63bc Merge pull request 'feat(views)' (#697) from misha/eatvio_app:issue-687 into main
Reviewed-on: eatvio/eatvio_app#697
2025-09-17 12:39:58 +00:00
misha
087436da1c changed logic of view requests sending 2025-09-17 15:13:16 +03:00
mso7nueh
c295c06565 fix(my_plans): Issue-189 2025-09-16 19:09:41 +03:00
mso7nueh
b146295996 fix(profile): Issue-582 2025-09-16 19:00:53 +03:00
84cdf34859 merge upstream 2025-09-16 08:55:48 +00:00
mso7nueh
41f77bd373 feat(;auth): social 2025-09-16 09:28:17 +03:00
misha
6ac93d42df Merge branch 'main' into issue-687 2025-09-15 14:13:28 +03:00
misha
1a6fb39d84 gitignore 2025-09-15 14:12:05 +03:00
mso7nueh
d4a8cbc637 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-09-12 16:29:37 +03:00
mso7nueh
2300bc4ab6 fix(consultations): Issue-372 2025-09-12 16:29:29 +03:00
mso7nueh
b4776c3be3 Merge pull request 'Issues: 416+675' (#699) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#699
2025-09-12 13:27:29 +00:00
mso7nueh
06e07a92b7 Merge pull request 'Issues-236, 332, 256' (#698) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#698
2025-09-12 10:48:22 +00:00
mso7nueh
0fce3f9d30 fix(diary): Issue-675 2025-09-12 13:38:50 +03:00
mso7nueh
4bc8cba941 fix(profile): Issue-416 2025-09-12 13:34:16 +03:00
mso7nueh
8c348f61b1 fix(settings): Issue-256 2025-09-11 21:35:28 +03:00
mso7nueh
0446e64409 merge upstream 2025-09-11 18:25:01 +00:00
mso7nueh
74b5c6732d fix(settings): Issue-256 2025-09-11 20:11:37 +03:00
mso7nueh
b840c936bf fix(finances): Issue-332 2025-09-11 20:02:48 +03:00
mso7nueh
f3dbbf3537 fix(settings): Issue-236 2025-09-11 19:51:16 +03:00
misha
ff49562e86 feat(views): added view handling for diets, recipes, plans and posts 2025-09-11 18:04:35 +03:00
mso7nueh
8b7180c2da Merge pull request 'fix(comments): Issue-548' (#695) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#695
2025-09-10 14:37:20 +00:00
mso7nueh
5c911707a3 fix(comments): Issue-548 2025-09-10 17:36:46 +03:00
mso7nueh
aa604b667b Merge pull request 'fix(notifications): Issue-236' (#693) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#693
2025-09-10 13:45:40 +00:00
mso7nueh
0a5d78be1f fix: ver upd 2025-09-10 16:45:22 +03:00
mso7nueh
f1f5c79661 fix(notifications): Issue-236 2025-09-10 15:58:26 +03:00
mso7nueh
1c517807c4 Merge pull request 'feat(metrica): Issue-685 + 675 + 180' (#688) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#688
2025-09-10 12:58:21 +00:00
Username1548
6b7b1f2d18 feat(deepLinks): added diary deep link and improved profile and chat deep links 2025-09-10 15:19:49 +03:00
Username1548
82bc51e45c feat(deepLinks): added chat and profile deeplinks 2025-09-10 08:08:58 +03:00
Username1548
77666aca0e Merge remote-tracking branch 'upstream/main' into deepLinks 2025-09-09 21:24:36 +03:00
Username1548
16430af989 gitignore 2025-09-09 21:24:05 +03:00
mso7nueh
cad54913d1 Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-09-09 18:58:51 +03:00
mso7nueh
89f0a46192 fix(diet): Issue-180 2025-09-09 18:58:39 +03:00
mso7nueh
65542020a7 merge upstream 2025-09-08 14:45:58 +00:00
mso7nueh
b6b1c8b3c1 feat(diary): кбжу 2025-09-08 14:14:41 +03:00
Username1548
8c2cd5eedd Merge remote-tracking branch 'upstream/main' into personalDiets 2025-09-05 11:28:51 +03:00
mso7nueh
bf6e23e96a feat(metrica): Issue-685 2025-09-03 11:34:41 +03:00
mso7nueh
952cf76164 Merge pull request 'fix: Issue-645' (#684) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#684
2025-09-01 10:04:31 +00:00
mso7nueh
b665692779 fix: Issue-645 2025-09-01 13:03:43 +03:00
mso7nueh
54ac20978f Merge pull request 'feat(notifications): Issue-236' (#682) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#682
2025-09-01 09:01:48 +00:00
mso7nueh
b9dc5c0136 Удалить env/.env 2025-08-29 12:16:55 +00:00
mso7nueh
39fce4b0f9 fix: mv env 2025-08-29 15:16:40 +03:00
mso7nueh
73ff67aa13 merge upstream 2025-08-29 12:10:23 +00:00
mso7nueh
dcf2805df7 fix: analyzer 2025-08-29 14:26:28 +03:00
mso7nueh
d13eb78f0e feat(notifications): Issue-236 2025-08-29 14:25:13 +03:00
mso7nueh
5f21a65028 Merge pull request 'feat(verify_email): add dialog' (#679) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#679
2025-08-27 11:40:22 +00:00
mso7nueh
12bf9f9e5f feat(verify_email): add dialog 2025-08-27 14:39:22 +03:00
mso7nueh
1680bd2556 fix: testflight 2025-08-27 12:04:20 +03:00
mso7nueh
91d5118f60 Merge pull request 'feat(verify_email): Issue-645' (#676) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#676
2025-08-27 08:44:19 +00:00
mso7nueh
d8324c1635 feat(verify_email): Issue-645 2025-08-27 11:33:06 +03:00
mso7nueh
0f1dbe16f1 Merge pull request 'fix: testflight' (#673) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#673
2025-08-25 15:31:56 +00:00
Alexander
020682ae80 fix: testflight 2025-08-25 18:31:37 +03:00
mso7nueh
e54476656b Merge pull request 'fix: test-flight' (#671) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#671
2025-08-25 15:28:43 +00:00
Alexander
dd56924076 fix: test-flight 2025-08-25 18:28:15 +03:00
mso7nueh
b47da44cf2 Merge pull request 'fix: testflight' (#669) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#669
2025-08-25 15:19:56 +00:00
Alexander
964550a325 fix: testflight 2025-08-25 18:19:18 +03:00
mso7nueh
7ffa061f3e Merge pull request 'fix: testflight' (#667) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#667
2025-08-25 15:16:06 +00:00
Alexander
997da4f940 fix: testflight 2025-08-25 18:15:49 +03:00
mso7nueh
ca1777ece0 Merge pull request 'main' (#665) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#665
2025-08-25 15:12:32 +00:00
Alexander
1a427d6f5d Merge branch 'main' of http://gitea.office.local:3000/mso7nueh/eatvio_app 2025-08-25 18:12:05 +03:00
Alexander
f190e70f3a fix: testflight 2025-08-25 18:11:04 +03:00
mso7nueh
bc6469a6ae fix: testflight 2025-08-25 17:55:34 +03:00
mso7nueh
e3ff359e1b Merge pull request 'fix: testflight' (#662) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#662
2025-08-25 14:42:39 +00:00
Alexander
b5edf13bd9 fix: testflight 2025-08-25 17:42:05 +03:00
mso7nueh
c05d027e3d Merge pull request 'fix: add product modal and auth error, add appmetrica' (#659) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#659
2025-08-25 14:29:20 +00:00
Alexander
bae79b60fd fix: testflight 2025-08-25 17:29:07 +03:00
mso7nueh
6061e413b2 fix: upd ver to 71 2025-08-25 14:40:50 +03:00
mso7nueh
5a8fa7089c feat: appmetrica 2025-08-25 14:24:06 +03:00
mso7nueh
886cfa8f1c feat: AppMetrica 2025-08-25 13:05:53 +03:00
mso7nueh
a416912d2a fix: add product modal and auth error 2025-08-25 11:26:14 +03:00
mso7nueh
f46392ec8e Merge pull request 'fix: Issue-592' (#655) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#655
2025-08-22 11:18:00 +00:00
mso7nueh
766d06fc4d fix: Issue-592 2025-08-22 14:17:11 +03:00
mso7nueh
6f4023dd0b Merge pull request #512: Add consultant rating functionality 2025-08-22 10:32:39 +03:00
a31f721d81 merge upstream 2025-08-21 12:05:04 +00:00
1b93f5c287 Update README.md 2025-08-20 12:55:06 +00:00
mso7nueh
f892dfed9f Merge pull request 'fix: Issue-618' (#654) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#654
2025-08-20 12:52:12 +00:00
Alexander
98803e56cf fix: Issue-618 2025-08-20 15:51:46 +03:00
7b8a5d14d7 Update README.md 2025-08-20 11:44:28 +00:00
f94fd6f358 Update README.md 2025-08-20 11:41:55 +00:00
a9ad6aedd0 Update README.md 2025-08-20 11:41:21 +00:00
83dd53351b merge upstream 2025-08-20 11:39:16 +00:00
mso7nueh
4391870e72 Merge pull request 'fix: build ios' (#652) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#652
2025-08-20 10:03:32 +00:00
Alexander
7fd24f57e3 fix: build ios 2025-08-20 13:03:16 +03:00
mso7nueh
384a25c4a6 Merge pull request 'fix: ios build' (#650) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#650
2025-08-20 09:59:07 +00:00
Alexander
88558d62ef fix: ios build 2025-08-20 12:58:48 +03:00
mso7nueh
09b04118aa Merge pull request 'fix: ios build' (#648) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#648
2025-08-20 09:55:07 +00:00
Alexander
f76b142117 fix: ios build 2025-08-20 12:54:54 +03:00
f269ab59cc merge upstream 2025-08-20 09:50:17 +00:00
mso7nueh
13e66edd27 Merge pull request 'fix: Issue-613' (#647) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#647
2025-08-20 09:43:06 +00:00
Alexander
5b74ae45b3 fix: Issue-613 2025-08-20 12:42:39 +03:00
mso7nueh
3d2634b96a Merge pull request 'Добавление таймера для подтверждения почты' (#643) from misha/eatvio_app:issue-642 into main
Reviewed-on: eatvio/eatvio_app#643
2025-08-20 09:39:16 +00:00
mso7nueh
1281abaf24 Merge pull request 'Issue-191: Notifications' (#644) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#644
2025-08-20 09:39:08 +00:00
Alexander
7dfac3f792 fix: baseUrl -> prod 2025-08-20 11:57:06 +03:00
Alexander
9d4687553a fix: analyzer and token storage 2025-08-20 11:34:28 +03:00
mso7nueh
442da40622 fix: token storage 2025-08-19 14:24:14 +03:00
mso7nueh
ccf586234b fix: user charts in consultations 2025-08-15 14:13:30 +03:00
mso7nueh
4f249499a9 fix(notifications): Issue-191 2025-08-15 13:28:12 +03:00
mso7nueh
2f74387df2 fix: firebase notificatons when qr login 2025-08-14 18:13:34 +03:00
Username1548
45774c3875 fix 2025-08-14 16:58:00 +03:00
Username1548
62c0914fe2 fix 2025-08-14 16:55:15 +03:00
Username1548
48f5b64223 feat(emailVerification): added timer for email code resending 2025-08-14 16:54:13 +03:00
ed4db5b59e Merge pull request 'feat(menu): Added build date' (#640) from misha/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#640
2025-08-12 06:02:06 +00:00
Username1548
91bb5cf483 feat(menu): fixed indentation 2025-08-12 09:01:31 +03:00
Username1548
c4dedac3f3 added build date 2025-08-12 12:27:58 +07:00
mso7nueh
8ed243f63c Merge pull request 'fix: upd ver' (#638) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#638
2025-08-11 14:19:46 +00:00
mso7nueh
a10fe6d2f5 fix: upd ver 2025-08-11 17:19:14 +03:00
mso7nueh
35b78bdeee Merge pull request 'fix(blackList+notifications): Issue-523, 191' (#636) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#636
2025-08-11 14:00:25 +00:00
mso7nueh
ef037eb4d5 Merge pull request 'feat(chats): added message resend and deleting, feat(menu): added build number' (#633) from misha/eatvio_app:issue-594 into main
Reviewed-on: eatvio/eatvio_app#633
2025-08-11 14:00:14 +00:00
mso7nueh
5a3385cacf Merge pull request 'removed public offer from ui on ios' (#637) from misha/eatvio_app:issue-635 into main
Reviewed-on: eatvio/eatvio_app#637
2025-08-11 14:00:05 +00:00
mso7nueh
dca4b4c471 fix(blackList+notifications): Issue-523, 191 2025-08-11 14:53:43 +03:00
Username1548
48f433288f feat(chats): added message resend and deleting, feat(menu): added build number 2025-08-11 02:52:41 +07:00
Username1548
996f2ecd70 Merge branch 'main' into personalDiets 2025-07-16 17:04:21 +07:00
Username1548
19787f459e feat(personalDiet): fixed wrong path for attach diet method 2025-07-16 17:03:46 +07:00
Username1548
7e64b24a8c added layout for suggestions page 2025-07-15 21:49:47 +07:00
Username1548
a07d085ba7 feat(personalDiets): preapared chats for consultations with personal diets 2025-07-14 20:24:40 +07:00
Username1548
5616bedd25 feat(personalDiets): diets suggestions 2025-07-14 13:44:44 +07:00
Username1548
0a3d9e577d Merge branch 'main' into personalDiets 2025-07-14 12:17:37 +07:00
Username1548
55e3abec99 feat(personal diets): added personal diet option to plans 2025-07-14 12:15:26 +07:00
0d4ec9390d merge upstream 2025-06-30 19:50:42 +00:00
a16e78f804 Merge pull request 'sync main' (#2) from eatvio/eatvio_app:main into main
Reviewed-on: apoloz/eatvio_app#2
2025-06-30 07:23:34 +00:00
Username1548
96e80ced38 feat(consultantRating): added api requests and state to consultant rating page 2025-06-17 13:33:41 +07:00
c021cdf2c1 Update .gitea/workflows/docker-run-tests.yml 2025-03-13 14:13:19 +00:00
851c300622 Merge pull request 'sync main' (#1) from eatvio/eatvio_app:main into main
Reviewed-on: apoloz/eatvio_app#1
2025-03-13 14:12:52 +00:00
1299 changed files with 158316 additions and 11258 deletions

View File

@@ -0,0 +1,62 @@
name: "🐞 Bug Report"
description: "Report a bug to help us improve"
title: "[Bug]: "
labels: ["bug"]
body:
- type: dropdown
id: stand
attributes:
label: "Stand"
description: "Select the environment where the bug occurs"
options:
- "prod"
- "stage-dev2"
- "local"
- "all"
validations:
required: true
- type: dropdown
id: platform
attributes:
label: "Platform"
description: "Select the platform where the bug occurs"
options:
- "Android"
- "iPhone"
- "Huawei"
- "All"
validations:
required: true
- type: input
id: device_model
attributes:
label: "Device Model"
description: "Optional. Specify the device where the bug occurs"
placeholder: "e.g., Samsung Galaxy S23, iPhone 15 Pro, Huawei P60"
- type: textarea
id: reproduction_steps
attributes:
label: "Steps to Reproduce"
description: "Clear numbered steps"
placeholder: "1. Click X\n2. Navigate to Y..."
validations:
required: true
- type: textarea
id: expected_actual
attributes:
label: "Expected vs Actual Behavior"
description: "What should happen vs what happens"
validations:
required: true
- type: textarea
id: description
attributes:
label: "Description"
description: "Дополнительная информация описывающая проблему"
validations:
required: true

View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: "💬 Community Support"
url: "https://pepe.eatv.io/channel/general"
about: "Ask questions here"

View File

@@ -0,0 +1,26 @@
name: "✨ Feature Request"
description: "Suggest an idea for this project"
title: "[Feature]: "
labels: ["enhancement"]
body:
- type: textarea
id: use_case
attributes:
label: "Use Case"
description: "Problem solved or value added"
validations:
required: true
- type: textarea
id: description
attributes:
label: "Description"
description: "Дополнительная информация описывающая функциональность"
validations:
required: true
- type: dropdown
id: priority
attributes:
label: "Priority Level"
options: ["Low", "Medium", "High"]

View File

@@ -3,19 +3,19 @@ name: Eatvio App Android Test
on: [ pull_request ]
env:
flutter_version: "3.32.0"
flutter_version: "3.41.2"
java_version: "21.x"
flutter_channel: "stable"
jobs:
build:
runs-on: [ dev-office ]
runs-on: [ ubuntu-latest ]
steps:
- uses: actions/checkout@v3
- uses: https://github.com/actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
uses: https://github.com/actions/setup-java@v3
with:
distribution: "zulu"
java-version: ${{ env.java_version }}
@@ -24,7 +24,7 @@ jobs:
- name: Install Android SDK
run: |
apt-get update
apt-get install -y openjdk-11-jdk wget
apt-get install -y openjdk-11-jdk wget xz-utils tar
wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip -O commandlinetools.zip
unzip commandlinetools.zip
mkdir -p $HOME/Android/Sdk/cmdline-tools/latest
@@ -44,7 +44,7 @@ jobs:
apt-get install -y jq
- id: flutter-action
uses: actions/flutter-action@v2
uses: https://github.com/subosito/flutter-action@v2
with:
channel: ${{ env.flutter_channel }}
flutter-version: ${{ env.flutter_version }}
@@ -79,7 +79,7 @@ jobs:
echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
- name: Upload APK artifact
uses: actions/upload-artifact@v3
uses: https://github.com/actions/upload-artifact@v3
with:
name: ${{ env.APK_NAME }}
path: ${{ env.APK_NAME }}

View File

@@ -3,7 +3,7 @@ name: Eatvio App Android Test on custom docker
on: [ pull_request ]
env:
flutter_version: "3.32.0"
flutter_version: "3.41.2"
java_version: "21.x"
flutter_channel: "stable"
my_local_cache_dir: "/opt/hostedtoolcache/"
@@ -15,7 +15,7 @@ jobs:
runs-on: [ dev-office-flutter ]
steps:
- uses: actions/checkout@v3
- uses: https://github.com/actions/checkout@v3
- name: Set up Android environment variables
id: "android-env-setup"
@@ -41,7 +41,7 @@ jobs:
# - name: Build apk
# run: flutter build apk
# some test
# some test 2
# - name: Rename and move apk
# run: |
@@ -52,7 +52,7 @@ jobs:
# echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
# - name: Upload APK artifact
# uses: actions/upload-artifact@v3
# uses: https://github.com/actions/upload-artifact@v3
# with:
# name: ${{ env.APK_NAME }}
# path: ${{ env.APK_NAME }}

View File

@@ -1,4 +1,4 @@
name: "Build Test Flight"
name: 'Build Test Flight'
on:
pull_request:
branches:
@@ -8,40 +8,51 @@ jobs:
build:
runs-on: [macos-arm64]
steps:
# launchd does not load the login-shell PATH, so Homebrew git is invisible to act.
- name: Add Homebrew to PATH
run: |
echo "/opt/homebrew/bin" >> "$GITHUB_PATH"
echo "/opt/homebrew/sbin" >> "$GITHUB_PATH"
- name: Fastlane version
run: |
git --version
fastlane --version
- name: Checkout
uses: actions/checkout@v2
uses: https://github.com/actions/checkout@v2
- name: Checkout env repository
uses: actions/checkout@v2
uses: https://github.com/actions/checkout@v3
with:
repository: mso7nueh/eatvio_app_env
repository: eatvio/eatvio_app_env
path: env_repo
token: ${{ vars.MSO7NUEH_TOKEN }}
# Здесь может быть токен любого юзера с доступом в gitea
token: ${{ vars.READ_USER_GITEA_TOKEN }}
ref: main
- name: Copy .env file
run: |
mkdir -p env
cp env_repo/.env env/.env
cp env_repo/.env .env
- name: Load environment variables from .env
run: |
set -a
source env/.env
source .env
set +a
# Export all variables to GITHUB_ENV
while IFS= read -r line; do
if [[ $line =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
echo "$line" >> $GITHUB_ENV
fi
done < env/.env
done < .env
- name: Unlock login keychain
run: |
security unlock-keychain -p "$KEYCHAIN_PASSWORD" /Users/gitea_runner_ci/Library/Keychains/login.keychain-db
env:
KEYCHAIN_PASSWORD: ${{ vars.IOS_RUNNER_CI_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ vars.IOS_RUNNER_CI_PASSWORD }}
- name: Setup API key
run: |
echo "${API_APPSTORE_KEY}" | tr -d '\n' | base64 --decode > ios/AuthKey.p8
@@ -55,19 +66,24 @@ jobs:
- name: Flutter build
run: |
flutter --version
flutter config --no-enable-swift-package-manager
rm -rf ios/Podfile.lock
flutter clean
flutter pub get
flutter pub upgrade
flutter pub run build_runner build --delete-conflicting-outputs
cd ios
pod update
pod install --repo-update
cd ..
flutter build ios --config-only --release
cd ios
fastlane beta
env:
LANG: en_US.UTF-8
LC_ALL: en_US.UTF-8
MATCH_PASSWORD: ${{ vars.IOS_RUNNER_CI_PASSWORD }}
FASTLANE_PASSWORD: ${{ vars.FASTLANE_PASSWORD }}
MATCH_GIT_URL: http://gitea.office.local:3000/mso7nueh/fastlane
MATCH_PASSWORD: ${{ vars.IOS_RUNNER_CI_PASSWORD }}
FASTLANE_PASSWORD: ${{ vars.FASTLANE_PASSWORD }}
MATCH_GIT_URL: http://eatvio:${{ vars.READ_USER_GITEA_TOKEN }}@gitea.office.local:3000/eatvio/fastlane.git
FASTLANE_USER: eatvio2023@icloud.com
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ vars.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ vars.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}
API_APPSTORE_KEY: ${{ vars.API_APPSTORE_KEY }}

View File

@@ -1,45 +1,59 @@
name: Eatvio App Android Test
on: [ pull_request ]
on:
pull_request:
branches:
- main
env:
flutter_version: "3.32.8"
java_version: "21.x"
flutter_channel: "stable"
my_local_cache_dir: "/opt/hostedtoolcache/"
ANDROID_SDK_ROOT: "/opt/hostedtoolcache/Android/Sdk"
flutter_version: '3.41.2'
java_version: '21.x'
flutter_channel: 'stable'
my_local_cache_dir: '/opt/hostedtoolcache/'
ANDROID_SDK_ROOT: '/opt/hostedtoolcache/Android/Sdk'
jobs:
build:
runs-on: [ dev-office ]
runs-on: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: https://github.com/actions/checkout@v3
# Пока что не нужно проксирование
# - name: Set proxy server
# env:
# PROXY_USER: ${{ secrets.PROXY_USER }}
# PROXY_PASSWORD: ${{ secrets.PROXY_PASSWORD }}
# run: |
# echo "Setting up proxy..."
# cat <<EOF >/etc/apt/apt.conf.d/proxy.conf
# Acquire::http::Proxy "socks5h://${PROXY_USER}:${PROXY_PASSWORD}@10.55.5.202:19843/";
# EOF
- name: Checkout env repository
uses: actions/checkout@v3
uses: https://github.com/actions/checkout@v3
with:
repository: mso7nueh/eatvio_app_env
repository: eatvio/eatvio_app_env
path: env_repo
token: ${{ vars.MSO7NUEH_TOKEN }}
# Здесь может быть токен любого юзера с доступом в gitea
token: ${{ vars.READ_USER_GITEA_TOKEN }}
ref: main
- name: Copy .env file
run: |
mkdir -p env
cp env_repo/.env env/.env
cp env_repo/.env .env
- name: Load environment variables from .env
run: |
set -a
source env/.env
source .env
set +a
# Export all variables to GITHUB_ENV
while IFS= read -r line; do
if [[ $line =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
echo "$line" >> $GITHUB_ENV
fi
done < env/.env
done < .env
- name: Create key.properties file
run: |
@@ -57,22 +71,22 @@ jobs:
- name: Cache Android SDK
id: cache-sdk
uses: "https://gitea.com/actions/cache@v4"
uses: 'https://github.com/actions/cache@v4'
with:
path: ${{ env.my_local_cache_dir }}
key: ${{ runner.os }}-cache-sdk
- name: Set up JDK
uses: actions/setup-java@v3
uses: https://github.com/actions/setup-java@v3
with:
distribution: "zulu"
distribution: 'zulu'
java-version: ${{ env.java_version }}
cache: gradle
- name: Install utils for Android SDK
run: |
apt-get update
apt-get install -y openjdk-11-jdk wget jq clang cmake ninja-build libgtk-3-dev
apt-get install -y openjdk-17-jdk wget jq clang cmake ninja-build libgtk-3-dev
- name: Install Android SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
@@ -91,25 +105,31 @@ jobs:
sdkmanager "platform-tools" "platforms;android-35" "platforms;android-34" "platforms;android-33" "platforms;android-31"
sdkmanager "build-tools;34.0.0"
sdkmanager "ndk;25.1.8937393"
sdkmanager --install "cmake;3.22.1"
sdkmanager --install "cmake;3.22.1"
- name: Set up Android environment variables
id: "android-env-setup"
id: 'android-env-setup'
run: |
echo "ANDROID_SDK_ROOT=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
echo "PATH=$PATH:${{ env.my_local_cache_dir }}Android/Sdk/cmdline-tools/latest/bin:${{ env.my_local_cache_dir }}Android/Sdk/platform-tools:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/30.0.3:${{ env.my_local_cache_dir }}Android/Sdk/build-tools/34.0.0" >> $GITHUB_ENV
echo "ANDROID_HOME=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
echo "ANDROID_HOME=${{ env.my_local_cache_dir }}Android/Sdk" >> $GITHUB_ENV
- id: flutter-action
uses: actions/flutter-action@v2
with:
channel: ${{ env.flutter_channel }}
flutter-version: ${{ env.flutter_version }}
cache: true
cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache
cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path
pub-cache-key: "flutter-pub:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache of dart pub get dependencies
pub-cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path
- name: Set up Flutter
run: |
FLUTTER_DIR="${{ env.my_local_cache_dir }}flutter"
if [ ! -f "$FLUTTER_DIR/bin/flutter" ]; then
echo "Downloading Flutter ${{ env.flutter_version }}..."
curl -fsSL -o /tmp/flutter.tar.xz "https://storage.googleapis.com/flutter_infra_release/releases/${{ env.flutter_channel }}/linux/flutter_linux_${{ env.flutter_version }}-${{ env.flutter_channel }}.tar.xz"
echo "Extracting Flutter..."
mkdir -p "${{ env.my_local_cache_dir }}"
tar xf /tmp/flutter.tar.xz -C "${{ env.my_local_cache_dir }}"
rm /tmp/flutter.tar.xz
else
echo "Flutter already cached at $FLUTTER_DIR"
fi
echo "$FLUTTER_DIR/bin" >> $GITHUB_PATH
echo "$FLUTTER_DIR/bin/cache/dart-sdk/bin" >> $GITHUB_PATH
echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH
# - name: Print flutter-action outputs
# shell: bash
@@ -127,24 +147,92 @@ jobs:
- name: Fix dir permissions
run: |
git config --global --add safe.directory /opt/hostedtoolcache/flutter/${{ env.flutter_channel }}-${{ env.flutter_version }}-${{ steps.flutter-action.outputs.ARCHITECTURE }}
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then ARCH="x64"; fi
git config --global --add safe.directory "${{ env.my_local_cache_dir }}flutter"
flutter config --android-sdk="$ANDROID_HOME"
flutter doctor -v
flutter doctor -v
- name: Get dependencies
run: |
flutter clean
flutter pub get
dart run build_runner build --delete-conflicting-outputs
flutter clean
flutter pub cache repair
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Native Analyze
run: flutter analyze
- name: Test
run: flutter test
run: flutter test --coverage
# - name: Test coverage
# run: |
# echo "📊 Analyzing test coverage..."
# echo ""
# awk -F: '
# /^SF:/ {
# file = $0
# sub(/^SF:/, "", file)
# sub(/^[[:space:]]+/, "", file)
# is_generated = 0
# if (file ~ /\.(g|freezed|gr|mocks)\.dart$/) {
# is_generated = 1
# generated_files++
# } else if (file ~ /\/(build|\.dart_tool)\//) {
# is_generated = 1
# generated_files++
# } else {
# source_files++
# }
# }
# /^LF:/ {
# if (!is_generated) {
# total += $2
# } else {
# generated_lines += $2
# }
# }
# /^LH:/ {
# if (!is_generated) {
# covered += $2
# } else {
# generated_covered += $2
# }
# }
# END {
# print "📁 Files:"
# printf " Source files: %d\n", source_files
# printf " Generated files: %d (excluded)\n", generated_files
# print ""
# print "📝 Lines:"
# printf " Total lines: %d\n", total
# printf " Covered lines: %d\n", covered
# printf " Uncovered lines: %d\n", total - covered
# print ""
# if (total == 0) {
# print "⚠️ Coverage: 0%"
# exit 1
# } else {
# percentage = (covered / total) * 100
# printf "✅ Coverage: %.2f%%\n", percentage
# print ""
# if (percentage < 70) {
# printf "❌ FAIL: Coverage is below 70%%\n"
# exit 1
# } else {
# printf "💚 Excellent: Coverage is above 70%%\n"
# }
# }
# }
# ' coverage/lcov.info
- name: Build apk
run: flutter build apk --release --dart-define=HIDE_PLANS=false
run: |
BUILD_DATE=$(TZ=Europe/Moscow date +'%Y-%m-%d %H:%M:%S')
flutter build apk --release \
--dart-define=HIDE_PLANS=false \
--dart-define=BUILD_DATE="$BUILD_DATE"
- name: Rename and move apk
run: |
@@ -152,10 +240,10 @@ jobs:
APK_NAME="eatvio_app_${TIMESTAMP}.apk"
mv build/app/outputs/flutter-apk/app-release.apk $APK_NAME
echo "APK build finished $APK_NAME"
echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
echo "APK_NAME=$APK_NAME" >> $GITHUB_ENV
- name: Upload APK artifact
uses: actions/upload-artifact@v3
uses: https://github.com/actions/upload-artifact@v3
with:
name: ${{ env.APK_NAME }}
path: ${{ env.APK_NAME }}

11
.gitignore vendored
View File

@@ -16,6 +16,13 @@
*.mocks.dart
android/build/
ios/XCBuildData/
.env
env.example
env/.env
.env
android/key.properties
app/upload-keystore.jks
coverage/
backend/
.fvm/
.fvmrc
/eatvio
*.code-workspace

View File

@@ -0,0 +1,167 @@
# Memory Bank
I am an expert software engineer with a unique characteristic: my memory resets completely between sessions. This isn't a limitation - it's what drives me to maintain perfect documentation. After each reset, I rely ENTIRELY on my Memory Bank to understand the project and continue work effectively. I MUST read ALL memory bank files at the start of EVERY task - this is not optional. The memory bank files are located in `.kilocode/rules/memory-bank` folder.
When I start a task, I will include `[Memory Bank: Active]` at the beginning of my response if I successfully read the memory bank files, or `[Memory Bank: Missing]` if the folder doesn't exist or is empty. If memory bank is missing, I will warn the user about potential issues and suggest initialization.
## Memory Bank Structure
The Memory Bank consists of core files and optional context files, all in Markdown format.
### Core Files (Required)
1. `brief.md`
This file is created and maintained manually by the developer. Don't edit this file directly but suggest to user to update it if it can be improved.
- Foundation document that shapes all other files
- Created at project start if it doesn't exist
- Defines core requirements and goals
- Source of truth for project scope
2. `product.md`
- Why this project exists
- Problems it solves
- How it should work
- User experience goals
3. `context.md`
This file should be short and factual, not creative or speculative.
- Current work focus
- Recent changes
- Next steps
4. `architecture.md`
- System architecture
- Source Code paths
- Key technical decisions
- Design patterns in use
- Component relationships
- Critical implementation paths
5. `tech.md`
- Technologies used
- Development setup
- Technical constraints
- Dependencies
- Tool usage patterns
### Additional Files
Create additional files/folders within memory-bank/ when they help organize:
- `tasks.md` - Documentation of repetitive tasks and their workflows
- Complex feature documentation
- Integration specifications
- API documentation
- Testing strategies
- Deployment procedures
## Core workflows
### Memory Bank Initialization
The initialization step is CRITICALLY IMPORTANT and must be done with extreme thoroughness as it defines all future effectiveness of the Memory Bank. This is the foundation upon which all future interactions will be built.
When user requests initialization of the memory bank (command `initialize memory bank`), I'll perform an exhaustive analysis of the project, including:
- All source code files and their relationships
- Configuration files and build system setup
- Project structure and organization patterns
- Documentation and comments
- Dependencies and external integrations
- Testing frameworks and patterns
I must be extremely thorough during initialization, spending extra time and effort to build a comprehensive understanding of the project. A high-quality initialization will dramatically improve all future interactions, while a rushed or incomplete initialization will permanently limit my effectiveness.
After initialization, I will ask the user to read through the memory bank files and verify product description, used technologies and other information. I should provide a summary of what I've understood about the project to help the user verify the accuracy of the memory bank files. I should encourage the user to correct any misunderstandings or add missing information, as this will significantly improve future interactions.
### Memory Bank Update
Memory Bank updates occur when:
1. Discovering new project patterns
2. After implementing significant changes
3. When user explicitly requests with the phrase **update memory bank** (MUST review ALL files)
4. When context needs clarification
If I notice significant changes that should be preserved but the user hasn't explicitly requested an update, I should suggest: "Would you like me to update the memory bank to reflect these changes?"
To execute Memory Bank update, I will:
1. Review ALL project files
2. Document current state
3. Document Insights & Patterns
4. If requested with additional context (e.g., "update memory bank using information from @/Makefile"), focus special attention on that source
Note: When triggered by **update memory bank**, I MUST review every memory bank file, even if some don't require updates. Focus particularly on context.md as it tracks current state.
### Add Task
When user completes a repetitive task (like adding support for a new model version) and wants to document it for future reference, they can request: **add task** or **store this as a task**.
This workflow is designed for repetitive tasks that follow similar patterns and require editing the same files. Examples include:
- Adding support for new AI model versions
- Implementing new API endpoints following established patterns
- Adding new features that follow existing architecture
Tasks are stored in the file `tasks.md` in the memory bank folder. The file is optional and can be empty. The file can store many tasks.
To execute Add Task workflow:
1. Create or update `tasks.md` in the memory bank folder
2. Document the task with:
- Task name and description
- Files that need to be modified
- Step-by-step workflow followed
- Important considerations or gotchas
- Example of the completed implementation
3. Include any context that was discovered during task execution but wasn't previously documented
Example task entry:
```markdown
## Add New Model Support
**Last performed:** [date]
**Files to modify:**
- `/providers/gemini.md` - Add model to documentation
- `/src/providers/gemini-config.ts` - Add model configuration
- `/src/constants/models.ts` - Add to model list
- `/tests/providers/gemini.test.ts` - Add test cases
**Steps:**
1. Add model configuration with proper token limits
2. Update documentation with model capabilities
3. Add to constants file for UI display
4. Write tests for new model configuration
**Important notes:**
- Check Google's documentation for exact token limits
- Ensure backward compatibility with existing configurations
- Test with actual API calls before committing
```
### Regular Task Execution
In the beginning of EVERY task I MUST read ALL memory bank files - this is not optional.
The memory bank files are located in `.kilocode/rules/memory-bank` folder. If the folder doesn't exist or is empty, I will warn user about potential issues with the memory bank. I will include `[Memory Bank: Active]` at the beginning of my response if I successfully read the memory bank files, or `[Memory Bank: Missing]` if the folder doesn't exist or is empty. If memory bank is missing, I will warn the user about potential issues and suggest initialization. I should briefly summarize my understanding of the project to confirm alignment with the user's expectations, like:
"[Memory Bank: Active] I understand we're building a React inventory system with barcode scanning. Currently implementing the scanner component that needs to work with the backend API."
When starting a task that matches a documented task in `tasks.md`, I should mention this and follow the documented workflow to ensure no steps are missed.
If the task was repetitive and might be needed again, I should suggest: "Would you like me to add this task to the memory bank for future reference?"
In the end of the task, when it seems to be completed, I will update `context.md` accordingly. If the change seems significant, I will suggest to the user: "Would you like me to update memory bank to reflect these changes?" I will not suggest updates for minor changes.
## Context Window Management
When the context window fills up during an extended session:
1. I should suggest updating the memory bank to preserve the current state
2. Recommend starting a fresh conversation/task
3. In the new conversation, I will automatically load the memory bank files to maintain continuity
## Technical Implementation
Memory Bank is built on Kilo Code's Custom Rules feature, with files stored as standard markdown documents that both the user and I can access.
## Important Notes
REMEMBER: After every memory reset, I begin completely fresh. The Memory Bank is my only link to previous work. It must be maintained with precision and clarity, as my effectiveness depends entirely on its accuracy.
If I detect inconsistencies between memory bank files, I should prioritize brief.md and note any discrepancies to the user.
IMPORTANT: I MUST read ALL memory bank files at the start of EVERY task - this is not optional. The memory bank files are located in `.kilocode/rules/memory-bank` folder.

View File

@@ -0,0 +1,374 @@
# System Architecture
## Project Structure
### Core Directory (`lib/core/`)
Central infrastructure and shared components:
- **Dependency Injection**: GetIt-based service locator in `locator_service.dart`
- **Routing**: GoRouter implementation in `app_router.dart` with deep linking
- **Theme**: Material theme with Mulish font family in `theme/theme_helper.dart`
- **Networking**: Dio HTTP client with token interceptor
- **WebSockets**: Pusher Channels for real-time communication
- **State Management**: Flutter BLoC/Cubit pattern
### Features Directory (`lib/features/`)
Feature-based modular architecture with 35+ feature modules:
**Core Features:**
- `auth/` - Authentication (email/password, OAuth)
- `feed/` - Content discovery feed
- `diary/` - Food diary tracking
- `chat/` - Real-time messaging
- `consultations/` - Consultation management
- `profile/` - User profiles and settings
**Content Creation:**
- `create_recipe/` - Recipe creation
- `create_diet/` - Diet plan creation
- `create_plan/` - Nutrition plan creation
- `blog_post_create/` - Blog post creation
**User Management:**
- `settings/` - User preferences
- `user_details/` - User information management
- `menu/` - App navigation menu
- `bottom_navigation_bar/` - Main navigation
**Consultant Features:**
- `consultant/` - Consultant verification
- `consultant_rating/` - Rating system
- `finances_and_consultations_archive/` - Financial tracking
**Supporting Features:**
- `notifications/` - Push notifications
- `glossary/` - Nutrition glossary
- `calendar/` - Calendar integration
- `support/` - Customer support
- `welcome/` - Onboarding
- `update_screen/` - App update management
## Architectural Patterns
### Clean Architecture Layers
Each feature follows a layered structure:
```
feature/
├── models/ # Data models (freezed + json_serializable)
├── services/ # API services (Retrofit)
├── repositories/ # Data repositories
├── presentation/ # UI layer
│ ├── pages/ # Screen widgets
│ ├── widgets/ # Feature-specific widgets
│ └── bloc/ # State management (Cubit)
└── entities/ # Domain entities
```
### Dependency Injection
**Registration Structure** (`lib/core/di/`):
- `app_config_registration.dart` - App configuration
- `external_registrations.dart` - External dependencies (Dio, etc.)
- `service_registrations.dart` - API services
- `repository_registrations.dart` - Data repositories
- `cubit_registrations.dart` - State management
**Service Lifecycle:**
- Singleton: Services, Repositories (most common)
- Factory: Cubits that need fresh instances
- Lazy Singleton: WebSocket manager, core services
### State Management Pattern
**BLoC/Cubit Implementation:**
- Global state: Registered in `AppConfig.globalBlocProviders`
- Feature state: Created per screen/feature
- State classes: Freezed unions for type-safe states
**Global Cubits:**
- `NewMessagesCubit` - Message notifications
- `NotificationsCubit` - Push notifications
- `FeedCubit` - Feed content
- `ProfileAvatarCubit` - User profile
- `ChatsCubit` - Chat rooms
- `ViewsCubit` - Content view tracking
- `InternetConnectionCubit` - Network status
## Data Flow
### API Integration
**Base Setup:**
- Base URL: Configurable via environment (prod/dev)
- HTTP Client: Dio with interceptors
- API Services: Retrofit for type-safe endpoints
- Authentication: Bearer token in headers
**Interceptors:**
1. `TokenInterceptor` - Adds auth token, handles 401 errors
2. `PhoneVerifyErrorInterceptor` - Handles phone verification errors
### Real-time Communication
**WebSocket Architecture:**
- Library: `dart_pusher_channels`
- Manager: `WsManager` (singleton)
- Connection: Authenticated via backend endpoint
**Channels:**
1. Private Notifications: `App\Events\BroadcastNotificationCreated`
2. Private Messages: `App\Events\ChatMessageUpdated`
3. Direct Chat: Room-specific message updates
4. Client Typing: Real-time typing indicators
**Socket ID Storage:**
- Persisted via SharedPreferences
- Used for authentication and channel subscription
### Authentication Flow
**Methods:**
1. Email/Password - Traditional credentials
2. OAuth Providers:
- VK ID (Russian social network)
- Yandex ID
- OK (Odnoklassniki)
- Mail.ru
**Token Management:**
- Storage: SharedPreferences via `TokenStorage`
- Refresh: Automatic on 401 response
- Logout: Token removal + WebSocket cleanup
**Post-Authentication:**
1. WebSocket initialization
2. Profile loading
3. Chat room loading
4. Notification loading
5. Firebase push token registration
## Navigation Architecture
### GoRouter Setup
**Route Structure:**
- Shell routes for persistent bottom navigation
- Named routes for easy navigation
- Deep linking support for content (recipe/blog_post/plan/diet)
**Route Groups:**
- `AuthRoutes` - Login, registration, password reset
- `MainNavigationRoutes` - Shell route with bottom nav
- `ContentRoutes` - Content viewing screens
- `SettingsRoutes` - User settings
- `OtherRoutes` - Miscellaneous screens
**Deep Linking Pattern:**
```
/content/{type}/{identifier}
- /content/recipe/{slug}
- /content/blog_post/{id}
- /content/plan/{slug}
- /content/diet/{slug}
```
### Bottom Navigation
**Main Sections:**
1. My Profile - User profile and content
2. Feed - Content discovery
3. Diary - Food tracking
4. Consultations - Consultation management
5. Chat - Messaging
6. Notifications - Notification center
7. Menu - Settings and more
**Implementation:**
- `BottomNavigationBarWidget` wraps content
- No transition animations for tab switches
- WebSocket initialization on feed screen
## Data Persistence
### Storage Solutions
**SharedPreferences:**
- Authentication token
- Socket ID
- User preferences
**Cached Network Images:**
- Library: `cached_network_image`
- Automatic caching of user avatars, content images
**Firebase:**
- Push notification tokens
- Remote configuration
- Analytics events
## Critical Implementation Details
### Content View Tracking
**Pattern:**
- `ViewsCubit` handles visibility detection
- `VisibilityDetector` widget tracks on-screen time
- Views sent to backend when 50%+ visible for 2+ seconds
- Debounced to prevent excessive API calls
**Tracked Content:**
- Blog posts
- Recipes
- Diets
- Nutrition plans
### Image Handling
**Upload Flow:**
1. `ImagePicker` for selection
2. `FlutterImageCompress` for compression
3. MultiPart form data upload via Dio
4. Preview via `CachedNetworkImage`
**Supported Formats:**
- User photos (profile, diary)
- Content images (recipes, diets, plans)
- Chat attachments
### Search Implementation
**Debounced Search:**
- Library: `easy_debounce`
- Delay: 500ms
- Min query length: 3 characters
- Applied to: Feed, Recipes, Diets, Plans, Consultants
**Tag-based Filtering:**
- Recipe tags for filtering
- Modal bottom sheet UI
- Persistent selection across sessions
### Pagination Pattern
**Implementation:**
- Page-based pagination
- Scroll detection for next page load
- Loading state during fetch
- Meta data tracking (current page, last page)
**Example (FeedCubit):**
```dart
currentPage = 1
lastPage = meta.lastPage
loadNextPage() when currentPage < lastPage
```
## Error Handling
### Network Errors
**401 Unauthorized:**
- Auto logout
- Token removal
- Navigate to auth screen
**Connection Errors:**
- `InternetConnectionCubit` monitors status
- Retry mechanisms in repositories
- User-friendly error messages
### State Error Handling
**Pattern:**
```dart
sealed class State {
const State.loading();
const State.loaded({required data});
const State.error({required String errorMessage});
}
```
**UI Response:**
- Loading: Show loaders/skeletons
- Error: Show `DataErrorWidget` with retry
- Empty: Show empty state messages
## Performance Optimizations
### Lazy Loading
- Lazy singleton services
- On-demand cubit creation
- Deferred widget loading
### Image Optimization
- Compression before upload
- Cached network images
- Thumbnail generation
### WebSocket Management
- Connection reuse
- Automatic reconnection
- Proper cleanup on logout
### List Rendering
- Pagination for large lists
- ListView.builder for efficiency
- Visibility detection for tracking
## Platform-Specific Features
### Android
- Huawei HMS support for Huawei devices
- Google FCM for push notifications
- ProGuard rules for release builds
- QR code scanning via camera
### iOS
- APNs for push notifications
- Deep linking configuration
- App Store compliance
### Firebase Integration
- Separate configs for Android/iOS
- Environment-based configuration
- Push notification handling
- Analytics tracking
## Security Considerations
### Authentication
- Bearer token authentication
- Secure token storage
- Automatic session management
- OAuth 2.0 for social login
### Data Protection
- HTTPS only communication
- Token encryption in storage
- Secure WebSocket connections
- Privacy policy compliance
## Key Files Reference
**Entry Point:**
- `lib/main.dart` - App initialization
**Core Infrastructure:**
- `lib/core/app_initializer.dart` - Startup sequence
- `lib/core/locator_service.dart` - DI container
- `lib/core/app_config.dart` - App configuration
- `lib/core/app_router.dart` - Routing setup
**WebSocket:**
- `lib/core/websockets/ws_manager.dart` - Connection management
- `lib/core/websockets/ws_service.dart` - API service
**Authentication:**
- `lib/features/auth/sdk/social_auth_facade.dart` - Social auth
- `lib/core/token_storage.dart` - Token persistence
- `lib/core/interceptors/token_interceptor.dart` - Auth interceptor
**Environment:**
- `lib/core/env_config.dart` - Environment variables
- `.env` - Environment file (not in repo)

View File

@@ -0,0 +1,35 @@
# Project Brief
## Project Name
Eatvio - Nutrition & Diet Management Application
## Project Description
A comprehensive mobile application connecting users with nutrition consultants, providing diet planning tools, recipes, food diary tracking, and professional consultation services.
## Core Features
- **Blog Posts**: Educational nutrition content and articles
- **Nutrition Consultation**: Professional consultation services with certified nutritionists
- **Recipes**: User-generated and professional recipes with nutritional information
- **Diets**: Structured diet plans with daily schedules
- **Nutrition Plans**: Long-term nutrition planning and tracking
## Target Audience
- Primary: Russian-speaking users interested in nutrition and healthy eating
- Secondary: Certified nutrition consultants offering professional services
- Market: Russian Federation and Russian-speaking countries
## Platform
- Mobile: iOS and Android (including Huawei devices)
- Language: Russian (ru)
- Current Version: 1.3.0+79
## Business Model
- Paid consultations with nutritionists
- Content marketplace for premium diets and plans
- Subscription-based features for consultants
## Key Success Metrics
- User engagement with food diary
- Consultation bookings and completion rates
- Content creation by consultants
- User retention and progress tracking

View File

@@ -0,0 +1,38 @@
# Current Context
## Project Status
Memory Bank initialized on 2025-10-16. This is a mature Flutter application (v1.3.24+106) currently in production.
## Recent Activity
- Memory Bank initialization completed
- All core files documented
- Architecture and technology stack catalogued
## Current Focus
Виджет видеоплеера ленты (`lib/features/feed/presentation/widgets/feed_video_player_widget.dart`)
мигрирован с `webview_flutter` v4 на `flutter_inappwebview` 6.1.5. Цель — фикс
fullscreen-кнопки внутри embed-плеера (Rutube/YouTube): `webview_flutter` не реализует
Android `WebChromeClient.onShowCustomView/onHideCustomView`, а `flutter_inappwebview`
делает это нативно (`InAppWebViewChromeClient`). Паритет UX сохранён (превью → play →
скрытая загрузка → fade-in по Rutube `player:canPlay`, плюс страховочный таймер 4с
для провайдеров без этого протокола). Добавлена ориентация landscape на fullscreen.
Остальные 4 экрана на `webview_flutter` не трогались; обе зависимости в `pubspec.yaml`.
## Known Issues
- 2 теста в `test/features/feed/` (`post_feed_pagination_model_test`,
`post_feed_mapper_test`) падают на ветке `personalized_feed` — пре-существующие,
связаны с fixtures/маппингом, не с видеоплеером.
## Next Steps
Awaiting user direction for:
- Feature development
- Bug fixes
- Architecture improvements
- Performance optimizations
## Important Notes
- Primary language: Russian (ru)
- Target market: Russian users
- Multi-platform: Android (including Huawei) and iOS
- Environment: Uses `.env` file for configuration (not in repository)
- Build system: Requires code generation for models/services

View File

@@ -0,0 +1,73 @@
# Product Overview
## Purpose
Eatvio is a comprehensive nutrition and diet management mobile application that connects users with nutrition consultants, provides diet planning tools, recipes, and personal food diary tracking.
## Core Problems It Solves
### For Regular Users:
1. **Diet Management**: Track daily food intake with detailed nutritional information
2. **Meal Planning**: Access to recipes and structured diet plans
3. **Professional Guidance**: Connect with certified nutrition consultants
4. **Progress Tracking**: Monitor weight, body measurements, and dietary habits
5. **Knowledge Access**: Learn about nutrition through blog posts and glossary
### For Nutrition Consultants:
1. **Client Management**: Communicate with clients via integrated chat
2. **Content Creation**: Create and publish diets, meal plans, recipes, and blog posts
3. **Consultation Services**: Offer paid nutrition consultation services
4. **Income Tracking**: Monitor earnings and client purchases
5. **Professional Presence**: Build profile and gain subscribers
## How It Works
### User Journey:
1. **Authentication**: Sign up via email/password or social networks (VK, Yandex, OK, Mail.ru)
2. **Feed Exploration**: Browse recipes, diets, nutrition plans, blog posts, and consultants
3. **Content Interaction**: Like, bookmark, comment on content
4. **Diary Tracking**: Log daily meals with photos and nutritional data
5. **Consultations**: Book and pay for nutrition consultant services
6. **Real-time Chat**: Communicate with consultants through integrated messaging
7. **Progress Monitoring**: Track weight and body measurements over time
### Consultant Journey:
1. **Become Consultant**: Apply and get verified as nutrition consultant
2. **Content Creation**: Publish professional diets, meal plans, recipes
3. **Client Interaction**: Respond to consultations and provide guidance
4. **Diary Review**: Review client food diaries and provide feedback
5. **Earnings Management**: Track income from consultations and content
## User Experience Goals
### Seamless Navigation:
- Bottom navigation bar for main sections (Profile, Feed, Diary, Consultations, Chat)
- Tab-based feed filtering (Blog posts, Recipes, Diets, Plans, Consultants)
- Deep linking support for direct content access
### Real-time Engagement:
- WebSocket-powered chat for instant messaging
- Push notifications for messages and updates
- Live content updates without app restart
### Professional Interface:
- Clean, modern UI with Mulish font family
- Intuitive search and filtering across all content types
- Visual progress tracking with charts and gauges
### Content Discovery:
- Tag-based recipe filtering
- Search functionality across all content types
- Personalized feed based on user interests
### Offline Capability:
- Token persistence for seamless re-authentication
- Cached content for better performance
- Queue system for offline actions
## Key Differentiators
1. **Integrated Platform**: Combines diet tracking, content, and professional consultations
2. **Social Features**: Follow consultants, like/bookmark content, engage with community
3. **Professional Tools**: Full toolkit for consultants to manage practice
4. **Russian Market Focus**: Optimized for Russian users with local payment and auth integrations
5. **Multi-platform Support**: Works on Android (including Huawei) and iOS

View File

@@ -0,0 +1,152 @@
# Technology Stack
## Core Framework
- **Flutter**: SDK 3.8.0+
- **Dart**: Language version >=3.8.0 <4.0.0
- **Version**: 1.3.0+79 (build 79)
## State Management
- **flutter_bloc**: ^9.1.1 - BLoC pattern implementation
- **equatable**: ^2.0.7 - Value equality for state objects
## Data Management
- **freezed**: ^3.2.0 - Immutable data classes
- **freezed_annotation**: ^3.1.0 - Code generation annotations
- **json_annotation**: ^4.9.0 - JSON serialization
- **json_serializable**: ^6.10.0 - JSON code generation
## Networking
- **dio**: ^5.9.0 - HTTP client
- **retrofit**: ^4.7.1 - Type-safe REST client
- **retrofit_generator**: ^10.0.2 - Retrofit code generation
- **http**: ^1.5.0 - Additional HTTP support
- **http_parser**: ^4.1.2 - HTTP parsing utilities
## Real-time Communication
- **dart_pusher_channels**: ^1.2.3 - WebSocket support via Pusher
- **connectivity_plus**: ^6.1.5 - Network connectivity monitoring
## Navigation & Routing
- **go_router**: ^16.1.0 - Declarative routing
- Deep linking support for content
## UI Components
- **cached_network_image**: ^3.4.1 - Image caching
- **flutter_svg**: ^2.2.0 - SVG rendering
- **google_fonts**: ^6.3.0 - Mulish font family
- **carousel_slider_plus**: ^7.1.1 - Carousel widgets
- **photo_view**: ^0.15.0 - Image viewer
- **dismissible_page**: ^1.0.2 - Swipe to dismiss
- **badges**: ^3.1.2 - Notification badges
- **lottie**: ^3.3.1 - Animation support
- **flutter_portal**: ^1.1.4 - Overlay widgets
- **dotted_border**: ^3.1.0 - Dotted borders
- **flutter_rating_bar**: ^4.0.1 - Rating widgets
## Forms & Input
- **flutter_form_builder**: ^10.2.0 - Form management
- **validators**: ^3.0.0 - Input validation
- **flutter_typeahead**: ^5.2.0 - Autocomplete
- **keyboard_dismisser**: ^3.0.0 - Keyboard management
- **flutter_keyboard_visibility**: ^6.0.0 - Keyboard state
- **mask_text_input_formatter**: ^2.9.0 - Input masking
## Media & Files
- **image_picker**: ^1.2.0 - Image selection
- **flutter_image_compress**: ^2.4.0 - Image compression
- **image**: ^4.5.4 - Image manipulation
- **file_picker**: ^10.3.1 - File selection
- **audioplayers**: ^6.5.0 - Audio playback
- **qr_code_scanner_plus**: ^2.0.10+1 - QR code scanning
## Data Visualization
- **syncfusion_flutter_charts**: ^30.2.5 - Chart widgets
- **syncfusion_flutter_gauges**: ^30.2.5 - Gauge widgets
- **table_calendar**: ^3.2.0 - Calendar widget
## Storage & Persistence
- **shared_preferences**: ^2.5.3 - Local key-value storage
- **path_provider**: ^2.1.5 - File system paths
- **path**: ^1.9.1 - Path manipulation
## Firebase
- **firebase_core**: ^4.0.0 - Firebase initialization
- **firebase_messaging**: ^16.0.0 - Push notifications
## Analytics & Monitoring
- **sentry_flutter**: ^9.6.0 - Error tracking
- **appmetrica_plugin**: ^3.3.0 - Analytics (Russian market)
## Authentication
- **vk_id**: ^1.0.3 - VK social login
- **flutter_login_yandex**: ^0.0.5 - Yandex ID login
- OAuth support for OK and Mail.ru
## Utilities
- **url_launcher**: ^6.3.2 - URL handling
- **easy_debounce**: ^2.0.3 - Debouncing
- **share_plus**: ^11.1.0 - Content sharing
- **flutter_html**: ^3.0.0 - HTML rendering
- **webview_flutter**: ^4.13.0 - WebView
- **intl**: ^0.20.2 - Internationalization
- **collection**: ^1.19.1 - Collection utilities
- **uuid**: ^4.5.1 - UUID generation
- **visibility_detector**: ^0.4.0+2 - Visibility tracking
- **fluttertoast**: ^8.2.12 - Toast messages
- **version**: ^3.0.2 - Version management
- **package_info_plus**: ^8.3.1 - Package info
- **device_info_plus**: ^11.5.0 - Device information
- **permission_handler**: ^12.0.1 - Permissions
## Platform-Specific
### Android
- Huawei HMS Push (6.12.0.300)
- Huawei Analytics (6.12.0.300)
- Google Play Services
- ProGuard for code obfuscation
- NDK version 27.0.12077973
- Compile SDK: Flutter default
- Min SDK: Flutter default
- Target SDK: Flutter default
### iOS
- APNs for push notifications
- Deep linking support
## Development Tools
- **build_runner**: ^2.7.0 - Code generation
- **flutter_native_splash**: ^2.4.6 - Splash screen
- **flutter_lints**: ^6.0.0 - Linting
- **mockito**: ^5.5.0 - Mocking for tests
- **flutter_test**: SDK - Testing framework
- **integration_test**: SDK - Integration testing
- **flutter_dotenv**: ^5.2.1 - Environment variables
## Localization
- **flutter_localizations**: SDK - Localization
- **flutter_intl**: Enabled - Internationalization
- Primary language: Russian (ru)
## Build Configuration
- **Environment**: Production/Development/Test modes
- **Build types**: Debug, Release, Profile
- **Code generation**: Freezed, JSON, Retrofit
- **Obfuscation**: ProGuard (Android release)
- **Resource optimization**: Shrink resources enabled
## API Integration Patterns
- RESTful API via Retrofit
- Bearer token authentication
- Interceptor-based auth injection
- Automatic 401 handling
- Environment-based base URLs
- Type-safe API clients
## Development Workflow
1. Code generation: `flutter pub run build_runner build`
2. Clean generation: `flutter pub run build_runner build --delete-conflicting-outputs`
3. Watch mode: `flutter pub run build_runner watch`
4. Environment setup: `.env` file configuration
5. Firebase setup: Separate configs per platform
6. Testing: Unit tests + Integration tests

View File

@@ -54,6 +54,15 @@ cp env.example .env
- `GOOGLE_CHECK_URL` - URL для проверки соединения (Google)
- `YANDEX_CHECK_URL` - URL для проверки соединения (Yandex)
### VK ID Configuration
- `VK_CLIENT_ID` - ID приложения VK (числовой)
- **Примечание**: VK_CLIENT_ID - это числовой "ID приложения" из консоли VK ID, НЕ "Защищённый ключ" или "Сервисный ключ доступа"
### Yandex ID Configuration
- `YANDEX_CLIENT_ID` - ID приложения Yandex OAuth
- `YANDEX_CLIENT_SECRET` - секретный ключ приложения Yandex OAuth
- `YANDEX_REDIRECT_URI` - URI для перенаправления (должен совпадать с настройками в Yandex OAuth приложении)
## Безопасность
⚠️ **ВАЖНО**: Файл `.env` добавлен в `.gitignore` и не должен попадать в репозиторий. Все секретные данные должны храниться только в этом файле.

View File

@@ -4,4 +4,10 @@ run-tests:
run-analyse:
flutter analyze
run-checks: run-analyse run-tests
run-checks: run-analyse run-tests
build-generated-files:
dart run build_runner build --delete-conflicting-outputs
clean-coverage:
@./scripts/remove_generated_from_coverage.sh

450
README.md
View File

@@ -1 +1,449 @@
# eatvio_app
# Eatvio - Nutrition & Diet Management Application
## Project Overview
Eatvio is a comprehensive mobile application connecting users with nutrition consultants, providing diet planning tools, recipes, food diary tracking, and professional consultation services. The application is specifically designed for Russian-speaking users interested in nutrition and healthy eating.
### Core Features
- **Blog Posts**: Educational nutrition content and articles
- **Nutrition Consultation**: Professional consultation services with certified nutritionists
- **Recipes**: User-generated and professional recipes with nutritional information
- **Diets**: Structured diet plans with daily schedules
- **Nutrition Plans**: Long-term nutrition planning and tracking
### Target Audience
- **Primary**: Russian-speaking users interested in nutrition and healthy eating
- **Secondary**: Certified nutrition consultants offering professional services
- **Market**: Russian Federation and Russian-speaking countries
### Business Model
- Paid consultations with nutritionists
- Content marketplace for premium diets and plans
- Subscription-based features for consultants
### Platform Information
- **Mobile**: iOS and Android (including Huawei devices)
- **Language**: Russian (ru)
- **Current Version**: 1.3.0+79 (build 79)
## Prerequisites
### Flutter & Dart Versions
- **Flutter**: SDK 3.8.0+
- **Dart**: Language version >=3.8.0 <4.0.0
### Platform-Specific Requirements
#### Android
- **NDK Version**: 27.0.12077973
- **Huawei HMS Dependencies**:
- Huawei Push (6.12.0.300)
- Huawei Analytics (6.12.0.300)
- **Google Play Services**
- **ProGuard** for code obfuscation
- **Compile SDK**: Flutter default
- **Min SDK**: Flutter default
- **Target SDK**: Flutter default
#### iOS
- **APNs** for push notifications
- **Deep linking** configuration
- **Xcode** version compatible with Flutter requirements
#### General IDE Requirements
- **VS Code** with Flutter/Dart extensions
- **Android Studio** with Flutter plugin
- **Visual Studio Code** recommended for development
## Environment Configuration
### .env Setup Process
1. Copy the environment template:
```bash
cp env.example .env
```
2. Edit the `.env` file with your configuration values
### Required Environment Variables
#### API URLs
- `BASE_URL` - основной URL API (по умолчанию: https://eatvio.ru)
- `DEV_BASE_URL` - URL API для разработки (по умолчанию: https://dev2.eatvio.com)
#### Sentry Configuration
- `SENTRY_DSN` - DSN для Sentry мониторинга
#### Firebase Configuration
- `FIREBASE_PROJECT_ID` - ID проекта Firebase
- `FIREBASE_DATABASE_URL` - URL базы данных Firebase
- `FIREBASE_STORAGE_BUCKET` - bucket для хранения файлов
- `FIREBASE_MESSAGING_SENDER_ID` - ID отправителя сообщений
#### Firebase Android Configuration
- `FIREBASE_ANDROID_API_KEY` - API ключ для Android
- `FIREBASE_ANDROID_APP_ID` - ID приложения для Android
#### Firebase iOS Configuration
- `FIREBASE_IOS_API_KEY` - API ключ для iOS
- `FIREBASE_IOS_APP_ID` - ID приложения для iOS
- `FIREBASE_IOS_BUNDLE_ID` - Bundle ID для iOS
#### App Store URLs
- `APP_STORE_URL` - URL App Store
- `RUSTORE_URL` - URL RuStore
#### Support URLs
- `TELEGRAM_SUPPORT_URL` - URL поддержки в Telegram
- `SUPPORT_EMAIL` - email для поддержки
#### Test Credentials (только для разработки)
- `TEST_EMAIL` - тестовый email
- `TEST_PASSWORD` - тестовый пароль
#### Email Validation API
- `EMAIL_VALIDATION_API_URL` - URL API для валидации email
#### Connection Check URLs
- `GOOGLE_CHECK_URL` - URL для проверки соединения (Google)
- `YANDEX_CHECK_URL` - URL для проверки соединения (Yandex)
#### VK ID Configuration
- `VK_CLIENT_ID` - ID приложения VK (числовой)
- **Примечание**: VK_CLIENT_ID - это числовой "ID приложения" из консоли VK ID, НЕ "Защищённый ключ" или "Сервисный ключ доступа"
#### Yandex ID Configuration
- `YANDEX_CLIENT_ID` - ID приложения Yandex OAuth
- `YANDEX_CLIENT_SECRET` - секретный ключ приложения Yandex OAuth
- `YANDEX_REDIRECT_URI` - URI для перенаправления (должен совпадать с настройками в Yandex OAuth приложении)
## Technology Stack
### Core Framework
- **Flutter**: SDK 3.8.0+
- **Dart**: Language version >=3.8.0 <4.0.0
- **Version**: 1.3.0+79 (build 79)
### State Management
- **flutter_bloc**: ^9.1.1 - BLoC pattern implementation
- **equatable**: ^2.0.7 - Value equality for state objects
### Data Management
- **freezed**: ^3.2.0 - Immutable data classes
- **freezed_annotation**: ^3.1.0 - Code generation annotations
- **json_annotation**: ^4.9.0 - JSON serialization
- **json_serializable**: ^6.10.0 - JSON code generation
### Networking
- **dio**: ^5.9.0 - HTTP client
- **retrofit**: ^4.7.1 - Type-safe REST client
- **retrofit_generator**: ^10.0.2 - Retrofit code generation
- **http**: ^1.5.0 - Additional HTTP support
- **http_parser**: ^4.1.2 - HTTP parsing utilities
### Real-time Communication
- **dart_pusher_channels**: ^1.2.3 - WebSocket support via Pusher
- **connectivity_plus**: ^6.1.5 - Network connectivity monitoring
### Navigation & Routing
- **go_router**: ^16.1.0 - Declarative routing
- Deep linking support for content
### UI Components
- **cached_network_image**: ^3.4.1 - Image caching
- **flutter_svg**: ^2.2.0 - SVG rendering
- **google_fonts**: ^6.3.0 - Mulish font family
- **carousel_slider_plus**: ^7.1.1 - Carousel widgets
- **photo_view**: ^0.15.0 - Image viewer
- **dismissible_page**: ^1.0.2 - Swipe to dismiss
- **badges**: ^3.1.2 - Notification badges
- **lottie**: ^3.3.1 - Animation support
- **flutter_portal**: ^1.1.4 - Overlay widgets
- **dotted_border**: ^3.1.0 - Dotted borders
- **flutter_rating_bar**: ^4.0.1 - Rating widgets
### Forms & Input
- **flutter_form_builder**: ^10.2.0 - Form management
- **validators**: ^3.0.0 - Input validation
- **flutter_typeahead**: ^5.2.0 - Autocomplete
- **keyboard_dismisser**: ^3.0.0 - Keyboard management
- **flutter_keyboard_visibility**: ^6.0.0 - Keyboard state
- **mask_text_input_formatter**: ^2.9.0 - Input masking
### Media & Files
- **image_picker**: ^1.2.0 - Image selection
- **flutter_image_compress**: ^2.4.0 - Image compression
- **image**: ^4.5.4 - Image manipulation
- **file_picker**: ^10.3.1 - File selection
- **audioplayers**: ^6.5.0 - Audio playback
- **qr_code_scanner_plus**: ^2.0.10+1 - QR code scanning
### Data Visualization
- **syncfusion_flutter_charts**: ^30.2.5 - Chart widgets
- **syncfusion_flutter_gauges**: ^30.2.5 - Gauge widgets
- **table_calendar**: ^3.2.0 - Calendar widget
### Storage & Persistence
- **shared_preferences**: ^2.5.3 - Local key-value storage
- **path_provider**: ^2.1.5 - File system paths
- **path**: ^1.9.1 - Path manipulation
### Firebase
- **firebase_core**: ^4.0.0 - Firebase initialization
- **firebase_messaging**: ^16.0.0 - Push notifications
### Analytics & Monitoring
- **sentry_flutter**: ^9.6.0 - Error tracking
- **appmetrica_plugin**: ^3.3.0 - Analytics (Russian market)
### Authentication
- **vk_id**: ^1.0.3 - VK social login
- **flutter_login_yandex**: ^0.0.5 - Yandex ID login
- OAuth support for OK and Mail.ru
### Utilities
- **url_launcher**: ^6.3.2 - URL handling
- **easy_debounce**: ^2.0.3 - Debouncing
- **share_plus**: ^11.1.0 - Content sharing
- **flutter_html**: ^3.0.0 - HTML rendering
- **webview_flutter**: ^4.13.0 - WebView
- **intl**: ^0.20.2 - Internationalization
- **collection**: ^1.19.1 - Collection utilities
- **uuid**: ^4.5.1 - UUID generation
- **visibility_detector**: ^0.4.0+2 - Visibility tracking
- **fluttertoast**: ^8.2.12 - Toast messages
- **version**: ^3.0.2 - Version management
- **package_info_plus**: ^8.3.1 - Package info
- **device_info_plus**: ^11.5.0 - Device information
- **permission_handler**: ^12.0.1 - Permissions
## Development Workflow
### Code Generation
- Run `flutter pub run build_runner build` for code generation
- Run `flutter pub run build_runner build --delete-conflicting-outputs` for clean generation
- Use `flutter pub run build_runner watch` for watch mode
### Environment Setup
- Configure `.env` file with all required variables
- Set up Firebase for both Android and iOS platforms
- Configure social authentication providers (VK, Yandex, etc.)
### Testing
- Unit tests with `flutter_test`
- Integration tests with `integration_test`
- Mocking with `mockito`
## Build Commands
### Development Builds
```bash
# Run on connected device
flutter run
# Run on specific Android device
flutter run -d emulator-5554
# Run on specific iOS simulator
flutter run -d iPhone\ 15
```
### Production Builds
#### Android
```bash
# Build APK (split by ABI)
flutter build apk --release --split-per-abi
# Build App Bundle
flutter build appbundle --release
# Huawei-specific build (with HMS)
flutter build apk --release --flavor production --target-platform android-arm64
```
#### iOS
```bash
# Build IPA for TestFlight
flutter build ipa --export-options-plist=ExportOptions.plist
# Build for specific device architecture
flutter build ipa --export-options-plist=ExportOptions.plist --no-codesign
```
## Optimization Techniques
### Android Build Optimization
1. **ProGuard Rules**:
- Configure rules in [`android/app/proguard-rules.pro`](android/app/proguard-rules.pro:1)
- Essential rules for Flutter:
```
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
```
2. **Resource Shrinking**:
- Enabled in `android/app/build.gradle`:
```gradle
buildTypes {
release {
shrinkResources true
minifyEnabled true
}
}
```
3. **Code Obfuscation**:
- Use `--obfuscate` flag with build commands
- Verify with `flutter build apk --release --obfuscate --split-debug-info=debug-info/`
4. **Image Compression Workflow**:
- Automatic compression via [`flutter_image_compress`](lib/features/create_diet/models/create_diet_model.dart:1)
- Configuration in image upload flows:
```dart
final compressedFile = await FlutterImageCompress.compressWithFile(
file.path,
quality: 85,
minWidth: 1024,
minHeight: 1024,
);
```
## Troubleshooting
### Common Issues
#### Missing .env Variables
- **Symptom**: Application crashes on startup with "Missing environment variable" error
- **Solution**:
1. Verify `.env` file exists in project root
2. Check [`ENV_SETUP.md`](ENV_SETUP.md) for required variables
3. Regenerate configuration with `flutter clean && flutter pub get`
#### Firebase Configuration Errors
- **Android**:
- Missing `google-services.json` in `android/app/`
- Missing `agconnect-services.json` for Huawei devices
- Verify SHA-1 fingerprints match Firebase console
- **iOS**:
- Missing `GoogleService-Info.plist` in `ios/Runner`
- Check bundle identifier matches Firebase project
#### WebSocket Connection Failures
- **Symptoms**: Chat messages not delivering, real-time updates not working
- **Solutions**:
1. Verify Pusher configuration in [`lib/core/websockets/ws_manager.dart`](lib/core/websockets/ws_manager.dart:1)
2. Check network connectivity with `connectivity_plus` package
3. Ensure proper authentication token is sent with WebSocket connection
#### Platform-Specific Build Errors
- **Huawei vs Google Services**:
- For Huawei devices, ensure `agconnect-services.json` is present
- Use `--flavor` flag to specify build variant:
```bash
flutter build apk --release --flavor hms
```
- Check for conflicting dependencies between HMS and GMS
- **iOS Code Signing Issues**:
- Verify `ExportOptions.plist` contains correct provisioning profiles
- Update signing certificates in Xcode
- Clean build folder: `flutter clean && rm -rf ios/Pods ios/Podfile.lock`
## Key Implementation Details
### Content View Tracking
- `ViewsCubit` handles visibility detection
- `VisibilityDetector` widget tracks on-screen time
- Views sent to backend when 50%+ visible for 2+ seconds
- Debounced to prevent excessive API calls
### Image Handling
- `ImagePicker` for selection
- `FlutterImageCompress` for compression
- MultiPart form data upload via Dio
- Preview via `CachedNetworkImage`
### Search Implementation
- Debounced search with 500ms delay
- Min query length: 3 characters
- Applied to: Feed, Recipes, Diets, Plans, Consultants
- Tag-based filtering for recipes
### Pagination Pattern
- Page-based pagination
- Scroll detection for next page load
- Loading state during fetch
- Meta data tracking (current page, last page)
## Security Considerations
### Authentication
- Bearer token authentication
- Secure token storage
- Automatic session management
- OAuth 2.0 for social login
### Data Protection
- HTTPS only communication
- Token encryption in storage
- Secure WebSocket connections
- Privacy policy compliance
## Key Files Reference
### Entry Point
- `lib/main.dart` - App initialization
### Core Infrastructure
- `lib/core/app_initializer.dart` - Startup sequence
- `lib/core/locator_service.dart` - DI container
- `lib/core/app_config.dart` - App configuration
- `lib/core/app_router.dart` - Routing setup
### WebSocket
- `lib/core/websockets/ws_manager.dart` - Connection management
- `lib/core/websockets/ws_service.dart` - API service
### Authentication
- `lib/features/auth/sdk/social_auth_facade.dart` - Social auth
- `lib/core/token_storage.dart` - Token persistence
- `lib/core/interceptors/token_interceptor.dart` - Auth interceptor
### Environment
- `lib/core/env_config.dart` - Environment variables
- `.env` - Environment file (not in repo)
## Key Success Metrics
- User engagement with food diary
- Consultation bookings and completion rates
- Content creation by consultants
- User retention and progress tracking
## Documentation Standards
- **Last Updated**: 2025-10-16
- All paths are relative to `/home/apoloz/dev/eatvio_app`
- Russian market focus maintained throughout documentation
- Version compatibility matrix:
| Component | Version | Notes |
|-----------|---------|-------|
| Flutter | 3.8.0+ | Required |
| Dart | 3.8.0-3.9.9 | Required |
| Android SDK | 34 | Target SDK |
| iOS Deployment | 14.0 | Minimum |
## Ubuntu Development PC Optimization
```bash
-# apt install linux-oem-24.04
-# sudo apt-get install --install-recommends linux-lowlatency-hwe-24.04
```
----
- ubuntu switch to hwe [kernel](https://canonical-kernel-docs.readthedocs-hosted.com/latest/reference/hwe-kernels/#installing-a-hwe-kernel)
----
- ubuntu instal intel iRIS gpu [drivers](https://dgpu-docs.intel.com/driver/client/overview.html#ubuntu-latest)
```

55
analyze_coverage.py Normal file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/env python3
import re
def analyze_coverage():
files = {}
current_file = None
with open('coverage/lcov.info', 'r', encoding='utf-8') as f:
lines = f.readlines()
i = 0
while i < len(lines):
line = lines[i].strip()
if line.startswith('SF:'):
current_file = line[3:]
files[current_file] = {'total': 0, 'covered': 0}
i += 1
elif line.startswith('LF:') and current_file:
files[current_file]['total'] = int(line[3:])
i += 1
elif line.startswith('LH:') and current_file:
files[current_file]['covered'] = int(line[3:])
i += 1
else:
i += 1
# Filter out generated files
filtered = []
for f, d in files.items():
if not f.endswith('.g.dart') and not 'generated' in f.lower() and not f.endswith('l10n.dart'):
filtered.append((f, d))
# Find files with less than 50% coverage
low_coverage = []
for f, d in filtered:
if d['total'] > 0:
pct = d['covered']/d['total']*100
if pct < 50:
low_coverage.append((f, d))
# Sort by coverage percentage (lowest first)
sorted_files = sorted(
low_coverage,
key=lambda x: (x[1]['covered']/x[1]['total']*100 if x[1]['total'] > 0 else 0)
)
print('Files with less than 50% coverage:')
print('=' * 80)
for f, d in sorted_files[:50]:
pct = d['covered']/d['total']*100
print(f'{pct:6.1f}% ({d["covered"]:4d}/{d["total"]:4d}) - {f}')
if __name__ == '__main__':
analyze_coverage()

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
import re
def analyze_coverage_by_uncovered():
files = {}
current_file = None
with open('coverage/lcov.info', 'r', encoding='utf-8') as f:
lines = f.readlines()
i = 0
while i < len(lines):
line = lines[i].strip()
if line.startswith('SF:'):
current_file = line[3:]
files[current_file] = {'total': 0, 'covered': 0}
i += 1
elif line.startswith('LF:') and current_file:
files[current_file]['total'] = int(line[3:])
i += 1
elif line.startswith('LH:') and current_file:
files[current_file]['covered'] = int(line[3:])
i += 1
else:
i += 1
# Filter out generated files and UI screens/widgets (hard to test)
filtered = []
exclude_patterns = ['.g.dart', 'generated', 'l10n.dart', '/pages/', '/widgets/', '_screen.dart', '_widget.dart']
for f, d in files.items():
if d['total'] > 0:
# Skip UI files
should_exclude = any(pattern in f for pattern in exclude_patterns)
if not should_exclude:
uncovered = d['total'] - d['covered']
pct = d['covered']/d['total']*100
filtered.append((f, d, uncovered, pct))
# Sort by uncovered lines (most uncovered first)
sorted_files = sorted(filtered, key=lambda x: x[2], reverse=True)
print('Files sorted by uncovered lines (excluding UI screens/widgets):')
print('=' * 100)
print(f'{"Uncovered":>10} {"Covered":>8} {"Total":>8} {"%":>7} {"File":<60}')
print('=' * 100)
for f, d, uncovered, pct in sorted_files[:30]:
print(f'{uncovered:>10} {d["covered"]:>8} {d["total"]:>8} {pct:>6.1f}% {f}')
if __name__ == '__main__':
analyze_coverage_by_uncovered()

52
analyze_output.txt Normal file
View File

@@ -0,0 +1,52 @@
Files with less than 50% coverage:
================================================================================
0.0% ( 0/ 37) - lib/core/firebase_api.dart
0.0% ( 0/ 1) - lib/features/auth/models/oauth_verification_confirm_request.dart
0.0% ( 0/ 1) - lib/features/auth/models/oauth_verification_confirm_response.dart
0.0% ( 0/ 1) - lib/features/auth/models/oauth_verification_request_response.dart
0.0% ( 0/ 342) - lib/features/dev_tools/test_cases.dart
0.9% ( 2/ 220) - lib/features/dev_tools/presentation/dev_tools_screen.dart
2.4% ( 1/ 42) - lib/features/auth/presentation/pages/scan_qr_code_screen.dart
2.9% ( 1/ 34) - lib/features/diary/presentation/pages/barcode_scanner_screen.dart
3.6% ( 1/ 28) - lib/features/personal_diet_suggestion/presentation/personal_diet_suggestion_screen.dart
3.8% ( 1/ 26) - lib/features/update_screen/presentation/update_screen.dart
4.4% ( 4/ 90) - lib/core/widgets/custom_popup.dart
5.9% ( 1/ 17) - lib/features/recipe/presentation/pages/my_recipes_screen.dart
6.2% ( 2/ 32) - lib/features/consultations/presentation/pages/consultations_screen.dart
7.1% ( 1/ 14) - lib/features/menu/presentation/pages/blocked_users_screen.dart
7.7% ( 1/ 13) - lib/features/registration_v2/presentation/pages/registration_v2_page.dart
8.3% ( 18/ 217) - lib/features/blog_post/presentation/pages/blog_post_screen.dart
11.1% ( 1/ 9) - lib/features/registration_v2/presentation/widgets/step_progress.dart
11.8% ( 14/ 119) - lib/features/auth/sdk/social_auth_facade.dart
13.0% ( 3/ 23) - lib/features/registration/presentation/bloc/registration_cubit/registration_cubit.dart
14.5% ( 11/ 76) - lib/core/app_router.dart
19.3% ( 11/ 57) - lib/features/create_recipe/presentation/widgets/image_widget.dart
19.6% ( 10/ 51) - lib/features/create_recipe/entities/recipe_create_entity.dart
19.7% ( 12/ 61) - lib/features/create_recipe/presentation/widgets/step_image_widget.dart
20.0% ( 6/ 30) - lib/core/image_compressing/image_compress_utility.dart
20.0% ( 57/ 285) - lib/features/complaining/presentation/complaining_bottom_sheet.dart
21.9% ( 7/ 32) - lib/core/routing/content_routes.dart
25.6% ( 46/ 180) - lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart
26.8% ( 11/ 41) - lib/features/create_recipe/reporitories/recipe_repository.dart
27.4% ( 96/ 351) - lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart
28.0% ( 28/ 100) - lib/core/utils/image_constant.dart
28.4% ( 23/ 81) - lib/core/websockets/ws_manager.dart
29.0% ( 157/ 541) - lib/features/profile/presentation/pages/profile_screen.dart
29.3% ( 137/ 468) - lib/features/notifications/models/notification_model.dart
33.1% ( 47/ 142) - lib/features/notifications/presentation/notifications_cubit/notifications_cubit.dart
33.3% ( 9/ 27) - lib/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart
35.2% ( 58/ 165) - lib/features/registration/presentation/pages/registration_screen.dart
35.6% ( 36/ 101) - lib/features/chat/presentation/pages/empty_chat_screen.dart
36.0% ( 9/ 25) - lib/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart
36.7% ( 11/ 30) - lib/core/routing/main_navigation_routes.dart
37.5% ( 3/ 8) - lib/core/permission_handler/permission_handler.dart
38.6% ( 22/ 57) - lib/features/registration/presentation/pages/date_of_birth_screen.dart
38.9% ( 35/ 90) - lib/core/routing/other_routes.dart
39.0% ( 30/ 77) - lib/features/create_diet/presentation/widgets/diet_image_picker_widget.dart
39.3% ( 119/ 303) - lib/features/settings/presentation/pages/settings_screen.dart
39.3% ( 22/ 56) - lib/features/consultant/become_consultant/presentation/pages/photo_or_scans_screen.dart
40.0% ( 4/ 10) - lib/features/menu/presentation/bloc/notification_settings_cubit/notification_settings_state.dart
40.0% ( 4/ 10) - lib/features/registration/services/registration_analytics_service.dart
41.5% ( 95/ 229) - lib/features/create_diet/presentation/cubit/create_diet_cubit.dart
41.9% ( 31/ 74) - lib/features/create_plan/presentation/widgets/plan_image_picker_widget.dart
42.7% ( 67/ 157) - lib/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart

View File

@@ -0,0 +1,94 @@
{
"agcgw" : {
"url" : "connect-drru.hispace.dbankcloud.ru",
"backurl" : "connect-drru.hispace.dbankcloud.cn",
"websocketurl" : "connect-ws-drru.hispace.dbankcloud.ru",
"websocketbackurl" : "connect-ws-drru.hispace.dbankcloud.cn"
},
"agcgw_all" : {
"SG" : "connect-dra.dbankcloud.cn",
"SG_back" : "connect-dra.hispace.hicloud.com",
"CN" : "connect-drcn.dbankcloud.cn",
"CN_back" : "connect-drcn.hispace.hicloud.com",
"RU" : "connect-drru.hispace.dbankcloud.ru",
"RU_back" : "connect-drru.hispace.dbankcloud.cn",
"DE" : "connect-dre.dbankcloud.cn",
"DE_back" : "connect-dre.hispace.hicloud.com"
},
"websocketgw_all" : {
"SG" : "connect-ws-dra.hispace.dbankcloud.cn",
"SG_back" : "connect-ws-dra.hispace.dbankcloud.com",
"CN" : "connect-ws-drcn.hispace.dbankcloud.cn",
"CN_back" : "connect-ws-drcn.hispace.dbankcloud.com",
"RU" : "connect-ws-drru.hispace.dbankcloud.ru",
"RU_back" : "connect-ws-drru.hispace.dbankcloud.cn",
"DE" : "connect-ws-dre.hispace.dbankcloud.cn",
"DE_back" : "connect-ws-dre.hispace.dbankcloud.com"
},
"client" : {
"cp_id" : "20007000036693451",
"product_id" : "461323198429446894",
"client_id" : "1595824543740483264",
"client_secret" : "2A1727B0D31AA9BE1F5D9E8A5CDA1A67B9EF084AC9FB68D6C633A3CCB08ECDEE",
"project_id" : "461323198429446894",
"app_id" : "113238569",
"api_key" : "DQEDAJNRITp9M3uc1rPHyT8PzLc7bnVcKJAeavZZk0TQNMx9ifvBebr+JOmZe9tEvjnLwv7c1hAHXmPGR/gWG86iABDrCVotq+NGnw==",
"package_name" : "com.eatvioapp.app"
},
"oauth_client" : {
"client_id" : "113238569",
"client_type" : 1
},
"app_info" : {
"app_id" : "113238569",
"package_name" : "com.eatvioapp.app"
},
"service" : {
"analytics" : {
"collector_url" : "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
"collector_url_cn" : "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
"collector_url_de" : "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
"collector_url_ru" : "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
"collector_url_sg" : "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
"resource_id" : "p1",
"channel_id" : ""
},
"ml" : {
"mlservice_url" : "ml-api-drru.ai.dbankcloud.ru,ml-api-drru.ai.dbankcloud.cn"
},
"cloudstorage" : {
"storage_url" : "https://agc-storage-drcn.platform.dbankcloud.cn",
"storage_url_ru" : "https://agc-storage-drru.cloud.huawei.ru",
"storage_url_sg" : "https://ops-dra.agcstorage.link",
"storage_url_de" : "https://ops-dre.agcstorage.link",
"storage_url_cn" : "https://agc-storage-drcn.platform.dbankcloud.cn",
"storage_url_ru_back" : "https://agc-storage-drru.cloud.huawei.ru",
"storage_url_sg_back" : "https://agc-storage-dra.cloud.huawei.asia",
"storage_url_de_back" : "https://agc-storage-dre.cloud.huawei.eu",
"storage_url_cn_back" : "https://agc-storage-drcn.cloud.huawei.com.cn"
},
"search" : {
"url" : "https://search-drru.cloud.huawei.ru"
},
"edukit" : {
"edu_url" : "edukit.cloud.huawei.com.cn",
"dh_url" : "edukit.cloud.huawei.com.cn"
}
},
"region" : "RU",
"configuration_version" : "3.0",
"appInfos" : [ {
"package_name" : "com.eatvioapp.app",
"client" : {
"app_id" : "113238569"
},
"app_info" : {
"package_name" : "com.eatvioapp.app",
"app_id" : "113238569"
},
"oauth_client" : {
"client_type" : 1,
"client_id" : "113238569"
}
} ]
}

View File

@@ -4,7 +4,9 @@ plugins {
id 'com.google.gms.google-services'
// END: FlutterFire Configuration
id "kotlin-android"
id "kotlin-parcelize"
id "dev.flutter.flutter-gradle-plugin"
id 'com.huawei.agconnect'
}
def keystoreProperties = new Properties()
@@ -13,26 +15,32 @@ if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
def yandexClientId = project.hasProperty('YANDEX_CLIENT_ID') ? project.property('YANDEX_CLIENT_ID') : (System.getenv('YANDEX_CLIENT_ID') ?: "")
android {
namespace = "com.eatvioapp.app"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
jvmTarget = JavaVersion.VERSION_17.toString()
}
defaultConfig {
applicationId = "com.eatvioapp.app"
minSdk = 23
minSdkVersion flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
manifestPlaceholders = [
YANDEX_CLIENT_ID: yandexClientId,
applicationName: "io.flutter.app.FlutterApplication"
]
}
signingConfigs {
@@ -47,6 +55,9 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.debug
@@ -57,6 +68,18 @@ android {
}
}
dependencies {
testImplementation 'junit:junit:4.13.2'
implementation platform('com.google.firebase:firebase-bom:34.4.0')
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.huawei.agconnect:agconnect-core:1.9.5.300'
implementation 'com.huawei.hms:push:6.13.0.301'
// Huawei Analytics dependency to satisfy com.huawei.hianalytics.* references during R8
implementation 'com.huawei.hms:hianalytics:6.12.0.301'
// BouncyCastle provider required by Huawei secure utils used transitively by HMS
implementation 'org.bouncycastle:bcprov-jdk15to18:1.78.1'
}
flutter {
source = "../.."
}

27
android/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,27 @@
-keep class com.huawei.** { *; }
-dontwarn com.huawei.**
-keep class org.bouncycastle.** { *; }
-dontwarn org.bouncycastle.**
-keep class com.hiennv.flutter_callkit_incoming.** { *; }
-dontwarn com.hiennv.flutter_callkit_incoming.**
-keep class com.pravera.flutter_foreground_task.** { *; }
-dontwarn com.pravera.flutter_foreground_task.**
-keep class io.flutter.** { *; }
-dontwarn io.flutter.**
-keep class kotlinx.coroutines.** { *; }
-dontwarn kotlinx.coroutines.**
-keep class **.R$* { *; }
-keepclassmembers class ** { @androidx.annotation.Keep *; }
-keep @androidx.annotation.Keep class * { *; }
-keep public class * extends android.app.Application
-keep public class * extends android.content.ContentProvider
-keep class * implements android.os.Parcelable { *; }
-keepclassmembers enum * { *; }

View File

@@ -1,7 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
@@ -11,11 +17,37 @@
android:usesCleartextTraffic="true"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<service
android:name=".EatvioFcmMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService"
tools:node="remove" />
<service
android:name=".HmsPushService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=113238569" />
<meta-data
android:name="com.huawei.hms.client.cpid"
android:value="cpid=20007000036693451" />
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:supportsPictureInPicture="true"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
@@ -39,20 +71,14 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<!-- Main domains -->
<data android:host="eatvio.ru" />
<data android:host="www.eatvio.ru" />
<data android:host="eatvio.com" />
<data android:host="www.eatvio.com" />
<data android:pathPattern="/ru/recipe/.*" />
<data android:pathPattern="/en/recipe/.*" />
<data android:pathPattern="/ru/blog_post/.*" />
<data android:pathPattern="/en/blog_post/.*" />
<data android:pathPattern="/ru/diet/.*" />
<data android:pathPattern="/en/diet/.*" />
<data android:pathPattern="/ru/plan/.*" />
<data android:pathPattern="/en/plan/.*" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
@@ -60,6 +86,77 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- The incoming notification's content intent and full-screen intent both open
CallkitIncomingActivity. Replace it with a bridge: a tap on an unlocked phone
routes to the same accept flow as Answer; on a locked/dark screen it shows a
ringing screen that wakes the device. Own task affinity keeps the plugin's
CLEAR_TASK flag from killing MainActivity. -->
<activity
android:name="com.hiennv.flutter_callkit_incoming.CallkitIncomingActivity"
tools:node="remove" />
<activity
android:name=".EatvioCallkitIncomingBridgeActivity"
android:exported="false"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:taskAffinity=""
android:allowTaskReparenting="false"
android:excludeFromRecents="true"
android:noHistory="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:launchMode="singleInstance"
android:configChanges="orientation" />
<activity-alias
android:name="com.hiennv.flutter_callkit_incoming.CallkitIncomingActivity"
android:targetActivity=".EatvioCallkitIncomingBridgeActivity"
android:exported="true"
android:taskAffinity=""
android:allowTaskReparenting="false"
android:excludeFromRecents="true"
android:noHistory="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:launchMode="singleInstance"
android:configChanges="orientation"
android:permission="${applicationId}.PERMISSION_CALL">
<intent-filter>
<action android:name="${applicationId}.com.hiennv.flutter_callkit_incoming.ACTION_CALL_INCOMING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
<activity
android:name="com.hiennv.flutter_callkit_incoming.TransparentActivity"
tools:node="remove" />
<activity
android:name=".EatvioCallkitTransparentBridgeActivity"
android:exported="false"
android:theme="@style/TranslucentTheme"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:excludeFromRecents="true"
android:noHistory="true"
android:launchMode="singleTop" />
<activity-alias
android:name="com.hiennv.flutter_callkit_incoming.TransparentActivity"
android:targetActivity=".EatvioCallkitTransparentBridgeActivity"
android:exported="false"
android:theme="@style/TranslucentTheme"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:excludeFromRecents="true"
android:noHistory="true"
android:launchMode="singleTop" />
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="microphone"
android:exported="false"
android:stopWithTask="true" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
@@ -71,5 +168,168 @@
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
<!-- SBP bank packages for СБП payment detection -->
<package android:name="ru.sberbankmobile" />
<package android:name="com.idamob.tinkoff.android" />
<package android:name="ru.vtb24.mobilebanking.android" />
<package android:name="ru.alfabank.mobile.android" />
<package android:name="ru.raiffeisennews" />
<package android:name="com.openbank" />
<package android:name="ru.gazprombank.android.mobilebank.app" />
<package android:name="com.logo.mbanking" />
<package android:name="ru.sovcomcard.halva.v1" />
<package android:name="ru.rosbank.android" />
<package android:name="ru.rshb.dbo" />
<package android:name="ru.mkb.mobile" />
<package android:name="ru.ucb.android" />
<package android:name="ru.unicredit.android" />
<package android:name="ru.skbbank.ib" />
<package android:name="ru.gebank.ib" />
<package android:name="ru.avangard.sbpent" />
<package android:name="ru.elplat.elplat2" />
<package android:name="com.bifit.rncbbeta" />
<package android:name="ru.ftc.faktura.expobank" />
<package android:name="com.bssys.vbrrretail" />
<package android:name="ru.wildberries.razz" />
<package android:name="ru.artsofte.russiafl" />
<package android:name="ru.ftc.faktura.multibank" />
<package android:name="ru.bank_hlynov.xbank" />
<package android:name="ru.ftc.faktura.vesta" />
<package android:name="com.isimplelab.ibank.solidarnost" />
<package android:name="com.bssys.roscapretail" />
<package android:name="ru.ftc.faktura.kbhmb" />
<package android:name="ru.mts.money" />
<package android:name="ru.ftc.faktura.pskb" />
<package android:name="ru.ftc.faktura.nskbl" />
<package android:name="ru.akbars.mobile" />
<package android:name="ru.ftc.faktura.rostfinance" />
<package android:name="ru.ilb.bbmobile" />
<package android:name="ru.mcbankrus.MCBankRus" />
<package android:name="ru.albank.online.aebit" />
<package android:name="com.bifit.mobile.citizen.icbru" />
<package android:name="ru.ftc.faktura.orbank" />
<package android:name="ru.ftc.faktura.agropromkredit" />
<package android:name="com.energobank.digital" />
<package android:name="com.bifit.mobile.citizen.kbnk" />
<package android:name="ru.ftc.faktura.sdm" />
<package android:name="com.bifit.mobile.citizen.mbb" />
<package android:name="ru.ftc.faktura.absolutbank" />
<package android:name="ru.ftc.faktura.akcept" />
<package android:name="ru.faktura.etbank.person" />
<package android:name="ru.ftc.faktura.razvitiestolica" />
<package android:name="ru.ftc.faktura.resokreditbank" />
<package android:name="ru.yoo.money" />
<package android:name="ru.bspb" />
<package android:name="com.isimplelab.ibank.kubankredit" />
<package android:name="com.tochka.bank" />
<package android:name="com.bssys.novikomretail" />
<package android:name="ru.rosdorbank.physical" />
<package android:name="ru.ftc.faktura.primsoc" />
<package android:name="ru.ftc.faktura.banksaratov" />
<package android:name="ru.ftc.faktura.tavrich" />
<package android:name="com.bifit.mobile.citizen.thbank" />
<package android:name="ru.ftc.faktura.kremlevskiy" />
<package android:name="ru.ftc.faktura.tkbbank" />
<package android:name="ru.chelyabinvestbank.investpay" />
<package android:name="ru.ftc.faktura.derzhava" />
<package android:name="ru.nbd.android" />
<package android:name="ru.sngb.dbo.client.android" />
<package android:name="ru.ftc.faktura.united" />
<package android:name="ru.ftc.faktura.venetsbank" />
<package android:name="ru.letobank.Prometheus" />
<package android:name="ru.simpls.brs2.mobbank" />
<package android:name="com.bifit.dvbank" />
<package android:name="ru.ftc.faktura.intesabank" />
<package android:name="com.mmonline.mobile" />
<package android:name="cb.ibank.vuz" />
<package android:name="ru.uralprombank.mobilebanknew.googleplay" />
<package android:name="ru.ftc.faktura.nsbank" />
<package android:name="ru.emb.android" />
<package android:name="ru.ftc.faktura.maritimebank" />
<package android:name="com.credituralbank.CUBmobilenew" />
<package android:name="com.isimplelab.isimpleceo.uglemet" />
<package android:name="com.bssys.stroylesretail" />
<package android:name="ru.ftc.faktura.iturup" />
<package android:name="ru.ftc.faktura.finbank" />
<package android:name="ru.faktura.gaztransbank.person" />
<package android:name="com.isimplelab.ibank.chelind" />
<package android:name="ru.ftc.faktura.nokss" />
<package android:name="ru.ftc.faktura.vlbb" />
<package android:name="ru.ftc.faktura.kbb" />
<package android:name="ru.faktura.avtograd.person" />
<package android:name="ru.ftc.faktura.forshtadt" />
<package android:name="ru.ftc.faktura.solidbank" />
<package android:name="ru.ftc.faktura.alexbank" />
<package android:name="ru.ftc.faktura.akibank" />
<package android:name="ru.ftc.faktura.nipbank" />
<package android:name="ru.ftc.faktura.alefbank" />
<package android:name="com.bifit.vfbank" />
<package android:name="com.bssys.uralfdretail" />
<package android:name="com.snb.online" />
<package android:name="com.bifit.mobile.citizen.okbank" />
<package android:name="com.tatsotsbank.dbomobile" />
<package android:name="ru.vtkbank.android" />
<package android:name="ru.faktura.jtbank.person" />
<package android:name="ru.ftc.faktura.ns" />
<package android:name="ru.ftc.faktura.zemskybank" />
<package android:name="com.bssys.aversretail" />
<package android:name="ru.rusnarbank.correqts.retail" />
<package android:name="ru.ftc.faktura.baikalinvestbank" />
<package android:name="ru.sbi.android" />
<package android:name="com.metkombank.mobile" />
<package android:name="com.isimplelab.ionic.kazan.fl" />
<package android:name="com.intervale.sbpas" />
<package android:name="com.bifit.mobile.citizen.zarech" />
<package android:name="ru.centrinvest.mobilebanking2018" />
<package android:name="com.mifors.izhcombank" />
<package android:name="com.bifit.pmobile.isbank" />
<package android:name="ru.zenit.android" />
<package android:name="ru.briginvest.sense" />
<package android:name="com.bifit.mobile.citizen.cfb" />
<package android:name="com.isimplelab.ionic.gorbank.prod" />
<package android:name="ru.ftc.faktura.moscombank" />
<package android:name="com.timerbank.retail" />
<package android:name="com.mob.android" />
<package android:name="com.citibank.mobile.ru" />
<package android:name="com.bifit.atbbank" />
<package android:name="ru.mw" />
<package android:name="ru.bankuralsib.mb.android" />
<package android:name="com.banksoyuz.artsofte" />
<package android:name="ru.rubank.ubsmobile" />
<package android:name="cb.ibank" />
<package android:name="ru.ipb.ubsmobile" />
<package android:name="com.openwaygroup.ic.panda.poidem" />
<package android:name="com.bifit.mobile.citizen.tenderbank" />
<package android:name="ru.otpbank.mobile" />
<package android:name="ru.krk.ubsmobile" />
<package android:name="ru.homecredit.mycredit" />
<package android:name="cz.bsc.rc" />
<package android:name="com.bifit.mobile.citizen.belsocbank" />
<package android:name="com.hicebank.android" />
<package android:name="com.bpc.crossplatform_trading.bpc_trading" />
<package android:name="com.bifit.nrb" />
<package android:name="com.bifit.mobile.citizen.moskb" />
<package android:name="ru.isfront.android.kt" />
<package android:name="ru.ftc.faktura.novobank" />
<package android:name="com.smp.android" />
<package android:name="com.bifit.mobile.citizen.nkbank" />
<package android:name="com.isimplelab.ibank.toyota" />
<package android:name="com.bifit.mobile.private.bbr" />
<package android:name="ru.ftc.faktura.lanta" />
<package android:name="com.yandex.bank" />
<package android:name="ru.ftc.faktura.bgfbank" />
<package android:name="com.idamobile.android.LockoBank" />
<package android:name="com.bifit.mobile.citizen.MCBank" />
<package android:name="com.cetelem.cetelem_android" />
<package android:name="com.bssys.gutaretail" />
<package android:name="ru.ftc.faktura.siab" />
<package android:name="com.isimplelab.ionic.round.prod" />
<package android:name="com.priobank.prio" />
<package android:name="com.inbank.mobilebank" />
<package android:name="com.isimplelab.isimplemobile.payjet" />
<package android:name="ru.ftc.faktura.agroros" />
<package android:name="com.bifit.mobile.citizen.invb" />
<package android:name="com.compassplus.mobicash.customer" />
<package android:name="ru.finambank.app" />
</queries>
</manifest>

View File

@@ -0,0 +1,53 @@
package com.eatvioapp.app
import android.content.Intent
import android.os.Bundle
import com.hiennv.flutter_callkit_incoming.CallkitConstants
import com.hiennv.flutter_callkit_incoming.FlutterCallkitIncomingPlugin
object CallKitAcceptIntentMapper {
fun payloadFromBundle(data: Bundle, action: String): Map<String, Any?>? {
if (!action.contains(CallkitConstants.ACTION_CALL_ACCEPT) &&
!action.contains(CallkitConstants.ACTION_CALL_CALLBACK)
) {
return null
}
return hashMapOf(
"action" to action,
"id" to data.getString(CallkitConstants.EXTRA_CALLKIT_ID, ""),
"handle" to data.getString(CallkitConstants.EXTRA_CALLKIT_HANDLE, ""),
"nameCaller" to data.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, ""),
"avatar" to data.getString(CallkitConstants.EXTRA_CALLKIT_AVATAR, ""),
"extra" to data.getSerializable(CallkitConstants.EXTRA_CALLKIT_EXTRA),
)
}
fun payloadFromIntent(intent: Intent?): Map<String, Any?>? {
if (intent == null) return null
val data = intent.getBundleExtra(FlutterCallkitIncomingPlugin.EXTRA_CALLKIT_CALL_DATA)
?: return null
val action = intent.action ?: return null
if (!action.contains(CallkitConstants.ACTION_CALL_ACCEPT) &&
!action.contains(CallkitConstants.ACTION_CALL_CALLBACK)
) {
return null
}
return hashMapOf(
"action" to action,
"id" to data.getString(CallkitConstants.EXTRA_CALLKIT_ID, ""),
"handle" to data.getString(CallkitConstants.EXTRA_CALLKIT_HANDLE, ""),
"nameCaller" to data.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, ""),
"avatar" to data.getString(CallkitConstants.EXTRA_CALLKIT_AVATAR, ""),
"extra" to data.getSerializable(CallkitConstants.EXTRA_CALLKIT_EXTRA),
)
}
fun clearCallKitLaunchIntent(intent: Intent?) {
if (intent == null) return
intent.removeExtra(FlutterCallkitIncomingPlugin.EXTRA_CALLKIT_CALL_DATA)
intent.action = null
}
}

View File

@@ -0,0 +1,42 @@
package com.eatvioapp.app
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.hiennv.flutter_callkit_incoming.AppUtils
import com.hiennv.flutter_callkit_incoming.CallkitIncomingBroadcastReceiver
object CallKitIntentBridge {
fun dispatchCallKitAction(context: Context, action: String, data: Bundle?) {
if (IncomingCallRingtonePolicy.actionStopsRingtone(action)) {
VideoCallPushBridge.silenceIncomingCall(context)
}
if (data != null) {
CallKitAcceptIntentMapper.payloadFromBundle(data, action)?.let { payload ->
PendingCallKitAcceptBridge.store(payload)
}
}
val broadcastIntent = CallkitIncomingBroadcastReceiver.getIntent(context, action, data)
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
context.sendBroadcast(broadcastIntent)
val shouldLaunchMainActivity =
action == com.hiennv.flutter_callkit_incoming.CallkitConstants.ACTION_CALL_ACCEPT ||
action == com.hiennv.flutter_callkit_incoming.CallkitConstants.ACTION_CALL_CALLBACK ||
!MainActivity.isInForeground
if (!shouldLaunchMainActivity) {
return
}
val activityIntent = AppUtils.getAppIntent(context, action, data) ?: return
activityIntent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_SINGLE_TOP or
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT,
)
context.startActivity(activityIntent)
}
}

View File

@@ -0,0 +1,329 @@
package com.eatvioapp.app
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.view.ViewGroup.MarginLayoutParams
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.hiennv.flutter_callkit_incoming.AppUtils
import com.hiennv.flutter_callkit_incoming.CallkitConstants
import com.hiennv.flutter_callkit_incoming.CallkitNotificationManager
import com.hiennv.flutter_callkit_incoming.ImageLoaderProvider
import com.hiennv.flutter_callkit_incoming.Utils
import com.hiennv.flutter_callkit_incoming.widgets.RippleRelativeLayout
import java.lang.ref.WeakReference
import kotlin.math.abs
import com.hiennv.flutter_callkit_incoming.R as CallkitR
/// Target of the incoming notification's content intent and full-screen intent.
///
/// Unlocked, lit screen: the user tapped the notification body, route it to the same
/// accept flow as the Answer button.
///
/// Locked or dark screen: Android fired the full-screen intent on its own, so show a
/// ringing screen that wakes the device and lets the user answer or decline.
class EatvioCallkitIncomingBridgeActivity : Activity() {
companion object {
private const val TAG = "EatvioIncomingBridge"
private const val WAKE_LOCK_TAG = "eatvio:incoming_call"
private const val DEFAULT_RING_DURATION_MS = 45_000L
private const val MIN_RING_SCREEN_MS = 1_000L
private val mainHandler = Handler(Looper.getMainLooper())
private var ringingScreen: WeakReference<EatvioCallkitIncomingBridgeActivity>? = null
/**
* Closes the ringing screen once the call stopped ringing: answered or declined
* from the notification, timed out, or ended by the caller.
*/
fun dismissRingingScreen() {
mainHandler.post {
ringingScreen?.get()?.closeRingingScreen()
ringingScreen = null
}
}
fun shouldShowRingingScreen(keyguardLocked: Boolean, screenInteractive: Boolean): Boolean {
return keyguardLocked || !screenInteractive
}
}
private var callData: Bundle? = null
private var wakeLock: PowerManager.WakeLock? = null
private var ringTimeout: Runnable? = null
private var actionTaken = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val data = intent.extras?.getBundle(CallkitConstants.EXTRA_CALLKIT_INCOMING_DATA)
if (data == null) {
finish()
return
}
callData = data
if (!launchedOnLockedOrDarkScreen()) {
Log.i(TAG, "tap on notification body: accept")
CallKitIntentBridge.dispatchCallKitAction(this, CallkitConstants.ACTION_CALL_ACCEPT, data)
finish()
@Suppress("DEPRECATION")
overridePendingTransition(0, 0)
return
}
Log.i(TAG, "full-screen intent on locked/dark screen: show ringing screen")
showRingingScreen(data)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
val data = intent.extras?.getBundle(CallkitConstants.EXTRA_CALLKIT_INCOMING_DATA) ?: return
if (ringingScreen?.get() !== this) return
callData = data
bindCallData(data)
scheduleRingTimeout(data)
}
override fun onDestroy() {
cancelRingTimeout()
releaseWakeLock()
if (ringingScreen?.get() === this) {
ringingScreen = null
}
super.onDestroy()
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
// The ringing screen is dismissed by Answer / Decline / timeout only.
}
private fun launchedOnLockedOrDarkScreen(): Boolean {
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
return shouldShowRingingScreen(
keyguardLocked = keyguardManager.isKeyguardLocked,
screenInteractive = powerManager.isInteractive,
)
}
private fun showRingingScreen(data: Bundle) {
ringingScreen = WeakReference(this)
setTheme(CallkitR.style.CallkitIncomingTheme)
requestedOrientation = if (Utils.isTablet(this)) {
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
} else {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setTurnScreenOn(true)
setShowWhenLocked(true)
} else {
@Suppress("DEPRECATION")
window.addFlags(
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = Color.TRANSPARENT
window.navigationBarColor = Color.TRANSPARENT
}
acquireWakeLock(ringDuration(data))
VideoCallPushBridge.keepRingingOnFullScreen()
setContentView(CallkitR.layout.activity_callkit_incoming)
bindCallData(data)
scheduleRingTimeout(data)
}
private fun bindCallData(data: Bundle) {
val background: ImageView = findViewById(CallkitR.id.ivBackground)
val ripple: RippleRelativeLayout = findViewById(CallkitR.id.llBackgroundAnimation)
val callerName: TextView = findViewById(CallkitR.id.tvNameCaller)
val callerNumber: TextView = findViewById(CallkitR.id.tvNumber)
val logo: ImageView = findViewById(CallkitR.id.ivLogo)
val avatar: ImageView = findViewById(CallkitR.id.ivAvatar)
val actions: LinearLayout = findViewById(CallkitR.id.llAction)
val acceptButton: ImageView = findViewById(CallkitR.id.ivAcceptCall)
val acceptLabel: TextView = findViewById(CallkitR.id.tvAccept)
val declineButton: ImageView = findViewById(CallkitR.id.ivDeclineCall)
val declineLabel: TextView = findViewById(CallkitR.id.tvDecline)
ripple.layoutParams.height = Utils.getScreenWidth() + Utils.getStatusBarHeight(this)
ripple.startRippleAnimation()
(actions.layoutParams as? MarginLayoutParams)?.let { params ->
params.setMargins(0, 0, 0, Utils.getNavigationBarHeight(this))
actions.layoutParams = params
}
callerName.text = data.getString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, "")
callerNumber.visibility = View.INVISIBLE
logo.visibility = View.INVISIBLE
val textColor = parseColor(data.getString(CallkitConstants.EXTRA_CALLKIT_TEXT_COLOR), Color.WHITE)
callerName.setTextColor(textColor)
acceptLabel.setTextColor(textColor)
declineLabel.setTextColor(textColor)
background.setBackgroundColor(
parseColor(data.getString(CallkitConstants.EXTRA_CALLKIT_BACKGROUND_COLOR), Color.parseColor("#0955fa")),
)
val avatarUrl = data.getString(CallkitConstants.EXTRA_CALLKIT_AVATAR, "")
if (!avatarUrl.isNullOrEmpty()) {
avatar.visibility = View.VISIBLE
@Suppress("DEPRECATION", "UNCHECKED_CAST")
val headers = data.getSerializable(CallkitConstants.EXTRA_CALLKIT_HEADERS) as? HashMap<String, Any?>
try {
ImageLoaderProvider.loadImage(this, avatarUrl, headers, CallkitR.drawable.ic_default_avatar, avatar)
} catch (error: Exception) {
Log.w(TAG, "failed to load caller avatar", error)
}
}
if (data.getInt(CallkitConstants.EXTRA_CALLKIT_TYPE, 0) > 0) {
acceptButton.setImageResource(CallkitR.drawable.ic_video)
}
acceptButton.background = AppUtils.createCircleDrawable(
parseColor(data.getString(CallkitConstants.EXTRA_CALLKIT_ACCEPT_COLOR), Color.parseColor("#4CAF50")),
)
declineButton.background = AppUtils.createCircleDrawable(
parseColor(data.getString(CallkitConstants.EXTRA_CALLKIT_DECLINE_COLOR), Color.parseColor("#F44336")),
)
val acceptText = data.getString(CallkitConstants.EXTRA_CALLKIT_TEXT_ACCEPT, "")
acceptLabel.text = if (acceptText.isNullOrEmpty()) getString(CallkitR.string.text_accept) else acceptText
val declineText = data.getString(CallkitConstants.EXTRA_CALLKIT_TEXT_DECLINE, "")
declineLabel.text = if (declineText.isNullOrEmpty()) getString(CallkitR.string.text_decline) else declineText
acceptButton.setOnClickListener { onAcceptClick() }
declineButton.setOnClickListener { onDeclineClick() }
}
private fun onAcceptClick() {
val data = callData ?: return
if (actionTaken) return
actionTaken = true
cancelRingTimeout()
Log.i(TAG, "ringing screen: accept")
// Same order as the plugin's own incoming activity: dispatch the accept, then ask
// the keyguard to unlock so MainActivity (which cannot show over the keyguard)
// becomes visible as soon as the user unlocks.
CallKitIntentBridge.dispatchCallKitAction(this, CallkitConstants.ACTION_CALL_ACCEPT, data)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardLocked) {
keyguardManager.requestDismissKeyguard(this, null)
}
}
finishRingingTask()
}
private fun onDeclineClick() {
val data = callData ?: return
if (actionTaken) return
actionTaken = true
cancelRingTimeout()
Log.i(TAG, "ringing screen: decline")
CallKitIntentBridge.dispatchCallKitAction(this, CallkitConstants.ACTION_CALL_DECLINE, data)
finishRingingTask()
}
private fun closeRingingScreen() {
if (isFinishing) return
cancelRingTimeout()
finishRingingTask()
}
private fun finishRingingTask() {
if (isFinishing) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask()
} else {
finish()
}
}
private fun ringDuration(data: Bundle): Long {
val duration = data.getLong(CallkitConstants.EXTRA_CALLKIT_DURATION, DEFAULT_RING_DURATION_MS)
return if (duration > 0L) duration else DEFAULT_RING_DURATION_MS
}
/**
* The notification was posted before this screen appeared, so ring only for the
* remaining part of the call duration.
*/
private fun scheduleRingTimeout(data: Bundle) {
cancelRingTimeout()
val now = System.currentTimeMillis()
val startedAt = data.getLong(CallkitNotificationManager.EXTRA_TIME_START_CALL, now)
val remaining = (ringDuration(data) - abs(now - startedAt)).coerceAtLeast(MIN_RING_SCREEN_MS)
val timeout = Runnable {
Log.i(TAG, "ringing screen: timed out")
closeRingingScreen()
}
ringTimeout = timeout
mainHandler.postDelayed(timeout, remaining)
}
private fun cancelRingTimeout() {
ringTimeout?.let { mainHandler.removeCallbacks(it) }
ringTimeout = null
}
@Suppress("DEPRECATION")
private fun acquireWakeLock(durationMs: Long) {
try {
val powerManager = applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager
val lock = powerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE,
WAKE_LOCK_TAG,
)
lock.acquire(durationMs)
wakeLock = lock
} catch (error: Exception) {
Log.w(TAG, "failed to acquire wake lock", error)
}
}
private fun releaseWakeLock() {
val lock = wakeLock ?: return
wakeLock = null
try {
if (lock.isHeld) lock.release()
} catch (error: Exception) {
Log.w(TAG, "failed to release wake lock", error)
}
}
private fun parseColor(value: String?, fallback: Int): Int {
if (value.isNullOrBlank()) return fallback
return try {
Color.parseColor(value)
} catch (error: IllegalArgumentException) {
fallback
}
}
}

View File

@@ -0,0 +1,25 @@
package com.eatvioapp.app
import android.app.Activity
import android.os.Bundle
/// Replaces plugin TransparentActivity: forwards CallKit actions without relaunching
/// MainActivity when the Flutter app is already in the foreground.
class EatvioCallkitTransparentBridgeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val action = intent.action
if (action.isNullOrBlank()) {
finish()
return
}
val data = intent.getBundleExtra("data")
CallKitIntentBridge.dispatchCallKitAction(this, action, data)
finish()
@Suppress("DEPRECATION")
overridePendingTransition(0, 0)
}
}

View File

@@ -0,0 +1,36 @@
package com.eatvioapp.app
import android.util.Log
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import io.flutter.plugins.firebase.messaging.FlutterFirebaseTokenLiveData
class EatvioFcmMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
FlutterFirebaseTokenLiveData.getInstance().postToken(token)
Log.i(TAG, "onNewToken")
}
override fun onMessageReceived(message: RemoteMessage) {
Log.i(TAG, "onMessageReceived: ${message.data}")
if (VideoCallPushBridge.isEndedVideoCall(message.data)) {
VideoCallPushBridge.dismissAllIncomingCalls(this)
return
}
if (!VideoCallPushBridge.isIncomingVideoCall(message.data)) {
return
}
// Data-only call pushes are delivered only to this service.
// FlutterFirebaseMessagingService is removed, so the Dart listener does
// not see them. Show the incoming UI here for both foreground and background.
VideoCallPushBridge.showIncomingCall(this, message.data)
}
companion object {
private const val TAG = "EatvioFCM"
}
}

View File

@@ -0,0 +1,66 @@
package com.eatvioapp.app
import android.app.PendingIntent
import android.content.Intent
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
class HmsPushService : HmsMessageService() {
override fun onNewToken(token: String?) {
super.onNewToken(token)
Log.i("HMS", "onNewToken: ${token ?: "null"}")
}
override fun onMessageReceived(message: RemoteMessage?) {
super.onMessageReceived(message)
Log.i("HMS", "onMessageReceived: ${message?.data}")
if (message == null) return
if (VideoCallPushBridge.isEndedVideoCall(message.dataOfMap)) {
VideoCallPushBridge.dismissAllIncomingCalls(this)
return
}
if (VideoCallPushBridge.isIncomingVideoCall(message.dataOfMap)) {
VideoCallPushBridge.showIncomingCall(this, message.dataOfMap)
return
}
val actionUrl = message.dataOfMap["action_url"]
showNotification(message, actionUrl)
}
private fun showNotification(message: RemoteMessage, actionUrl: String?) {
val context = applicationContext
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
if (!actionUrl.isNullOrBlank()) {
putExtra("action_url", actionUrl)
}
}
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
val channelId = "hms_push_channel"
val notification = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(message.notification?.title ?: context.getString(R.string.app_name))
.setContentText(message.notification?.body ?: "")
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()
NotificationManagerCompat.from(context).notify(message.messageId.hashCode(), notification)
}
}

View File

@@ -0,0 +1,15 @@
package com.eatvioapp.app
/**
* Call actions that must stop the incoming ringtone.
* Accept is included: answering the call is not the same as ending it,
* but the ringing player is a separate object from the in-call audio.
*/
internal object IncomingCallRingtonePolicy {
fun actionStopsRingtone(action: String): Boolean {
return action.contains("ACTION_CALL_ACCEPT") ||
action.contains("ACTION_CALL_DECLINE") ||
action.contains("ACTION_CALL_ENDED") ||
action.contains("ACTION_CALL_TIMEOUT")
}
}

View File

@@ -1,6 +1,281 @@
package com.eatvioapp.app
import android.app.PictureInPictureParams
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Rational
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import com.hiennv.flutter_callkit_incoming.FlutterCallkitIncomingPlugin
import com.huawei.agconnect.config.AGConnectServicesConfig
import com.huawei.hms.aaid.HmsInstanceId
import com.huawei.hms.api.ConnectionResult
import com.huawei.hms.api.HuaweiApiAvailability
import com.huawei.hms.common.ApiException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainActivity: FlutterActivity() {
companion object {
@JvmStatic
var isInForeground: Boolean = false
private set
}
private val channelName = "com.eatvioapp/hms_push"
private val videoCallPipChannelName = "com.eatvioapp/video_call_pip"
private val videoCallPushChannelName = "com.eatvioapp/video_call_push"
private var methodChannel: MethodChannel? = null
private var videoCallPipChannel: MethodChannel? = null
private var videoCallPushChannel: MethodChannel? = null
private var videoCallPipEnabled: Boolean = false
override fun onResume() {
super.onResume()
isInForeground = true
captureCallKitLaunchIntent(intent)
if (PendingCallKitAcceptBridge.peek() != null) {
scheduleDeliverPendingCallKitAccept()
}
}
override fun onPause() {
isInForeground = false
super.onPause()
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName)
videoCallPipChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, videoCallPipChannelName)
videoCallPushChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, videoCallPushChannelName)
videoCallPushChannel?.setMethodCallHandler { call, result ->
when (call.method) {
"dismissIncomingCalls" -> {
try {
VideoCallPushBridge.dismissAllIncomingCalls(applicationContext)
result.success(null)
} catch (e: Exception) {
result.error("DISMISS_INCOMING_CALLS_FAILED", e.message, null)
}
}
"showIncomingCall" -> {
try {
val args = call.arguments as? Map<*, *> ?: emptyMap<Any, Any>()
val data = HashMap<String, String>()
for ((key, value) in args) {
val name = key as? String ?: continue
if (value == null) continue
data[name] = value.toString()
}
VideoCallPushBridge.showIncomingCall(applicationContext, data)
result.success(null)
} catch (e: Exception) {
result.error("SHOW_INCOMING_CALL_FAILED", e.message, null)
}
}
"drainPendingCallKitAccept" -> {
result.success(PendingCallKitAcceptBridge.drain())
}
"peekPendingCallKitAccept" -> {
result.success(PendingCallKitAcceptBridge.peekPending())
}
else -> result.notImplemented()
}
}
videoCallPipChannel?.setMethodCallHandler { call, result ->
when (call.method) {
"setPipEnabled" -> {
videoCallPipEnabled = call.arguments as? Boolean ?: false
result.success(null)
}
else -> result.notImplemented()
}
}
methodChannel?.setMethodCallHandler { call, result ->
when (call.method) {
"isHmsAvailable" -> {
CoroutineScope(Dispatchers.IO).launch {
val available = try {
HuaweiApiAvailability.getInstance()
.isHuaweiMobileServicesAvailable(applicationContext) == ConnectionResult.SUCCESS
} catch (e: Exception) {
android.util.Log.w("HMS", "HMS availability check failed: ${e.message}")
false
}
runOnUiThread {
result.success(available)
}
}
}
"getHuaweiToken" -> {
CoroutineScope(Dispatchers.IO).launch {
try {
// Try to read appId from agconnect-services.json
var appId: String? = try {
AGConnectServicesConfig.fromContext(applicationContext)
.getString("client/app_id")
} catch (_: Exception) {
null
}
// Fallback to manifest meta-data if needed
if (appId.isNullOrBlank()) {
try {
val pm: PackageManager = applicationContext.packageManager
val ai: ApplicationInfo = pm.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
val raw = ai.metaData?.getString("com.huawei.hms.client.appid")
if (!raw.isNullOrBlank()) {
appId = raw.removePrefix("appid=")
}
} catch (_: Exception) {
// ignore and handle below
}
}
if (appId.isNullOrBlank()) {
android.util.Log.e("HMS", "Missing Huawei appId. Ensure agconnect-services.json or manifest meta-data is configured.")
runOnUiThread {
result.error("HMS_TOKEN_ERROR", "Missing Huawei appId. Ensure agconnect-services.json or manifest meta-data is configured.", null)
}
return@launch
}
android.util.Log.i("HMS", "Getting token for appId: $appId")
val token = HmsInstanceId.getInstance(applicationContext)
.getToken(appId, "HCM")
android.util.Log.i("HMS", "Token retrieved successfully")
runOnUiThread {
result.success(token)
}
} catch (e: ApiException) {
if (e.statusCode == 907135003) {
android.util.Log.w("HMS", "HMS client API invalid (${e.statusCode}), falling back to FCM")
runOnUiThread {
result.success(null)
}
} else {
android.util.Log.e("HMS", "Error getting HMS token: ${e.statusCode}: ${e.message}", e)
runOnUiThread {
result.error("HMS_TOKEN_ERROR", "${e.statusCode}: ${e.message}", null)
}
}
} catch (e: Exception) {
val message = e.message.orEmpty()
if (message.contains("907135003") || message.contains("client api invalid", ignoreCase = true)) {
android.util.Log.w("HMS", "HMS client API invalid, falling back to FCM")
runOnUiThread {
result.success(null)
}
} else {
android.util.Log.e("HMS", "Error getting HMS token: $message", e)
runOnUiThread {
result.error("HMS_TOKEN_ERROR", e.message, null)
}
}
}
}
}
else -> result.notImplemented()
}
}
// Обрабатываем возможный action_url, с которым была открыта Activity (например, из HMS уведомления).
handleIntentForActionUrl(intent)
captureCallKitLaunchIntent(intent)
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
enterVideoCallPictureInPictureIfNeeded()
videoCallPipChannel?.invokeMethod("onUserLeaveHint", null)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
captureCallKitLaunchIntent(intent)
// Обработка нового интента, когда Activity уже запущена (тап по уведомлению).
handleIntentForActionUrl(intent)
}
private fun captureCallKitLaunchIntent(intent: Intent?) {
val payload = CallKitAcceptIntentMapper.payloadFromIntent(intent) ?: return
android.util.Log.i(
"VideoCallPush",
"captureCallKitLaunchIntent: action=${payload["action"]} id=${payload["id"]}",
)
PendingCallKitAcceptBridge.store(payload)
CallKitAcceptIntentMapper.clearCallKitLaunchIntent(intent)
scheduleDeliverPendingCallKitAccept()
}
private fun scheduleDeliverPendingCallKitAccept() {
PendingCallKitAcceptBridge.scheduleDeliverToFlutter(
deliver = { deliverPendingCallKitAcceptToFlutter() },
)
}
private fun deliverPendingCallKitAcceptToFlutter() {
val payload = PendingCallKitAcceptBridge.peek() ?: return
val channel = videoCallPushChannel
if (channel == null) {
android.util.Log.w(
"VideoCallPush",
"deliverPendingCallKitAcceptToFlutter: channel not ready",
)
return
}
android.util.Log.i(
"VideoCallPush",
"deliverPendingCallKitAcceptToFlutter: id=${payload["id"]}",
)
channel.invokeMethod("onCallKitLaunchIntent", payload)
}
private fun handleIntentForActionUrl(intent: Intent?) {
if (intent == null) return
if (intent.hasExtra(FlutterCallkitIncomingPlugin.EXTRA_CALLKIT_CALL_DATA)) {
return
}
// Вариант 1: action_url лежит в extras.
val fromExtras = intent.extras?.getString("action_url")
// Вариант 2: action_url передан как data Uri.
val dataUri = intent.data
val fromData = dataUri?.toString()
val actionUrl = fromExtras ?: fromData
if (actionUrl.isNullOrBlank()) return
android.util.Log.i("HMS", "MainActivity.handleIntentForActionUrl: $actionUrl")
// Проксируем URL во Flutter, где уже есть общая логика навигации по диплинкам.
methodChannel?.invokeMethod("openActionUrl", actionUrl)
}
private fun enterVideoCallPictureInPictureIfNeeded() {
if (!videoCallPipEnabled) return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
if (isInPictureInPictureMode) return
try {
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(2, 3))
.build()
enterPictureInPictureMode(params)
} catch (e: Exception) {
android.util.Log.w("VideoCallPiP", "Unable to enter PiP from onUserLeaveHint", e)
}
}
}

View File

@@ -0,0 +1,42 @@
package com.eatvioapp.app
import android.os.Handler
import android.os.Looper
import android.util.Log
/// Stores accepted call payloads until the Flutter engine is ready to drain them.
object PendingCallKitAcceptBridge {
private const val TAG = "PendingCallKitAccept"
@Volatile
private var pendingPayload: Map<String, Any?>? = null
private val mainHandler = Handler(Looper.getMainLooper())
fun store(payload: Map<String, Any?>) {
pendingPayload = payload
Log.i(TAG, "stored pending accept id=${payload["id"]}")
}
fun peek(): Map<String, Any?>? = pendingPayload
fun drain(): Map<String, Any?>? {
val payload = pendingPayload
pendingPayload = null
if (payload != null) {
Log.i(TAG, "drained pending accept id=${payload["id"]}")
}
return payload
}
fun peekPending(): Map<String, Any?>? = pendingPayload
fun scheduleDeliverToFlutter(
deliver: () -> Unit,
delaysMs: LongArray = longArrayOf(0L, 250L, 700L, 1500L, 2800L, 4200L, 6000L),
) {
for (delayMs in delaysMs) {
mainHandler.postDelayed({ deliver() }, delayMs)
}
}
}

View File

@@ -0,0 +1,499 @@
package com.eatvioapp.app
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.hiennv.flutter_callkit_incoming.CallkitConstants
import com.hiennv.flutter_callkit_incoming.CallkitEventCallback
import com.hiennv.flutter_callkit_incoming.CallkitNotificationManager
import com.hiennv.flutter_callkit_incoming.CallkitNotificationService
import com.hiennv.flutter_callkit_incoming.CallkitSoundPlayerManager
import com.hiennv.flutter_callkit_incoming.Data
import com.hiennv.flutter_callkit_incoming.FlutterCallkitIncomingPlugin
import com.hiennv.flutter_callkit_incoming.addCall
import com.hiennv.flutter_callkit_incoming.getDataActiveCalls
import com.hiennv.flutter_callkit_incoming.removeAllCalls
import java.util.HashMap
import java.util.concurrent.atomic.AtomicInteger
object VideoCallPushBridge {
private const val TAG = "VideoCallPushBridge"
private const val ANDROID_ACCENT_COLOR = "#2787F5"
private const val MISSED_CALL_CLEANUP_DELAY_MS = 250L
private const val WAKE_LOCK_TAG = "eatvio:incoming_call_ring"
private val mainHandler = Handler(Looper.getMainLooper())
private val playbackLock = Any()
private val playbackGeneration = AtomicInteger(0)
private var activeSoundManager: CallkitSoundPlayerManager? = null
private var activeNotificationManager: CallkitNotificationManager? = null
private var activeCallBundle: Bundle? = null
private var storedAppContext: Context? = null
private var ringtoneTimeout: Runnable? = null
private var ringWakeLock: PowerManager.WakeLock? = null
private var callbackRegistered = false
/**
* The plugin stops only the sound player owned by [FlutterCallkitIncomingPlugin].
* Incoming pushes start a different player, so accept/decline never reached it
* and the ringtone kept looping until the process died.
*/
private val incomingCallEventCallback = object : CallkitEventCallback {
override fun onCallEvent(event: CallkitEventCallback.CallEvent, callData: Bundle) {
val context = storedAppContext ?: return
Log.i(TAG, "incoming call event=$event, stopping ringtone")
silenceIncomingCall(context)
}
}
fun isIncomingVideoCall(data: Map<String, String>): Boolean {
val rawType = data["type"]
?: data["notification_type"]
?: data["event"]
?: data["action"]
?: data["push_type"]
?: data["call_type"]
if (rawType != null) {
val normalized = rawType.lowercase().replace("-", "_")
if (normalized.contains("video_call")) {
return !normalized.contains("end") && !normalized.contains("ended")
}
if (normalized == "incoming_call" ||
normalized == "video_call_incoming" ||
normalized == "incoming_video_call"
) {
return true
}
}
if (isTruthy(data["is_video_call"]) ||
isTruthy(data["incoming_call"]) ||
isTruthy(data["is_incoming_call"])
) {
return conversationUuid(data) != null
}
val actionUrl = data["action_url"]
if (!actionUrl.isNullOrBlank() &&
(actionUrl.contains("video-call") || actionUrl.contains("videoCall"))
) {
return true
}
return false
}
fun isEndedVideoCall(data: Map<String, String>): Boolean {
val rawType = data["type"]
?: data["notification_type"]
?: data["event"]
?: data["action"]
?: data["push_type"]
?: data["call_type"]
if (rawType != null) {
val normalized = rawType.lowercase().replace("-", "_")
if (normalized == "video_call_ended" || normalized == "video_call_end") {
return true
}
if (normalized.contains("video_call") &&
(normalized.contains("ended") || normalized.endsWith("_end"))
) {
return true
}
}
return false
}
fun showIncomingCall(context: Context, data: Map<String, String>) {
val appContext = context.applicationContext
storedAppContext = appContext
ensureIncomingCallCallbackRegistered()
val callData = buildCallDataBundle(data)
if (callData == null) {
Log.w(TAG, "showIncomingCall: missing conversation uuid, data=$data")
return
}
val callId = callData.getString(CallkitConstants.EXTRA_CALLKIT_ID)
val seenGeneration = playbackGeneration.get()
Log.i(TAG, "showIncomingCall: conversation=$callId")
// Ringtone.play() and stop() must run on the same thread. FCM delivers
// pushes on a background thread, while Answer runs on the main thread.
// A second show for the same conversation must not bump the generation:
// that would cancel the timeout of the call that is already ringing.
mainHandler.post {
synchronized(playbackLock) {
if (seenGeneration != playbackGeneration.get()) {
Log.i(TAG, "showIncomingCall: skipped after silence")
return@post
}
val alreadyRinging = activeCallBundle?.getString(CallkitConstants.EXTRA_CALLKIT_ID)
if (!callId.isNullOrBlank() && callId == alreadyRinging) {
Log.i(TAG, "showIncomingCall: already ringing $callId")
return@post
}
val generation = playbackGeneration.incrementAndGet()
startIncomingCallLocked(appContext, callData, generation)
}
}
}
/**
* Stops the ringtone that [showIncomingCall] started and removes the incoming
* notification. Safe to call more than once.
*/
fun silenceIncomingCall(context: Context) {
val appContext = context.applicationContext
storedAppContext = appContext
Log.i(TAG, "silenceIncomingCall")
playbackGeneration.incrementAndGet()
val stop = Runnable {
synchronized(playbackLock) {
stopPlaybackLocked(appContext)
}
}
if (Looper.myLooper() == Looper.getMainLooper()) {
stop.run()
} else {
mainHandler.post(stop)
}
}
/**
* The plugin's sound player stops on ACTION_SCREEN_OFF. The ringing screen turns
* the display on itself, so keep ringing through that transition.
*/
fun keepRingingOnFullScreen() {
synchronized(playbackLock) {
activeSoundManager?.keepRingingOnFullScreen()
}
}
fun dismissAllIncomingCalls(context: Context) {
val appContext = context.applicationContext
val calls = getDataActiveCalls(appContext)
Log.i(TAG, "dismissAllIncomingCalls: active calls=${calls.size}")
playbackGeneration.incrementAndGet()
val dismiss = Runnable {
synchronized(playbackLock) {
val notificationManager = resolveNotificationManager(appContext)
val bundles = calls.map { it.toBundle() }
stopPlaybackLocked(appContext)
for (bundle in bundles) {
try {
dismissIncomingCallNotification(appContext, notificationManager, bundle)
} catch (error: Exception) {
Log.w(
TAG,
"dismissAllIncomingCalls: failed for call ${bundle.getString(CallkitConstants.EXTRA_CALLKIT_ID)}",
error,
)
}
}
try {
CallkitNotificationService.stopService(appContext)
} catch (error: Exception) {
Log.w(TAG, "dismissAllIncomingCalls: failed to stop callkit service", error)
}
try {
removeAllCalls(appContext)
} catch (error: Exception) {
Log.w(TAG, "dismissAllIncomingCalls: failed to remove persisted calls", error)
}
stopIncomingRingtone()
scheduleMissedCallCleanup(notificationManager, bundles)
}
}
if (Looper.myLooper() == Looper.getMainLooper()) {
dismiss.run()
} else {
mainHandler.post(dismiss)
}
}
private fun ensureIncomingCallCallbackRegistered() {
if (callbackRegistered) return
FlutterCallkitIncomingPlugin.registerEventCallback(incomingCallEventCallback)
callbackRegistered = true
}
private fun startIncomingCallLocked(appContext: Context, callData: Bundle, generation: Int) {
stopPlaybackLocked(appContext)
val soundManager = CallkitSoundPlayerManager(appContext)
val notificationManager = CallkitNotificationManager(appContext, soundManager)
activeSoundManager = soundManager
activeNotificationManager = notificationManager
activeCallBundle = callData
notificationManager.createNotificationChanel(callData)
notificationManager.showIncomingNotification(callData)
try {
addCall(appContext, Data.fromBundle(callData))
} catch (error: Exception) {
Log.w(TAG, "showIncomingCall: failed to persist active call", error)
}
val durationMs = callData.getLong(CallkitConstants.EXTRA_CALLKIT_DURATION, 45_000L)
wakeScreenLocked(appContext, if (durationMs > 0L) durationMs else 45_000L)
if (durationMs > 0L) {
val timeout = Runnable {
synchronized(playbackLock) {
if (generation != playbackGeneration.get()) return@Runnable
Log.i(TAG, "incoming ringtone timed out")
stopPlaybackLocked(appContext)
}
}
ringtoneTimeout = timeout
mainHandler.postDelayed(timeout, durationMs)
}
}
/**
* Turns the screen on while the call rings. The full-screen intent of the
* notification does the same only when the system grants it; the wake lock
* works without any grant, so the lock screen with the call card lights up.
*/
@Suppress("DEPRECATION")
private fun wakeScreenLocked(appContext: Context, durationMs: Long) {
releaseScreenWakeLockLocked()
try {
val powerManager = appContext.getSystemService(Context.POWER_SERVICE) as PowerManager
val lock = powerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE,
WAKE_LOCK_TAG,
)
lock.acquire(durationMs)
ringWakeLock = lock
Log.i(TAG, "wakeScreen: screen on for ${durationMs}ms, interactive=${powerManager.isInteractive}")
} catch (error: Exception) {
Log.w(TAG, "wakeScreen: failed to acquire wake lock", error)
}
}
private fun releaseScreenWakeLockLocked() {
val lock = ringWakeLock ?: return
ringWakeLock = null
try {
if (lock.isHeld) lock.release()
} catch (error: Exception) {
Log.w(TAG, "wakeScreen: failed to release wake lock", error)
}
}
private fun stopPlaybackLocked(appContext: Context) {
cancelRingtoneTimeoutLocked()
releaseScreenWakeLockLocked()
val notificationManager = activeNotificationManager
val bundle = activeCallBundle
stopIncomingRingtone()
if (notificationManager != null && bundle != null) {
try {
dismissIncomingCallNotification(appContext, notificationManager, bundle)
} catch (error: Exception) {
Log.w(TAG, "stopPlayback: failed to dismiss incoming notification", error)
}
}
activeSoundManager = null
activeNotificationManager = null
activeCallBundle = null
EatvioCallkitIncomingBridgeActivity.dismissRingingScreen()
}
private fun cancelRingtoneTimeoutLocked() {
ringtoneTimeout?.let { mainHandler.removeCallbacks(it) }
ringtoneTimeout = null
}
private fun resolveNotificationManager(context: Context): CallkitNotificationManager {
activeNotificationManager?.let { return it }
FlutterCallkitIncomingPlugin.getInstance()
?.getCallkitNotificationManager()
?.let { return it }
val soundManager = CallkitSoundPlayerManager(context)
return CallkitNotificationManager(context, soundManager)
}
private fun stopIncomingRingtone() {
try {
activeSoundManager?.stop()
} catch (error: Exception) {
Log.w(TAG, "stopIncomingRingtone: active player", error)
}
try {
FlutterCallkitIncomingPlugin.getInstance()
?.getCallkitSoundPlayerManager()
?.stop()
} catch (error: Exception) {
Log.w(TAG, "stopIncomingRingtone: plugin player", error)
}
}
/**
* Replaces the incoming notification before cancel so Android does not fire the
* timeout delete intent (which would show a missed-call notification).
*/
private fun dismissIncomingCallNotification(
context: Context,
notificationManager: CallkitNotificationManager,
bundle: Bundle,
) {
val notificationId = incomingNotificationId(bundle)
val silentNotification = NotificationCompat.Builder(
context,
CallkitNotificationManager.NOTIFICATION_CHANNEL_ID_INCOMING,
)
.setSmallIcon(context.applicationInfo.icon)
.setContentTitle("")
.setSilent(true)
.setOngoing(false)
.setPriority(NotificationCompat.PRIORITY_MIN)
.build()
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.notify(notificationId, silentNotification)
notificationManagerCompat.cancel(notificationId)
bundle.putBoolean(CallkitConstants.EXTRA_CALLKIT_MISSED_CALL_SHOW, false)
notificationManager.clearIncomingNotification(bundle, isAccepted = true)
notificationManager.clearMissCallNotification(bundle)
}
private fun scheduleMissedCallCleanup(
notificationManager: CallkitNotificationManager,
bundles: List<Bundle>,
) {
if (bundles.isEmpty()) return
Handler(Looper.getMainLooper()).postDelayed({
for (bundle in bundles) {
try {
notificationManager.clearMissCallNotification(bundle)
} catch (error: Exception) {
Log.w(TAG, "dismissAllIncomingCalls: delayed missed-call cleanup failed", error)
}
}
}, MISSED_CALL_CLEANUP_DELAY_MS)
}
private fun incomingNotificationId(bundle: Bundle): Int {
return bundle.getString(CallkitConstants.EXTRA_CALLKIT_ID, "callkit_incoming").hashCode()
}
private fun buildCallDataBundle(data: Map<String, String>): Bundle? {
val conversationUuid = conversationUuid(data) ?: return null
val callerName = data["counterpartName"]
?: data["counterpart_name"]
?: data["caller_name"]
?: data["callerName"]
?: data["nameCaller"]
?: data["caller"]
?: "Итвио"
val avatarUrl = data["counterpartAvatarUrl"]
?: data["counterpart_avatar_url"]
?: data["avatar"]
?: data["avatarUrl"]
?: data["avatar_url"]
?: data["caller_avatar"]
?: ""
val localParticipantName = data["localParticipantName"]
?: data["local_participant_name"]
val counterpartIsConsultant = isTruthy(
data["counterpartIsConsultant"]
?: data["counterpart_is_consultant"]
?: data["is_consultant"]
?: data["isConsultant"]
)
val extra = HashMap<String, Any?>()
extra["conversationUuid"] = conversationUuid
extra["counterpartName"] = callerName
if (avatarUrl.isNotBlank()) {
extra["counterpartAvatarUrl"] = avatarUrl
}
if (!localParticipantName.isNullOrBlank()) {
extra["localParticipantName"] = localParticipantName
}
if (counterpartIsConsultant) {
extra["counterpartIsConsultant"] = true
}
return Bundle().apply {
putString(CallkitConstants.EXTRA_CALLKIT_ID, conversationUuid)
putString(CallkitConstants.EXTRA_CALLKIT_NAME_CALLER, callerName)
putString(CallkitConstants.EXTRA_CALLKIT_APP_NAME, "Итвио")
putString(CallkitConstants.EXTRA_CALLKIT_HANDLE, conversationUuid)
putString(CallkitConstants.EXTRA_CALLKIT_AVATAR, avatarUrl)
putInt(CallkitConstants.EXTRA_CALLKIT_TYPE, 1)
putLong(CallkitConstants.EXTRA_CALLKIT_DURATION, 45000L)
putString(CallkitConstants.EXTRA_CALLKIT_TEXT_ACCEPT, "Answer")
putString(CallkitConstants.EXTRA_CALLKIT_TEXT_DECLINE, "Decline")
putSerializable(CallkitConstants.EXTRA_CALLKIT_EXTRA, extra)
putSerializable(CallkitConstants.EXTRA_CALLKIT_HEADERS, HashMap<String, Any?>())
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_CUSTOM_NOTIFICATION, true)
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_CUSTOM_SMALL_EX_NOTIFICATION, false)
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_LOGO, false)
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_CALL_ID, false)
putString(CallkitConstants.EXTRA_CALLKIT_RINGTONE_PATH, "system_ringtone_default")
putString(CallkitConstants.EXTRA_CALLKIT_BACKGROUND_COLOR, ANDROID_ACCENT_COLOR)
putString(CallkitConstants.EXTRA_CALLKIT_ACTION_COLOR, ANDROID_ACCENT_COLOR)
putString(CallkitConstants.EXTRA_CALLKIT_TEXT_COLOR, "#ffffff")
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_SHOW_FULL_LOCKED_SCREEN, false)
putBoolean(CallkitConstants.EXTRA_CALLKIT_IS_FULL_SCREEN, false)
putBoolean(CallkitConstants.EXTRA_CALLKIT_CALLING_SHOW, false)
}
}
private fun conversationUuid(data: Map<String, String>): String? {
val fromData = data["conversationUuid"]
?: data["conversation_uuid"]
?: data["conversation_id"]
?: data["chat_uuid"]
?: data["uuid"]
if (!fromData.isNullOrBlank()) {
return fromData
}
val actionUrl = data["action_url"] ?: return null
val uuidFromQuery = Regex("""[?&](?:uuid|conversationUuid|conversation_uuid)=([^&]+)""")
.find(actionUrl)
?.groupValues
?.getOrNull(1)
?.trim()
if (!uuidFromQuery.isNullOrEmpty()) {
return uuidFromQuery
}
val pathMatch = Regex("""/video-call/([^/?#]+)""").find(actionUrl)
return pathMatch?.groupValues?.getOrNull(1)?.trim()?.takeIf { it.isNotEmpty() }
}
private fun isTruthy(value: String?): Boolean {
if (value.isNullOrBlank()) return false
return when (value.trim().lowercase()) {
"1", "true", "yes" -> true
else -> false
}
}
}

View File

@@ -0,0 +1,45 @@
package com.eatvioapp.app
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class IncomingCallRingtonePolicyTest {
@Test
fun answerDeclineEndAndTimeoutStopTheRingtone() {
assertTrue(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_ACCEPT",
),
)
assertTrue(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_DECLINE",
),
)
assertTrue(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_ENDED",
),
)
assertTrue(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_TIMEOUT",
),
)
}
@Test
fun incomingAndStartActionsKeepTheRingtonePlaying() {
assertFalse(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_INCOMING",
),
)
assertFalse(
IncomingCallRingtonePolicy.actionStopsRingtone(
"com.hiennv.flutter_callkit_incoming.ACTION_CALL_START",
),
)
}
}

View File

@@ -1,7 +1,21 @@
buildscript {
repositories {
google()
mavenCentral()
maven {url 'https://developer.huawei.com/repo/'}
gradlePluginPortal()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.12.0'
classpath 'com.huawei.agconnect:agcp:1.9.1.301'
}
}
allprojects {
repositories {
google()
mavenCentral()
maven {url 'https://developer.huawei.com/repo/'}
}
}
@@ -13,6 +27,32 @@ subprojects {
project.evaluationDependsOn(":app")
}
// Temporary safeguard: set missing namespaces for Android library modules based on their manifest package
subprojects { Project subproject ->
subproject.pluginManager.withPlugin('com.android.library') {
def androidExt = subproject.extensions.findByName('android')
if (androidExt != null) {
def hasNamespaceProp = androidExt.hasProperty('namespace')
def currentNamespace = hasNamespaceProp ? androidExt.namespace : null
if (hasNamespaceProp && !currentNamespace) {
def manifestFile = file("${subproject.projectDir}/src/main/AndroidManifest.xml")
if (manifestFile.exists()) {
try {
def manifest = new groovy.xml.XmlSlurper().parse(manifestFile)
def manifestPackage = manifest.@package?.text()
if (manifestPackage) {
androidExt.namespace = manifestPackage
subproject.logger.lifecycle("[namespace-fix] Set namespace for ${subproject.path} to '${manifestPackage}' from AndroidManifest.xml")
}
} catch (Throwable t) {
subproject.logger.warn("[namespace-fix] Failed to read manifest for ${subproject.path}: ${t.message}")
}
}
}
}
}
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

File diff suppressed because one or more lines are too long

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip

View File

@@ -12,17 +12,18 @@ pluginManagement {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.3" apply false
id "com.android.application" version "8.12.0" apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.4.2" apply false
id "com.google.gms.google-services" version "4.4.3" apply false
// END: FlutterFire Configuration
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
id "org.jetbrains.kotlin.android" version "2.2.10" apply false
}
include ":app"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
assets/icons/check.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="12" height="9" viewBox="0 0 12 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.16229 6.8625L10.5185 0.50625C10.6685 0.35625 10.8435 0.28125 11.0435 0.28125C11.2435 0.28125 11.4185 0.35625 11.5685 0.50625C11.7185 0.65625 11.7935 0.834375 11.7935 1.04063C11.7935 1.24688 11.7185 1.425 11.5685 1.575L4.68729 8.475C4.53729 8.625 4.36229 8.7 4.16229 8.7C3.96229 8.7 3.78729 8.625 3.63729 8.475L0.412289 5.25C0.262289 5.1 0.190414 4.92188 0.196664 4.71563C0.202914 4.50938 0.281039 4.33125 0.431039 4.18125C0.581039 4.03125 0.759164 3.95625 0.965414 3.95625C1.17166 3.95625 1.34979 4.03125 1.49979 4.18125L4.16229 6.8625Z" fill="#16A249"/>
</svg>

After

Width:  |  Height:  |  Size: 668 B

View File

@@ -0,0 +1,11 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.2" width="20" height="20" rx="6" fill="#16A249"/>
<g clip-path="url(#clip0_1823_10218)">
<path d="M8.16229 12.8625L14.5185 6.50625C14.6685 6.35625 14.8435 6.28125 15.0435 6.28125C15.2435 6.28125 15.4185 6.35625 15.5685 6.50625C15.7185 6.65625 15.7935 6.83438 15.7935 7.04063C15.7935 7.24688 15.7185 7.425 15.5685 7.575L8.68729 14.475C8.53729 14.625 8.36229 14.7 8.16229 14.7C7.96229 14.7 7.78729 14.625 7.63729 14.475L4.41229 11.25C4.26229 11.1 4.19041 10.9219 4.19666 10.7156C4.20291 10.5094 4.28104 10.3313 4.43104 10.1813C4.58104 10.0313 4.75916 9.95625 4.96541 9.95625C5.17166 9.95625 5.34979 10.0313 5.49979 10.1813L8.16229 12.8625Z" fill="#16A249"/>
</g>
<defs>
<clipPath id="clip0_1823_10218">
<rect width="12" height="9" fill="white" transform="translate(4 6)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 911 B

View File

@@ -0,0 +1,12 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1846_342)">
<path d="M5.33333 16C3.85185 16 2.59259 15.4815 1.55556 14.4444C0.518518 13.4074 0 12.1481 0 10.6667V5.33333C0 3.85185 0.518518 2.59259 1.55556 1.55556C2.59259 0.518518 3.85185 0 5.33333 0H10.6667C12.1481 0 13.4074 0.518518 14.4444 1.55556C15.4815 2.59259 16 3.85185 16 5.33333V10.6667C16 12.1481 15.4815 13.4074 14.4444 14.4444C13.4074 15.4815 12.1481 16 10.6667 16H5.33333ZM5.33333 14.2222H10.6667C11.6444 14.2222 12.4815 13.8741 13.1778 13.1778C13.8741 12.4815 14.2222 11.6444 14.2222 10.6667V5.33333C14.2222 4.35556 13.8741 3.51852 13.1778 2.82222C12.4815 2.12593 11.6444 1.77778 10.6667 1.77778H5.33333C4.35556 1.77778 3.51852 2.12593 2.82222 2.82222C2.12593 3.51852 1.77778 4.35556 1.77778 5.33333V10.6667C1.77778 11.6444 2.12593 12.4815 2.82222 13.1778C3.51852 13.8741 4.35556 14.2222 5.33333 14.2222Z" fill="#D22121"/>
<rect x="4.81836" y="10.9749" width="8" height="1" rx="0.5" transform="rotate(-45 4.81836 10.9749)" fill="#D22121"/>
<rect x="5.52539" y="5.31799" width="8" height="1" rx="0.5" transform="rotate(45 5.52539 5.31799)" fill="#D22121"/>
</g>
<defs>
<clipPath id="clip0_1846_342">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#2F80ED"><path d="M759.23-353.08q8.92-8.92 21.19-8.92 12.27 0 21.19 8.92l63.39 64q8.92 9.07 8.92 21.15 0 12.08-8.92 21.01-8.92 8.92-21.01 8.92-12.08 0-21.14-8.92l-64-63.39q-8.93-8.92-8.73-21.38.19-12.46 9.11-21.39Zm33.85-472.22q8.92 9 8.92 21.38 0 12.38-8.92 21.3l-63.39 63.39q-8.92 8.92-21.19 8.92-12.27 0-21.19-9-8.92-9.01-8.92-21.39t8.92-21.3l63.61-63.38q9.07-8.93 21.15-8.93 12.08 0 21.01 9.01ZM167-825q9.01-8.92 21.39-8.92t21.3 8.92l63.39 63.62q8.92 9.06 8.92 21.14 0 12.09-9 21.01-9.01 8.92-21.39 8.92t-21.3-8.92l-63.39-63.39q-8.92-8.92-8.92-21.19 0-12.27 9-21.19Zm33.77 472.31q8.92 8.92 8.92 21.19 0 12.27-8.92 21.19l-63.39 63.39q-8.92 8.92-21.19 8.92-12.27 0-21.19-9-8.92-9.01-8.92-21.39t8.92-21.3l63.62-63.39q8.92-8.92 21.07-8.73 12.16.2 21.08 9.12Zm135.54 86.85L480-352.23l144.08 87.77-37.62-163.62 126.39-109.07-166.39-14.93L480-706.54l-66.08 153.46-166.38 14.54 126.38 110.46-37.61 162.24ZM480.38-486ZM480-281.31 306.69-177.08q-8.69 5.08-17.42 4.27-8.73-.81-15.81-5.88-7.07-5.08-10.92-13.27-3.85-8.19-1.23-18.12L307.23-406 154.08-538.39q-7.69-6.83-9.62-15.57-1.92-8.73 1.31-17.04 3.23-8.31 9.28-13.62 6.05-5.32 16.64-6.84l201.7-17.39 78.46-185.3q3.84-9.31 11.65-13.77 7.81-4.46 16.5-4.46 8.69 0 16.5 4.46 7.81 4.46 11.65 13.77L587-608.85l201.69 17.39q10.68 1.51 16.78 6.82 6.1 5.3 9.14 13.64 3.24 8.31 1.31 17.04-1.92 8.74-9.61 15.57L653.15-406l45.93 196.31q2.61 9.92-1.23 17.92-3.85 8-10.93 13.08-7.07 5.07-15.8 5.88-8.73.81-17.43-4.27L480-281.31Z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,3 @@
<svg width="10" height="9" viewBox="0 0 10 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.53669 8.89177L6.8122 7.15382C6.52317 7.26749 6.22614 7.34957 5.92111 7.40005C5.61615 7.45053 5.3063 7.47578 4.99155 7.47578C3.95998 7.47578 3.01527 7.19683 2.15742 6.63893C1.29964 6.08096 0.619788 5.34562 0.117849 4.43293C0.0770142 4.36144 0.047164 4.28862 0.0282984 4.21447C0.00943278 4.14041 0 4.06506 0 3.98842C0 3.91178 0.0102087 3.8356 0.030626 3.75987C0.0510433 3.68423 0.0816693 3.61224 0.122504 3.5439C0.317857 3.21368 0.525501 2.89417 0.745437 2.58538C0.96529 2.2765 1.22096 2.00328 1.51243 1.76572L0.406101 0.633204C0.338315 0.564287 0.303606 0.478889 0.301972 0.377008C0.300421 0.275127 0.337662 0.185536 0.413696 0.108233C0.484667 0.0360776 0.570746 0 0.671934 0C0.773041 0 0.85908 0.0360776 0.93005 0.108233L9.05304 8.3668C9.12091 8.43579 9.15689 8.52119 9.16097 8.62299C9.16505 8.72487 9.12908 8.81446 9.05304 8.89177C8.98207 8.96392 8.89599 9 8.79481 9C8.6937 9 8.60766 8.96392 8.53669 8.89177ZM4.99155 6.01955C5.10025 6.01955 5.20405 6.01299 5.30295 5.99988C5.40194 5.98676 5.49855 5.95815 5.5928 5.91406L3.09751 3.37713C3.05725 3.47295 3.02989 3.57118 3.01544 3.67181C3.00098 3.77237 2.99375 3.8779 2.99375 3.98842C2.99375 4.5537 3.18772 5.03355 3.57565 5.42795C3.96358 5.82235 4.43554 6.01955 4.99155 6.01955ZM4.99155 0.501058C6.02622 0.501058 6.97529 0.781293 7.83878 1.34176C8.70227 1.90223 9.38344 2.64201 9.88227 3.56109C9.91992 3.62436 9.94896 3.69224 9.96937 3.76473C9.98979 3.83721 10 3.91178 10 3.98842C10 4.06506 9.99106 4.13962 9.97317 4.21211C9.95529 4.28459 9.92748 4.35247 9.88975 4.41574C9.74086 4.70378 9.57442 4.97521 9.39042 5.23004C9.20634 5.48487 9.00057 5.72471 8.77312 5.94956C8.67136 6.05302 8.55074 6.10059 8.41125 6.09229C8.27184 6.08399 8.15121 6.02811 8.04937 5.92465L7.0223 4.88517C6.97142 4.83344 6.93781 4.77369 6.92147 4.70594C6.90514 4.63827 6.90608 4.56769 6.92429 4.49421C6.94749 4.40868 6.96411 4.32565 6.97415 4.24511C6.98428 4.16465 6.98934 4.07909 6.98934 3.98842C6.98934 3.42313 6.79538 2.94329 6.40745 2.54888C6.01952 2.15448 5.54755 1.95728 4.99155 1.95728C4.90236 1.95728 4.81898 1.96322 4.74139 1.97509C4.66381 1.98688 4.58447 2.00461 4.50337 2.02827C4.43117 2.04994 4.35894 2.05248 4.28666 2.03587C4.21446 2.01926 4.15293 1.9851 4.10205 1.93337L3.64584 1.46967C3.50643 1.32785 3.46012 1.16274 3.50692 0.974343C3.55372 0.785942 3.67136 0.665878 3.85985 0.614149C4.04516 0.575788 4.23174 0.547349 4.41958 0.528832C4.60742 0.510316 4.79807 0.501058 4.99155 0.501058ZM5.94046 3.04758C6.03977 3.15876 6.1216 3.28347 6.18596 3.42172C6.25032 3.55997 6.29066 3.70449 6.30699 3.85527C6.31516 3.91531 6.29303 3.95699 6.2406 3.98032C6.18817 4.00357 6.139 3.9919 6.0931 3.94532L5.04153 2.88093C4.99563 2.83427 4.98542 2.78428 5.0109 2.73097C5.0363 2.67767 5.07852 2.65101 5.13757 2.65101C5.29593 2.66438 5.44199 2.70478 5.57577 2.7722C5.70962 2.83954 5.83119 2.93133 5.94046 3.04758Z" fill="#2F80ED"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

9
assets/icons/logo_2.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg width="89" height="90" viewBox="0 0 89 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M45.0119 0C65.9947 0 83 9.05026 83 29.6764C83 50.2792 65.9947 67 45.0119 67C24.0053 67 7 50.2792 7 29.6764C7 9.05026 24.0053 0 45.0119 0Z" fill="#43A6F2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.8844 43.5162C39.8585 43.5162 34.9274 42.5623 30.3282 40.7209C25.7291 38.8573 21.5803 36.1284 18.1428 32.7119C16.5544 31.1589 16.6493 28.6741 18.3087 27.2098C19.9919 25.7234 22.6234 25.8122 24.2118 27.3651C26.867 30.0052 30.0675 32.1129 33.6235 33.5327C37.1796 34.9748 40.9964 35.7069 44.8844 35.7069C48.7486 35.7069 52.5655 34.9748 56.1215 33.5327C59.6776 32.1129 62.878 30.0052 65.5332 27.3651C67.1216 25.8122 69.7531 25.7234 71.4363 27.2098C73.0958 28.6741 73.1906 31.1589 71.6022 32.7119C68.1647 36.1284 64.016 38.8573 59.4168 40.7209C54.8176 42.5623 49.8866 43.5162 44.8844 43.5162Z" fill="white"/>
<path d="M9.69721 80.8957L3.51318 88.877C2.93793 89.6257 2.28049 90 1.54087 90C0.513623 90 0 89.3382 0 88.0147V77.3663C0 75.7888 0.56841 75 1.70523 75C2.84205 75 3.41046 75.7888 3.41046 77.3663V84.2246L9.71775 76.0829C10.2793 75.361 10.882 75 11.5257 75C12.5803 75 13.1077 75.7487 13.1077 77.246V87.6337C13.1077 89.2112 12.5393 90 11.4024 90C10.2656 90 9.69721 89.2112 9.69721 87.6337V80.8957Z" fill="#323F4B"/>
<path d="M23.0017 78.2888C21.769 78.2888 21.0019 78.2553 20.7006 78.1885C19.7829 78.0013 19.3241 77.5201 19.3241 76.7447C19.3241 75.7019 20.1322 75.1805 21.7484 75.1805H27.6859C29.3021 75.1805 30.1102 75.7019 30.1102 76.7447C30.1102 77.5201 29.6514 78.0013 28.7337 78.1885C28.4324 78.2553 27.6654 78.2888 26.4327 78.2888V87.6337C26.4327 89.2112 25.8642 90 24.7274 90C23.5769 90 23.0017 89.2112 23.0017 87.6337V78.2888Z" fill="#323F4B"/>
<path d="M38.6564 89.8195C37.7935 89.8195 37.1909 89.6791 36.8485 89.3984C36.506 89.1043 36.3348 88.5428 36.3348 87.7139V77.5267C36.3348 76.6578 36.506 76.0495 36.8485 75.7019C37.1909 75.3543 37.8072 75.1805 38.6975 75.1805H41.4916C42.8476 75.1805 43.9981 75.4545 44.9432 76.0027C46.0937 76.6578 46.6689 77.6003 46.6689 78.8302C46.6689 80.4211 46.08 81.4973 44.9021 82.0588V82.119C45.7787 82.3864 46.4087 82.7807 46.7922 83.3021C47.1757 83.8102 47.3675 84.512 47.3675 85.4078C47.3675 86.8917 46.8401 88.0214 45.7855 88.7968C44.8541 89.4786 43.6009 89.8195 42.0258 89.8195H38.6564ZM39.7453 83.5027V86.9519H41.4505C42.1764 86.9519 42.7175 86.8583 43.0736 86.6711C43.5393 86.4171 43.7721 85.9626 43.7721 85.3075C43.7721 84.5455 43.5461 84.0374 43.0941 83.7834C42.7654 83.5963 42.197 83.5027 41.3889 83.5027H39.7453ZM39.7453 78.0281V80.8957H41.2245C41.8957 80.8957 42.3682 80.8155 42.6421 80.6551C43.0256 80.4412 43.2174 80.0401 43.2174 79.4519C43.2174 78.5027 42.5531 78.0281 41.2245 78.0281H39.7453Z" fill="#323F4B"/>
<path d="M64.1493 80.8957L57.9653 88.877C57.39 89.6257 56.7326 90 55.993 90C54.9657 90 54.4521 89.3382 54.4521 88.0147V77.3663C54.4521 75.7888 55.0205 75 56.1573 75C57.2941 75 57.8626 75.7888 57.8626 77.3663V84.2246L64.1698 76.0829C64.7314 75.361 65.3341 75 65.9778 75C67.0324 75 67.5598 75.7487 67.5598 77.246V87.6337C67.5598 89.2112 66.9913 90 65.8545 90C64.7177 90 64.1493 89.2112 64.1493 87.6337V80.8957Z" fill="#323F4B"/>
<path d="M74.6391 82.5201C74.6391 80.3275 75.2691 78.5428 76.5292 77.1658C77.8304 75.7219 79.5904 75 81.8093 75C84.0418 75 85.8087 75.7152 87.1099 77.1457C88.37 78.5227 89 80.3142 89 82.5201C89 84.7126 88.37 86.4973 87.1099 87.8743C85.795 89.2914 84.0281 90 81.8093 90C79.5904 90 77.8304 89.2848 76.5292 87.8543C75.2691 86.4906 74.6391 84.7126 74.6391 82.5201ZM78.255 82.5602C78.255 83.7634 78.5358 84.7594 79.0973 85.5481C79.7274 86.4706 80.6314 86.9318 81.8093 86.9318C82.9872 86.9318 83.898 86.4773 84.5417 85.5682C85.1033 84.766 85.3841 83.7634 85.3841 82.5602C85.3841 81.3168 85.117 80.2941 84.5828 79.492C83.9391 78.5428 83.0146 78.0682 81.8093 78.0682C80.604 78.0682 79.6863 78.5428 79.0563 79.492C78.5221 80.2941 78.255 81.3168 78.255 82.5602Z" fill="#323F4B"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,11 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1713_218)">
<path d="M7.48034 0.0116882H20.547C24.6707 0.0116882 28.0137 3.35463 28.0137 7.47836V20.545C28.0137 24.6687 24.6707 28.0117 20.547 28.0117H7.48034C3.35661 28.0117 0.0136719 24.6687 0.0136719 20.545V7.47836C0.0136717 3.35463 3.35661 0.0116882 7.48034 0.0116882Z" fill="#0077FF"/>
<path d="M14.0133 3.43393C19.8423 3.43393 24.5911 8.18276 24.5911 14.0117C24.5911 17.6432 22.8964 19.3565 20.7548 19.3565C19.5071 19.3565 18.4269 18.7047 17.8124 17.7363C16.844 18.7233 15.5031 19.3378 14.0133 19.3378C11.0709 19.3378 8.6872 16.9541 8.6872 14.0117C8.6872 11.0693 11.0709 8.68558 14.0133 8.68558C16.9557 8.68558 19.3395 11.0693 19.3395 14.0117V15.7436C19.3395 16.6189 19.954 17.2334 20.7548 17.2334C21.7046 17.2334 22.4867 16.4327 22.4867 14.0117C22.4867 9.33739 18.6876 5.53832 14.0133 5.53832C9.339 5.53832 5.53993 9.33739 5.53993 14.0117C5.53993 18.686 9.339 22.4851 14.0133 22.4851C16.7136 22.4851 18.5759 21.1443 18.5759 21.1443L19.9726 22.7458C19.9726 22.7458 17.5889 24.5895 14.0133 24.5895C8.18438 24.5895 3.43555 19.8407 3.43555 14.0117C3.43555 8.18276 8.18438 3.43393 14.0133 3.43393ZM10.7916 14.0117C10.7916 15.7809 12.2255 17.2334 14.0133 17.2334C15.7825 17.2334 17.2351 15.7809 17.2351 14.0117C17.2351 12.2239 15.7825 10.79 14.0133 10.79C12.2255 10.79 10.7916 12.2239 10.7916 14.0117Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_1713_218">
<rect width="28" height="28" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

5
assets/icons/ok_logo.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 13.4393C0 7.10718 0 3.92462 1.9623 1.96231C3.9411 1.57261e-07 7.10718 0 13.4393 0H14.5607C20.8928 0 24.0754 1.57261e-07 26.0377 1.96231C28 3.92462 28 7.10718 28 13.4393V14.5607C28 20.8928 28 24.0754 26.0377 26.0377C24.0754 28 20.8928 28 14.5607 28H13.4393C7.10718 28 3.92461 28 1.9623 26.0377C0 24.0754 0 20.9093 0 14.5607V13.4393Z" fill="#FF7700"/>
<path d="M13.9997 13.934C15.3684 13.934 16.6051 13.3734 17.4956 12.4829C18.3861 11.5925 18.9467 10.3557 18.9467 8.98704C18.9467 7.61837 18.3861 6.38162 17.4956 5.49116C16.6051 4.6007 15.3684 4.04004 13.9997 4.04004C12.631 4.04004 11.3943 4.6007 10.5039 5.49116C9.61339 6.38162 9.05273 7.61837 9.05273 8.98704C9.05273 10.3557 9.61339 11.5925 10.5039 12.4829C11.3943 13.3734 12.6475 13.934 13.9997 13.934ZM12.4167 7.38751C12.8289 6.97526 13.3896 6.72791 13.9997 6.72791C14.6263 6.72791 15.187 6.97526 15.5828 7.38751C15.995 7.79976 16.2424 8.36042 16.2424 8.97055C16.2424 9.59716 15.995 10.1578 15.5828 10.5536C15.1705 10.9658 14.6098 11.2132 13.9997 11.2132C13.3731 11.2132 12.8124 10.9658 12.4167 10.5536C12.0044 10.1413 11.7571 9.58067 11.7571 8.97055C11.7571 8.36042 12.0209 7.79976 12.4167 7.38751Z" fill="white"/>
<path d="M20.6615 15.9293L19.2104 13.9505C19.1279 13.8351 18.963 13.8186 18.8641 13.9175C17.4954 15.0883 15.8134 15.8469 13.9995 15.8469C12.1856 15.8469 10.5037 15.0883 9.13498 13.9175C9.03604 13.8351 8.87114 13.8516 8.78869 13.9505L7.33758 15.9293C7.27162 16.0283 7.28811 16.1602 7.37056 16.2426C8.59081 17.232 10.009 17.9081 11.4931 18.2544L8.42591 23.6631C8.34346 23.8115 8.45889 24.0094 8.62379 24.0094H11.625C11.7239 24.0094 11.8064 23.9599 11.8393 23.861L13.983 19.0789L16.1267 23.861C16.1597 23.9434 16.2422 24.0094 16.3411 24.0094H19.3423C19.5237 24.0094 19.6226 23.828 19.5402 23.6631L16.473 18.2544C17.9571 17.9081 19.3753 17.2485 20.5955 16.2426C20.7274 16.1602 20.7439 16.0283 20.6615 15.9293Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

3
assets/icons/resend.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.377 11L15.3193 6.94225C15.1641 6.78709 15.0865 6.60892 15.0865 6.40775C15.0865 6.20642 15.1641 6.02817 15.3193 5.873C15.4744 5.72817 15.6542 5.65734 15.8587 5.6605C16.0631 5.66384 16.2345 5.73467 16.373 5.873L20.8673 10.3673C20.9609 10.4609 21.0269 10.5597 21.0653 10.6635C21.1038 10.7673 21.123 10.8795 21.123 11C21.123 11.1205 21.1038 11.2327 21.0653 11.3365C21.0269 11.4403 20.9609 11.5391 20.8673 11.6328L16.373 16.127C16.2178 16.282 16.0422 16.357 15.8462 16.352C15.6501 16.3468 15.4744 16.2718 15.3193 16.127C15.1641 15.9718 15.0856 15.7946 15.0837 15.5953C15.0817 15.3959 15.1551 15.2218 15.3038 15.073L19.377 11ZM14.0693 11.75H7.25C6.3525 11.75 5.5865 12.0673 4.952 12.702C4.31733 13.3365 4 14.1025 4 15V17.75C4 17.9628 3.92817 18.141 3.7845 18.2845C3.641 18.4282 3.46283 18.5 3.25 18.5C3.03717 18.5 2.859 18.4282 2.7155 18.2845C2.57183 18.141 2.5 17.9628 2.5 17.75V15C2.5 13.6872 2.9635 12.5673 3.8905 11.6405C4.81733 10.7135 5.93717 10.25 7.25 10.25H14.0693L10.7615 6.94225C10.6065 6.78709 10.529 6.60892 10.529 6.40775C10.529 6.20642 10.6065 6.02817 10.7615 5.873C10.9167 5.72817 11.0965 5.65734 11.301 5.6605C11.5055 5.66384 11.677 5.73467 11.8155 5.873L16.3095 10.3673C16.4032 10.4609 16.4692 10.5597 16.5078 10.6635C16.5463 10.7673 16.5655 10.8795 16.5655 11C16.5655 11.1205 16.5463 11.2327 16.5078 11.3365C16.4692 11.4403 16.4032 11.5391 16.3095 11.6328L11.8155 16.127C11.6603 16.282 11.4847 16.357 11.2885 16.352C11.0923 16.3468 10.9167 16.2718 10.7615 16.127C10.6065 15.9718 10.528 15.7946 10.526 15.5953C10.524 15.3959 10.5974 15.2218 10.7463 15.073L14.0693 11.75Z" fill="#2F80ED"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

3
assets/icons/sucess.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.33333 16C3.85185 16 2.59259 15.4815 1.55556 14.4444C0.518519 13.4074 0 12.1481 0 10.6667V5.33333C0 3.85185 0.518519 2.59259 1.55556 1.55556C2.59259 0.518519 3.85185 0 5.33333 0H10.6667C12.1481 0 13.4074 0.518519 14.4444 1.55556C15.4815 2.59259 16 3.85185 16 5.33333V10.6667C16 12.1481 15.4815 13.4074 14.4444 14.4444C13.4074 15.4815 12.1481 16 10.6667 16H5.33333ZM7.11111 9.06667L5.77778 7.73333C5.61481 7.57037 5.40741 7.48889 5.15556 7.48889C4.9037 7.48889 4.6963 7.57037 4.53333 7.73333C4.37037 7.8963 4.28889 8.1037 4.28889 8.35556C4.28889 8.60741 4.37037 8.81481 4.53333 8.97778L6.48889 10.9333C6.66667 11.1111 6.87407 11.2 7.11111 11.2C7.34815 11.2 7.55556 11.1111 7.73333 10.9333L11.8222 6.84444C11.9852 6.68148 12.0667 6.47407 12.0667 6.22222C12.0667 5.97037 11.9852 5.76296 11.8222 5.6C11.6593 5.43704 11.4519 5.35556 11.2 5.35556C10.9481 5.35556 10.7407 5.43704 10.5778 5.6L7.11111 9.06667ZM5.33333 14.2222H10.6667C11.6444 14.2222 12.4815 13.8741 13.1778 13.1778C13.8741 12.4815 14.2222 11.6444 14.2222 10.6667V5.33333C14.2222 4.35556 13.8741 3.51852 13.1778 2.82222C12.4815 2.12593 11.6444 1.77778 10.6667 1.77778H5.33333C4.35556 1.77778 3.51852 2.12593 2.82222 2.82222C2.12593 3.51852 1.77778 4.35556 1.77778 5.33333V10.6667C1.77778 11.6444 2.12593 12.4815 2.82222 13.1778C3.51852 13.8741 4.35556 14.2222 5.33333 14.2222Z" fill="#16A249"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,3 @@
<svg width="18" height="14" viewBox="0 0 18 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 12.0833V7.91666C0 7.56944 0.121528 7.2743 0.364583 7.03125C0.607639 6.78819 0.902778 6.66666 1.25 6.66666C1.59722 6.66666 1.89236 6.78819 2.13542 7.03125C2.37847 7.2743 2.5 7.56944 2.5 7.91666V12.0833C2.5 12.4306 2.37847 12.7257 2.13542 12.9687C1.89236 13.2118 1.59722 13.3333 1.25 13.3333C0.902778 13.3333 0.607639 13.2118 0.364583 12.9687C0.121528 12.7257 0 12.4306 0 12.0833ZM5 12.0833V5.83333C5 5.48611 5.12153 5.19097 5.36458 4.94791C5.60764 4.70486 5.90278 4.58333 6.25 4.58333C6.59722 4.58333 6.89236 4.70486 7.13542 4.94791C7.37847 5.19097 7.5 5.48611 7.5 5.83333V12.0833C7.5 12.4306 7.37847 12.7257 7.13542 12.9687C6.89236 13.2118 6.59722 13.3333 6.25 13.3333C5.90278 13.3333 5.60764 13.2118 5.36458 12.9687C5.12153 12.7257 5 12.4306 5 12.0833ZM10 12.0833V3.75C10 3.40278 10.1215 3.10764 10.3646 2.86458C10.6076 2.62153 10.9028 2.5 11.25 2.5C11.5972 2.5 11.8924 2.62153 12.1354 2.86458C12.3785 3.10764 12.5 3.40278 12.5 3.75V12.0833C12.5 12.4306 12.3785 12.7257 12.1354 12.9687C11.8924 13.2118 11.5972 13.3333 11.25 13.3333C10.9028 13.3333 10.6076 13.2118 10.3646 12.9687C10.1215 12.7257 10 12.4306 10 12.0833ZM15 6.8125V1.25C15 0.902777 15.1215 0.607639 15.3646 0.364583C15.6076 0.121528 15.9028 0 16.25 0C16.5972 0 16.8924 0.121528 17.1354 0.364583C17.3785 0.607639 17.5 0.902777 17.5 1.25V6.54166C17.3611 6.51389 17.2257 6.49305 17.0938 6.47916C16.9618 6.46528 16.8194 6.45833 16.6667 6.45833C16.375 6.45833 16.0868 6.48958 15.8021 6.55208C15.5174 6.61458 15.25 6.70139 15 6.8125ZM16.0729 13.0937C15.9132 12.934 15.8333 12.7361 15.8333 12.5C15.8333 12.2639 15.9132 12.066 16.0729 11.9062C16.2326 11.7465 16.4306 11.6667 16.6667 11.6667C16.9028 11.6667 17.1007 11.7465 17.2604 11.9062C17.4201 12.066 17.5 12.2639 17.5 12.5C17.5 12.7361 17.4201 12.934 17.2604 13.0937C17.1007 13.2535 16.9028 13.3333 16.6667 13.3333C16.4306 13.3333 16.2326 13.2535 16.0729 13.0937ZM15.8333 10V8.75C15.8333 8.51389 15.9132 8.31597 16.0729 8.15625C16.2326 7.99652 16.4306 7.91666 16.6667 7.91666C16.9028 7.91666 17.1007 7.99652 17.2604 8.15625C17.4201 8.31597 17.5 8.51389 17.5 8.75V10C17.5 10.2361 17.4201 10.434 17.2604 10.5937C17.1007 10.7535 16.9028 10.8333 16.6667 10.8333C16.4306 10.8333 16.2326 10.7535 16.0729 10.5937C15.9132 10.434 15.8333 10.2361 15.8333 10Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.292969 2.29289C0.683493 1.90237 1.31651 1.90237 1.70703 2.29289L3.41406 3.99992H11.4424C12.3865 3.99991 13.1558 3.99969 13.7803 4.05071C14.4257 4.10345 15.0042 4.21564 15.543 4.49016C16.3897 4.92159 17.0783 5.61023 17.5098 6.45696C17.7843 6.99573 17.8965 7.57424 17.9492 8.21965C17.9518 8.25175 17.9517 8.28444 17.9541 8.31731L22.4189 5.12981C23.0808 4.65704 24 5.12991 24 5.94328V18.0566C24 18.8699 23.0808 19.3428 22.4189 18.87L18 15.7138V18.5859L19.707 20.2929C20.0976 20.6834 20.0976 21.3164 19.707 21.707C19.3165 22.0975 18.6835 22.0975 18.293 21.707L0.292969 3.70696C-0.097555 3.31643 -0.0975551 2.68342 0.292969 2.29289ZM1 7.99895C1.55212 7.99895 1.99974 8.44689 2 8.99895V13.3993C2 14.3959 2.00036 15.0836 2.04395 15.6171C2.08658 16.1387 2.16554 16.4249 2.27246 16.6347C2.51215 17.105 2.89491 17.4868 3.36523 17.7265C3.57511 17.8334 3.86102 17.9124 4.38281 17.955C4.91619 17.9986 5.60333 17.9989 6.59961 17.9989H11C11.5521 17.9989 11.9997 18.4469 12 18.9989C12 19.5512 11.5523 19.9989 11 19.9989H6.55762C5.61342 19.999 4.84421 19.9992 4.21973 19.9482C3.57428 19.8954 2.99583 19.7832 2.45703 19.5087C1.61035 19.0773 0.921646 18.3886 0.490235 17.5419C0.215871 17.0032 0.103504 16.4245 0.0507818 15.7792C-0.000207456 15.1548 -1.10191e-05 14.3854 5.0477e-07 13.4413V8.99895C0.00026378 8.44689 0.447878 7.99895 1 7.99895ZM16 16.5859V10.5995C16 9.60324 15.9986 8.91611 15.9551 8.38274C15.9125 7.86113 15.8344 7.57502 15.7275 7.36516C15.4879 6.89475 15.1052 6.51207 14.6348 6.27239C14.4249 6.16547 14.1389 6.0865 13.6172 6.04387C13.0837 6.00029 12.396 5.99992 11.3994 5.99992H5.41406L16 16.5859Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,3 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.3438 5.34375C14.9405 5.34375 15.5128 5.5808 15.9347 6.00276C16.3567 6.42472 16.5938 6.99701 16.5938 7.59375M14.3438 0.84375C16.134 0.84375 17.8509 1.55491 19.1167 2.82078C20.3826 4.08665 21.0938 5.80354 21.0938 7.59375M3.09375 1.96875H7.59375L9.84375 7.59375L7.03125 9.28125C8.23608 11.7242 10.2133 13.7014 12.6562 14.9062L14.3438 12.0938L19.9688 14.3438V18.8438C19.9688 19.4405 19.7317 20.0128 19.3097 20.4347C18.8878 20.8567 18.3155 21.0938 17.7188 21.0938C13.3304 20.8271 9.19142 18.9636 6.08268 15.8548C2.97394 12.7461 1.11043 8.60708 0.84375 4.21875C0.84375 3.62201 1.0808 3.04972 1.50276 2.62776C1.92472 2.2058 2.49701 1.96875 3.09375 1.96875Z" stroke="white" stroke-width="1.6875" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.83398 9.03418C6.1464 8.72177 6.6534 8.72178 6.96582 9.03418C7.27824 9.3466 7.27824 9.8536 6.96582 10.166L2.73047 14.4004H5.59961C6.04144 14.4004 6.40039 14.7584 6.40039 15.2002C6.40032 15.642 6.04139 16 5.59961 16H0.799805C0.750353 16 0.702243 15.994 0.655273 15.9854C0.650431 15.9845 0.645453 15.9844 0.640625 15.9834C0.632394 15.9817 0.624348 15.9795 0.616211 15.9775C0.599845 15.9737 0.583526 15.9697 0.567383 15.9648C0.525709 15.9522 0.485753 15.936 0.447266 15.917C0.370564 15.8792 0.298188 15.8294 0.234375 15.7656C0.170233 15.7015 0.119834 15.6289 0.0820312 15.5518C0.0522722 15.4911 0.0292924 15.4265 0.015625 15.3584C0.0146554 15.3536 0.0145519 15.3486 0.0136719 15.3438C0.0052094 15.2971 7.59671e-06 15.2493 0 15.2002V10.4004C0 9.95863 0.358067 9.59972 0.799805 9.59961C1.24163 9.59961 1.59961 9.95856 1.59961 10.4004V13.2686L5.83398 9.03418ZM15.2002 0C15.2493 1.2747e-05 15.2971 0.0052045 15.3438 0.0136719C15.3486 0.0145519 15.3536 0.0146554 15.3584 0.015625C15.3666 0.017277 15.3747 0.0195822 15.3828 0.0214844C15.3992 0.0253083 15.4155 0.0293148 15.4316 0.0341797C15.4733 0.0467652 15.5133 0.0631386 15.5518 0.0820312C15.6289 0.119834 15.7015 0.170233 15.7656 0.234375C15.8294 0.298188 15.8792 0.370564 15.917 0.447266C15.9252 0.463964 15.9334 0.480716 15.9404 0.498047C15.9612 0.549032 15.9755 0.601773 15.9854 0.655273C15.994 0.702239 16 0.750358 16 0.799805V5.59961C16 6.04137 15.6419 6.40028 15.2002 6.40039C14.7584 6.40039 14.4004 6.04144 14.4004 5.59961V2.73047L10.166 6.96582C9.8536 7.27824 9.3466 7.27824 9.03418 6.96582C8.72178 6.6534 8.72177 6.1464 9.03418 5.83398L13.2695 1.59961H10.4004C9.95856 1.59961 9.59961 1.24163 9.59961 0.799805C9.59972 0.358067 9.95863 0 10.4004 0H15.2002Z" fill="#EFF0FA"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,9 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 6.3V6C16 3.79 14.21 2 12 2C9.79 2 8 3.79 8 6V11" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.04004 14.19C9.77004 15 10.83 15.5 12 15.5C14.21 15.5 16 13.71 16 11.5V11" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.77979 16.9499C8.14979 18.2199 9.97978 18.9999 11.9998 18.9999C16.2198 18.9999 19.6498 15.5699 19.6498 11.3499V9.6499" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.3501 9.6499V11.3499C4.3501 12.4099 4.5601 13.4099 4.9501 14.3299" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20.0702 2.83984L3.93018 18.9898" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 3V6" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 19V22" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 15.5C14.21 15.5 16 13.71 16 11.5V6C16 3.79 14.21 2 12 2C9.79 2 8 3.79 8 6V11.5C8 13.71 9.79 15.5 12 15.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.35059 9.6499V11.3499C4.35059 15.5699 7.78059 18.9999 12.0006 18.9999C16.2206 18.9999 19.6506 15.5699 19.6506 11.3499V9.6499" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 19V22" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.40023 8.79965C6.44894 8.79967 6.49651 8.80496 6.54281 8.81332C6.54796 8.81425 6.5533 8.81424 6.55844 8.81527C6.56666 8.81692 6.57472 8.81923 6.58285 8.82113C6.5992 8.82496 6.61555 8.82896 6.63168 8.83383C6.64056 8.83651 6.64929 8.83963 6.65805 8.84262C6.69881 8.85648 6.73865 8.87374 6.77719 8.89437C6.80436 8.90894 6.83012 8.9257 6.85531 8.9432C6.89387 8.97001 6.93129 8.99965 6.96566 9.03402C6.9997 9.06805 7.02889 9.10526 7.05551 9.1434C7.05897 9.14836 7.06289 9.153 7.06625 9.15804C7.12722 9.24979 7.16631 9.35128 7.18539 9.4559C7.19389 9.50255 7.20001 9.55035 7.20004 9.59945V14.4002C7.19984 14.8418 6.84178 15.1998 6.40023 15.2C5.95852 15.2 5.59964 14.8419 5.59945 14.4002V11.5311L1.36508 15.7655C1.05264 16.0777 0.546577 16.0778 0.234217 15.7655C-0.0781257 15.4531 -0.0780189 14.947 0.234217 14.6346L4.46762 10.4002H1.59945C1.15782 10.4 0.799647 10.0411 0.799647 9.59945C0.799876 9.15796 1.15796 8.79988 1.59945 8.79965H6.40023ZM14.6346 0.234217C14.947 -0.0780189 15.4531 -0.0781257 15.7655 0.234217C16.0778 0.546577 16.0777 1.05264 15.7655 1.36508L11.5321 5.59945H14.4002C14.8419 5.59964 15.2 5.95852 15.2 6.40023C15.1998 6.84178 14.8418 7.19984 14.4002 7.20004H9.59945C9.55035 7.20001 9.50255 7.19389 9.4559 7.18539C9.45074 7.18445 9.44541 7.18448 9.44027 7.18344C9.43204 7.18177 9.42399 7.17949 9.41586 7.17758C9.3995 7.17372 9.38317 7.16978 9.36703 7.16488C9.35943 7.16257 9.35207 7.1596 9.34457 7.15707C9.30221 7.14282 9.2605 7.12587 9.22054 7.10433C9.19365 7.08982 9.16833 7.0729 9.1434 7.05551C9.10526 7.02889 9.06805 6.9997 9.03402 6.96566C8.99965 6.93129 8.97001 6.89387 8.9432 6.85531C8.9257 6.83012 8.90894 6.80436 8.89437 6.77719C8.85465 6.70298 8.82796 6.62378 8.81332 6.54281C8.80496 6.49651 8.79967 6.44894 8.79965 6.40023V1.59945C8.79988 1.15796 9.15796 0.799876 9.59945 0.799647C10.0411 0.799647 10.4 1.15782 10.4002 1.59945V4.46762L14.6346 0.234217Z" fill="#EFF0FA"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 0C15.523 0 20 4.477 20 10C20 15.523 15.523 20 10 20C4.477 20 0 15.523 0 10C0 4.477 4.477 0 10 0ZM10 2C7.87827 2 5.84344 2.84285 4.34315 4.34315C2.84285 5.84344 2 7.87827 2 10C2 12.1217 2.84285 14.1566 4.34315 15.6569C5.84344 17.1571 7.87827 18 10 18C12.1217 18 14.1566 17.1571 15.6569 15.6569C17.1571 14.1566 18 12.1217 18 10C18 7.87827 17.1571 5.84344 15.6569 4.34315C14.1566 2.84285 12.1217 2 10 2ZM10 13C10.2652 13 10.5196 13.1054 10.7071 13.2929C10.8946 13.4804 11 13.7348 11 14C11 14.2652 10.8946 14.5196 10.7071 14.7071C10.5196 14.8946 10.2652 15 10 15C9.73478 15 9.48043 14.8946 9.29289 14.7071C9.10536 14.5196 9 14.2652 9 14C9 13.7348 9.10536 13.4804 9.29289 13.2929C9.48043 13.1054 9.73478 13 10 13ZM10 4C10.2652 4 10.5196 4.10536 10.7071 4.29289C10.8946 4.48043 11 4.73478 11 5V11C11 11.2652 10.8946 11.5196 10.7071 11.7071C10.5196 11.8946 10.2652 12 10 12C9.73478 12 9.48043 11.8946 9.29289 11.7071C9.10536 11.5196 9 11.2652 9 11V5C9 4.73478 9.10536 4.48043 9.29289 4.29289C9.48043 4.10536 9.73478 4 10 4Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

16
assets/icons/vk_logo.svg Normal file
View File

@@ -0,0 +1,16 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1709_298)">
<mask id="mask0_1709_298" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="28">
<path d="M27.8614 0H0.138672V28H27.8614V0Z" fill="white"/>
</mask>
<g mask="url(#mask0_1709_298)">
<path d="M0.138672 13.44C0.138672 7.10433 0.138672 3.93649 2.08743 1.96824C4.03619 0 7.17266 0 13.4456 0H14.5545C20.8275 0 23.9639 0 25.9127 1.96824C27.8614 3.93649 27.8614 7.10433 27.8614 13.44V14.56C27.8614 20.8957 27.8614 24.0635 25.9127 26.0318C23.9639 28 20.8275 28 14.5545 28H13.4456C7.17266 28 4.03619 28 2.08743 26.0318C0.138672 24.0635 0.138672 20.8957 0.138672 14.56V13.44Z" fill="#0077FF"/>
<path d="M14.89 20.1718C8.57149 20.1718 4.96756 15.7968 4.81738 8.51675H7.98241C8.08637 13.8601 10.4197 16.1234 12.2678 16.5901V8.51675H15.2481V13.125C17.0732 12.9267 18.9905 10.8268 19.6373 8.51675H22.6176C22.1209 11.3634 20.0417 13.4634 18.5632 14.3267C20.0417 15.0267 22.4098 16.8584 23.3108 20.1718H20.0302C19.3255 17.9551 17.5699 16.2401 15.2481 16.0067V20.1718H14.89Z" fill="white"/>
</g>
</g>
<defs>
<clipPath id="clip0_1709_298">
<rect width="28" height="28" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,16 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1709_319)">
<mask id="mask0_1709_319" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="28">
<path d="M27.8614 0H0.138672V28H27.8614V0Z" fill="white"/>
</mask>
<g mask="url(#mask0_1709_319)">
<path d="M0.138672 13.44C0.138672 7.10433 0.138672 3.93649 2.08743 1.96824C4.03619 0 7.17266 0 13.4456 0H14.5545C20.8275 0 23.9639 0 25.9127 1.96824C27.8614 3.93649 27.8614 7.10433 27.8614 13.44V14.56C27.8614 20.8957 27.8614 24.0635 25.9127 26.0318C23.9639 28 20.8275 28 14.5545 28H13.4456C7.17266 28 4.03619 28 2.08743 26.0318C0.138672 24.0635 0.138672 20.8957 0.138672 14.56V13.44Z" fill="#FC3F1D"/>
</g>
<path d="M17.3371 24H21V4H15.6687C10.3069 4 7.49454 6.614 7.49454 10.4755C7.49454 13.809 9.31785 15.6885 12.5476 17.73L14.51 18.9635L11.9911 16.9515L7 24H10.971L16.3029 16.423L14.4486 15.248C12.2079 13.809 11.1107 12.693 11.1107 10.27C11.1107 8.141 12.6873 6.702 15.6844 6.702H17.3224V24H17.3382H17.3371Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_1709_319">
<rect width="28" height="28" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/images/logo_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

View File

@@ -0,0 +1,39 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/env_config.dart';
import 'package:eatvio_app/features/feed/presentation/pages/feed_screen.dart';
import 'package:eatvio_app/main.dart' as app;
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../common_cases/skip_welcome_screen.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
await AppInitializer.initialize(buildType: AppBuildType.tests);
});
testWidgets('Signs in successfully with valid credentials', (WidgetTester tester) async {
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 3));
await skipWelcomeScreen(tester);
final emailFieldFinder = find.byKey(AppKeys.emailTextFieldAuthScreen);
final passwordFieldFinder = find.byKey(AppKeys.passwordTextFieldAuthScreen);
final signInButtonFinder = find.byKey(AppKeys.signInButtonAuthScreen);
expect(emailFieldFinder, findsOneWidget, reason: 'Email text field should be found.');
expect(passwordFieldFinder, findsOneWidget, reason: 'Password text field should be found.');
expect(signInButtonFinder, findsOneWidget, reason: 'Sign In button should be found.');
await tester.enterText(emailFieldFinder, EnvConfig.testEmail);
await tester.enterText(passwordFieldFinder, EnvConfig.testPassword);
await tester.pumpAndSettle();
await tester.tap(signInButtonFinder);
await tester.pumpAndSettle(const Duration(seconds: 3));
expect(FeedScreen, findsOne, reason: 'Feed screen should be visible after successful login and navigation.');
});
}

View File

@@ -0,0 +1,31 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/features/dev_tools/presentation/dev_tools_screen.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:eatvio_app/main.dart' as app;
import '../common_cases/skip_welcome_screen.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
await AppInitializer.initialize(buildType: AppBuildType.tests);
});
testWidgets('tapping logo 7 times opens dev tools', (WidgetTester tester) async {
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 3));
await skipWelcomeScreen(tester);
final logoButtonFinder = find.byKey(AppKeys.hiddenLogoButtonAuthScreen);
expect(logoButtonFinder, findsOneWidget, reason: 'The logo GestureDetector should be found in auth screen');
for (int i = 0; i < 7; i++) {
await tester.tap(logoButtonFinder);
await tester.pump(const Duration(milliseconds: 50));
}
await tester.pumpAndSettle();
expect(find.byType(DevToolsScreen), findsOneWidget, reason: 'DevToolsScreen should be visible after tapping the logo 7 times.');
});
}

View File

@@ -0,0 +1,21 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:eatvio_app/core/env_config.dart';
import 'package:flutter_test/flutter_test.dart';
Future<void> skipSignIn(WidgetTester tester) async {
final emailFieldFinder = find.byKey(AppKeys.emailTextFieldAuthScreen);
final passwordFieldFinder = find.byKey(AppKeys.passwordTextFieldAuthScreen);
final signInButtonFinder = find.byKey(AppKeys.signInButtonAuthScreen);
expect(emailFieldFinder, findsOneWidget, reason: 'Email text field should be found.');
expect(passwordFieldFinder, findsOneWidget, reason: 'Password text field should be found.');
expect(signInButtonFinder, findsOneWidget, reason: 'Sign In button should be found.');
await tester.enterText(emailFieldFinder, EnvConfig.testEmail);
await tester.enterText(passwordFieldFinder, EnvConfig.testPassword);
await tester.pumpAndSettle();
await tester.tap(signInButtonFinder);
await tester.pumpAndSettle(const Duration(seconds: 3));
}

View File

@@ -0,0 +1,8 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:flutter_test/flutter_test.dart';
Future<void> skipWelcomeScreen(WidgetTester tester) async {
final welcomeScreenButtonFinder = find.byKey(AppKeys.welcomeScreenButton);
await tester.tap(welcomeScreenButtonFinder);
await tester.pumpAndSettle();
}

View File

@@ -0,0 +1,147 @@
# Интеграционные тесты создания рецепта
Этот набор интеграционных тестов покрывает полный пользовательский путь создания нового рецепта в приложении Eatvio.
## Структура файлов
- `create_recipe_test.dart` - Основные интеграционные тесты
- `create_recipe_helpers.dart` - Helper функции для тестирования
- `README.md` - Документация
## Тестовые сценарии
### 1. Полное создание рецепта
**Файл:** `create_recipe_test.dart` - `should create and publish a new recipe successfully`
**Описание:** Тестирует полный пользовательский путь создания рецепта с заполнением всех полей.
**Шаги:**
1. Запуск приложения и вход в систему
2. Навигация к экрану создания рецепта
3. Заполнение основной информации (название, тип, порции, калории, время)
4. Добавление тегов
5. Добавление ингредиентов
6. Добавление шагов приготовления
7. Симуляция добавления изображения
8. Публикация рецепта
9. Проверка успешного перехода
### 2. Валидация полей
**Файл:** `create_recipe_test.dart` - `should validate required fields before publishing`
**Описание:** Проверяет, что валидация обязательных полей работает корректно.
**Шаги:**
1. Запуск приложения и вход в систему
2. Навигация к экрану создания рецепта
3. Попытка публикации без заполнения полей
4. Проверка, что остались на экране создания (валидация не прошла)
### 3. Минимальное создание рецепта
**Файл:** `create_recipe_test.dart` - `should create recipe with minimal required fields`
**Описание:** Тестирует создание рецепта с минимально необходимыми полями.
**Шаги:**
1. Запуск приложения и вход в систему
2. Навигация к экрану создания рецепта
3. Заполнение только обязательных полей
4. Добавление минимума ингредиентов
5. Симуляция добавления изображения
6. Публикация рецепта
7. Проверка успешного перехода
## Helper функции
### Навигация
- `navigateToCreateRecipeScreen()` - Переход к экрану создания рецепта
### Заполнение формы
- `fillRecipeBasicInfo()` - Заполнение основной информации о рецепте
- `selectRecipeType()` - Выбор типа рецепта
- `addTags()` - Добавление тегов
- `addIngredients()` - Добавление ингредиентов
- `addCookingSteps()` - Добавление шагов приготовления
### Публикация и проверки
- `publishRecipe()` - Публикация рецепта
- `verifyRecipePublished()` - Проверка успешной публикации
- `verifyValidationErrors()` - Проверка ошибок валидации
### Симуляция изображений
- `mockImageSelection()` - Симуляция выбора изображения для рецепта
- `mockStepImageSelection()` - Симуляция выбора изображения для шага
### Тестовые данные
- `createTestRecipeData()` - Создание набора тестовых данных
## Ключи для тестирования
В файле `lib/app_keys.dart` добавлены следующие ключи для стабильного тестирования:
### Основные поля
- `recipeCreateScreenTitleField` - Поле названия
- `recipeCreateScreenDescriptionField` - Поле описания
- `recipeCreateScreenTypeDropdown` - Выпадающий список типа рецепта
- `recipeCreateScreenPortionsField` - Поле количества порций
- `recipeCreateScreenCaloriesField` - Поле калорийности
### Время приготовления
- `recipeCreateScreenTotalHoursField` - Часы общего времени
- `recipeCreateScreenTotalMinutesField` - Минуты общего времени
- `recipeCreateScreenActiveHoursField` - Часы активного времени
- `recipeCreateScreenActiveMinutesField` - Минуты активного времени
### Теги и ингредиенты
- `recipeCreateScreenTagField` - Поле для ввода тега
- `recipeCreateScreenAddTagButton` - Кнопка добавления тега
- `recipeCreateScreenAddIngredientButton` - Кнопка добавления ингредиента
### Шаги приготовления
- `recipeCreateScreenAddStepButton` - Кнопка добавления шага
- `recipeCreateScreenStepDescriptionField` - Поле описания шага
- `recipeCreateScreenStepImageWidget` - Виджет изображения шага
### Изображения и публикация
- `recipeCreateScreenImageWidget` - Виджет основного изображения
- `recipeCreateScreenPublishButton` - Кнопка публикации
## Запуск тестов
```bash
# Запуск всех интеграционных тестов
flutter test integration_test/
# Запуск только тестов создания рецепта
flutter test integration_test/create_recipe/
# Запуск конкретного теста
flutter test integration_test/create_recipe/create_recipe_test.dart
```
## Требования
- Flutter SDK
- Настроенная тестовая среда (AppBuildType.tests)
- Тестовые учетные данные в .env файле
- Доступ к API бэкенда для тестирования
## Примечания
1. **Изображения**: В текущей реализации используется симуляция выбора изображений. Для полноценного тестирования рекомендуется добавить моки для `image_picker`.
2. **API взаимодействие**: Тесты взаимодействуют с реальным API бэкенда. Убедитесь, что тестовая среда настроена корректно.
3. **Время выполнения**: Тесты могут занимать значительное время из-за анимаций и API запросов. Используйте `pumpAndSettle()` с достаточными таймаутами.
4. **Стабильность**: Ключи для тестирования добавлены в UI компоненты для обеспечения стабильности тестов при изменениях в интерфейсе.
## Расширение тестов
Для добавления новых тестовых сценариев:
1. Создайте новый `testWidgets` в `create_recipe_test.dart`
2. Используйте существующие helper функции или создайте новые в `create_recipe_helpers.dart`
3. При необходимости добавьте новые ключи в `app_keys.dart`
4. Обновите документацию в этом файле

View File

@@ -0,0 +1,237 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:eatvio_app/features/create_recipe/entities/recipe_create_entity.dart';
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
/// Helper функции для интеграционных тестов создания рецепта
/// Навигация к экрану создания рецепта
Future<void> navigateToCreateRecipeScreen(WidgetTester tester) async {
// Переключаемся на вкладку "Рецепты" если она есть
final recipesTab = find.text('Рецепты');
if (recipesTab.evaluate().isNotEmpty) {
await tester.tap(recipesTab);
await tester.pumpAndSettle();
}
// Находим кнопку добавления рецепта (круглая кнопка с плюсом)
final addRecipeButton = find.byType(InkWell).first;
await tester.tap(addRecipeButton);
await tester.pumpAndSettle(const Duration(seconds: 2));
}
/// Заполняет основную информацию о рецепте
Future<void> fillRecipeBasicInfo(
WidgetTester tester, {
String title = 'Интеграционный Тестовый Рецепт',
TypeOfRecipe type = TypeOfRecipe.salads,
int portions = 4,
double calories = 250.0,
int totalHours = 1,
int totalMinutes = 30,
int activeHours = 0,
int activeMinutes = 45,
String description = 'Этот рецепт создан для интеграционного тестирования. Он содержит все необходимые ингредиенты и пошаговую инструкцию приготовления.',
}) async {
// Заполняем название рецепта
final titleField = find.byKey(AppKeys.recipeCreateScreenTitleField);
await tester.enterText(titleField, title);
await tester.pumpAndSettle();
// Выбираем тип рецепта
await selectRecipeType(tester, type);
// Заполняем количество порций
final portionsField = find.byKey(AppKeys.recipeCreateScreenPortionsField);
await tester.enterText(portionsField, portions.toString());
await tester.pumpAndSettle();
// Заполняем калорийность
final caloriesField = find.byKey(AppKeys.recipeCreateScreenCaloriesField);
await tester.enterText(caloriesField, calories.toString());
await tester.pumpAndSettle();
// Заполняем общее время приготовления
final totalHoursField = find.byKey(AppKeys.recipeCreateScreenTotalHoursField);
await tester.enterText(totalHoursField, totalHours.toString());
await tester.pumpAndSettle();
final totalMinutesField = find.byKey(AppKeys.recipeCreateScreenTotalMinutesField);
await tester.enterText(totalMinutesField, totalMinutes.toString());
await tester.pumpAndSettle();
// Заполняем активное время приготовления
final activeHoursField = find.byKey(AppKeys.recipeCreateScreenActiveHoursField);
await tester.enterText(activeHoursField, activeHours.toString());
await tester.pumpAndSettle();
final activeMinutesField = find.byKey(AppKeys.recipeCreateScreenActiveMinutesField);
await tester.enterText(activeMinutesField, activeMinutes.toString());
await tester.pumpAndSettle();
// Заполняем описание
final descriptionField = find.byKey(AppKeys.recipeCreateScreenDescriptionField);
await tester.enterText(descriptionField, description);
await tester.pumpAndSettle();
}
/// Выбирает тип рецепта из выпадающего списка
Future<void> selectRecipeType(WidgetTester tester, TypeOfRecipe type) async {
final typeDropdown = find.byKey(AppKeys.recipeCreateScreenTypeDropdown);
await tester.tap(typeDropdown);
await tester.pumpAndSettle();
// Выбираем нужный тип из выпадающего списка
final typeOption = find.text(type.toString());
await tester.tap(typeOption);
await tester.pumpAndSettle();
}
/// Добавляет теги к рецепту
Future<void> addTags(WidgetTester tester, List<String> tags) async {
final tagField = find.byKey(AppKeys.recipeCreateScreenTagField);
final addTagButton = find.byKey(AppKeys.recipeCreateScreenAddTagButton);
for (final tag in tags) {
await tester.enterText(tagField, tag);
await tester.pumpAndSettle();
await tester.tap(addTagButton);
await tester.pumpAndSettle();
}
}
/// Добавляет ингредиенты к рецепту
Future<void> addIngredients(WidgetTester tester, List<Map<String, String>> ingredients) async {
final addIngredientButton = find.byKey(AppKeys.recipeCreateScreenAddIngredientButton);
for (final ingredient in ingredients) {
await tester.ensureVisible(addIngredientButton);
await tester.tap(addIngredientButton);
await tester.pumpAndSettle();
await addIngredientInModal(tester, ingredient['name']!, ingredient['quantity']!);
await tester.pumpAndSettle();
}
}
/// Добавляет ингредиент в модальном окне
Future<void> addIngredientInModal(WidgetTester tester, String name, String quantity) async {
// Ищем поля в модальном окне
final nameFields = find.byType(TextFormField);
if (nameFields.evaluate().isNotEmpty) {
await tester.enterText(nameFields.first, name);
await tester.pumpAndSettle();
}
// Ищем поле количества (второе поле)
if (nameFields.evaluate().length > 1) {
await tester.enterText(nameFields.at(1), quantity);
await tester.pumpAndSettle();
}
// Ищем кнопку добавления в модальном окне
final addButton = find.text('Добавить');
if (addButton.evaluate().isNotEmpty) {
await tester.tap(addButton);
await tester.pumpAndSettle();
}
}
/// Добавляет шаги приготовления
Future<void> addCookingSteps(WidgetTester tester, List<Map<String, String>> steps) async {
final addStepButton = find.byKey(AppKeys.recipeCreateScreenAddStepButton);
for (int i = 0; i < steps.length; i++) {
final step = steps[i];
// Заполняем описание шага
final stepDescription = find.byKey(Key('${AppKeys.recipeCreateScreenStepDescriptionField}_$i'));
await tester.enterText(stepDescription, step['description']!);
await tester.pumpAndSettle();
// Симулируем добавление изображения к шагу если указано
if (step.containsKey('hasImage') && step['hasImage'] == 'true') {
await mockStepImageSelection(tester, i);
}
// Добавляем следующий шаг (кроме последнего)
if (i < steps.length - 1) {
await tester.ensureVisible(addStepButton);
await tester.tap(addStepButton);
await tester.pumpAndSettle();
}
}
}
/// Публикует рецепт
Future<void> publishRecipe(WidgetTester tester) async {
final publishButton = find.byKey(AppKeys.recipeCreateScreenPublishButton);
await tester.ensureVisible(publishButton);
await tester.tap(publishButton);
await tester.pumpAndSettle(const Duration(seconds: 5)); // Дать время на API-запрос
}
/// Симулирует выбор изображения для основного рецепта
Future<void> mockImageSelection(WidgetTester tester) async {
final imageWidget = find.byKey(AppKeys.recipeCreateScreenImageWidget);
if (imageWidget.evaluate().isNotEmpty) {
await tester.tap(imageWidget);
await tester.pumpAndSettle();
// В реальном интеграционном тесте здесь будет мок image_picker
// который возвращает тестовое изображение
}
}
/// Симулирует выбор изображения для шага приготовления
Future<void> mockStepImageSelection(WidgetTester tester, int stepIndex) async {
final stepImageWidget = find.byKey(Key('${AppKeys.recipeCreateScreenStepImageWidget}_$stepIndex'));
if (stepImageWidget.evaluate().isNotEmpty) {
await tester.tap(stepImageWidget);
await tester.pumpAndSettle();
// В реальном интеграционном тесте здесь будет мок image_picker
// который возвращает тестовое изображение
}
}
/// Проверяет, что рецепт был успешно опубликован
void verifyRecipePublished(WidgetTester tester) {
// После успешной публикации должен произойти переход обратно на экран ленты
expect(find.byKey(AppKeys.recipeCreateScreenPublishButton), findsNothing);
// Можно добавить дополнительные проверки в зависимости от того, куда происходит переход
}
/// Проверяет, что валидация полей работает корректно
void verifyValidationErrors(WidgetTester tester) {
// Проверяем, что остались на экране создания рецепта (валидация не прошла)
expect(find.byType(RecipeCreateScreen), findsOneWidget);
expect(find.byKey(AppKeys.recipeCreateScreenPublishButton), findsOneWidget);
}
/// Создает тестовые данные для рецепта
Map<String, dynamic> createTestRecipeData() {
return {
'title': 'Интеграционный Тестовый Рецепт',
'type': TypeOfRecipe.salads,
'portions': 4,
'calories': 250.0,
'totalHours': 1,
'totalMinutes': 30,
'activeHours': 0,
'activeMinutes': 45,
'description': 'Этот рецепт создан для интеграционного тестирования. Он содержит все необходимые ингредиенты и пошаговую инструкцию приготовления.',
'tags': ['здоровое питание', 'быстро', 'легко'],
'ingredients': [
{'name': 'Помидоры', 'quantity': '200'},
{'name': 'Огурцы', 'quantity': '150'},
{'name': 'Лук', 'quantity': '50'},
],
'steps': [
{'description': 'Помойте и нарежьте помидоры и огурцы кубиками среднего размера.', 'hasImage': 'true'},
{'description': 'Нарежьте лук полукольцами и добавьте к овощам.', 'hasImage': 'false'},
{'description': 'Смешайте все ингредиенты в большой миске, добавьте соль и перец по вкусу.', 'hasImage': 'true'},
],
};
}

View File

@@ -0,0 +1,128 @@
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/features/create_recipe/entities/recipe_create_entity.dart';
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
import 'package:eatvio_app/main.dart' as app;
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../common_cases/skip_welcome_screen.dart';
import '../common_cases/skip_sign_in.dart';
import 'create_recipe_helpers.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
await AppInitializer.initialize(buildType: AppBuildType.tests);
});
group('Create Recipe Integration Tests', () {
testWidgets('should create and publish a new recipe successfully', (tester) async {
// 1. Запустить приложение
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 20));
// 2. Пропустить онбординг и войти в систему
await skipWelcomeScreen(tester);
await skipSignIn(tester);
await tester.pumpAndSettle(const Duration(seconds: 3));
// 3. Перейти на экран создания рецепта
await navigateToCreateRecipeScreen(tester);
// Проверяем, что мы на экране создания рецепта
expect(find.byType(RecipeCreateScreen), findsOneWidget);
// 4. Заполнить все поля формы
final testData = createTestRecipeData();
await fillRecipeBasicInfo(
tester,
title: testData['title'] as String,
type: testData['type'] as TypeOfRecipe,
portions: testData['portions'] as int,
calories: testData['calories'] as double,
totalHours: testData['totalHours'] as int,
totalMinutes: testData['totalMinutes'] as int,
activeHours: testData['activeHours'] as int,
activeMinutes: testData['activeMinutes'] as int,
description: testData['description'] as String,
);
// 5. Добавить теги
await addTags(tester, testData['tags'] as List<String>);
// 6. Добавить ингредиенты
await addIngredients(tester, testData['ingredients'] as List<Map<String, String>>);
// 7. Добавить шаги приготовления
await addCookingSteps(tester, testData['steps'] as List<Map<String, String>>);
// 8. Симулировать добавление изображения
await mockImageSelection(tester);
// 9. Нажать "Опубликовать"
await publishRecipe(tester);
// 10. Проверить результат
verifyRecipePublished(tester);
});
testWidgets('should validate required fields before publishing', (tester) async {
// 1. Запустить приложение и войти в систему
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 3));
await skipWelcomeScreen(tester);
await skipSignIn(tester);
await tester.pumpAndSettle(const Duration(seconds: 3));
// 2. Перейти на экран создания рецепта
await navigateToCreateRecipeScreen(tester);
// 3. Попытаться опубликовать без заполнения полей
await publishRecipe(tester);
// 4. Проверить, что валидация сработала
verifyValidationErrors(tester);
});
testWidgets('should create recipe with minimal required fields', (tester) async {
// 1. Запустить приложение и войти в систему
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 3));
await skipWelcomeScreen(tester);
await skipSignIn(tester);
await tester.pumpAndSettle(const Duration(seconds: 3));
// 2. Перейти на экран создания рецепта
await navigateToCreateRecipeScreen(tester);
// 3. Заполнить только обязательные поля
await fillRecipeBasicInfo(
tester,
title: 'Минимальный тестовый рецепт',
type: TypeOfRecipe.firstMeals,
portions: 2,
calories: 300.0,
totalHours: 0,
totalMinutes: 30,
activeHours: 0,
activeMinutes: 15,
description: 'Простой рецепт для тестирования.',
);
// 4. Добавить минимум ингредиентов
await addIngredients(tester, [
{'name': 'Тестовый ингредиент', 'quantity': '100'},
]);
// 5. Симулировать добавление изображения
await mockImageSelection(tester);
// 6. Опубликовать рецепт
await publishRecipe(tester);
// 7. Проверить результат
verifyRecipePublished(tester);
});
});
}

View File

@@ -0,0 +1,31 @@
import 'package:eatvio_app/app_keys.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/main.dart' as app;
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../common_cases/skip_sign_in.dart';
import '../common_cases/skip_welcome_screen.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async {
await AppInitializer.initialize(buildType: AppBuildType.tests);
});
testWidgets('qwe', (WidgetTester tester) async {
await tester.pumpWidget(const app.MyApp());
await tester.pumpAndSettle(const Duration(seconds: 3));
await skipWelcomeScreen(tester);
await skipSignIn(tester);
final blogPostCreationFinder = find.byKey(AppKeys.feedScreenBlogPostCreationButton);
expect(blogPostCreationFinder, findsOneWidget, reason: 'Blog post creation button should be found.');
await tester.tap(blogPostCreationFinder);
await tester.pumpAndSettle();
});
}

View File

@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<string>16.0</string>
</dict>
</plist>

View File

@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '14.0'
platform :ios, '16.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -39,16 +39,16 @@ post_install do |installer|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.camera
'PERMISSION_CAMERA=1',
## dart: PermissionGroup.microphone
'PERMISSION_MICROPHONE=1',
## dart: PermissionGroup.photos
'PERMISSION_PHOTOS=1',
'PERMISSION_NOTIFICATIONS=1',
## dart: PermissionGroup.mediaLibrary
'PERMISSION_MEDIA_LIBRARY=1',
]
end

View File

@@ -11,6 +11,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
46B43B96F809CEC6058EFDD3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15ADDB2A35F334AF0AE50011 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
C4A8E2022E9A4B1000123456 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A8E2012E9A4B1000123456 /* SceneDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -37,6 +38,7 @@
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C4A8E2012E9A4B1000123456 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
938EE8FB5BAA359AAEDEFFF8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
@@ -115,6 +117,7 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
C4A8E2012E9A4B1000123456 /* SceneDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
FEE92A0E2D772EA300E6E989 /* Runner.entitlements */,
);
@@ -213,14 +216,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -287,14 +286,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -308,6 +303,7 @@
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
C4A8E2022E9A4B1000123456 /* SceneDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -378,7 +374,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -396,7 +392,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 67;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -405,7 +401,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -414,10 +410,11 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.2.3;
MARKETING_VERSION = 1.3.3;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@@ -474,7 +471,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -526,7 +523,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -546,7 +543,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 67;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -555,7 +552,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -564,10 +561,11 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.2.3;
MARKETING_VERSION = 1.3.3;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -584,7 +582,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 67;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -593,7 +591,7 @@
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Eatvio;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -602,10 +600,11 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.2.3;
MARKETING_VERSION = 1.3.3;
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";

View File

@@ -41,7 +41,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>67</string>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
@@ -31,18 +31,43 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSAppleMusicUsageDescription</key>
<string>This permission is not needed by the app, but it is required by an underlying API. If you see this dialog, contact us.</string>
<key>NSCameraUsageDescription</key>
<string>Предоставление доступа позволит Вам делать фотографии и добавлять к записям</string>
<key>NSMicrophoneUsageDescription</key>
<string>Нужен для звука в видеозвонках с консультантом</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Может использоваться для стабильного поддержания связи во время звонка.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<string>Может использоваться для стабильного поддержания связи во время звонка.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Предоставление доступа позволит Вам добавлять фото к записям</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>voip</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
@@ -67,5 +92,83 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>yandexauth</string>
<string>yandexauth2</string>
<string>yandexauth4</string>
<!-- SBP bank schemes (top ~50 by popularity, iOS 15+ caps at 50) -->
<string>bank100000000111</string>
<string>bank100000000004</string>
<string>bank100000000005</string>
<string>bank100000000008</string>
<string>bank100000000007</string>
<string>bank100000000015</string>
<string>bank100000000001</string>
<string>bank100000000010</string>
<string>bank100000000013</string>
<string>bank100000000012</string>
<string>bank100000000020</string>
<string>bank100000000025</string>
<string>bank100000000030</string>
<string>bank100000000030_new</string>
<string>bank100000000003</string>
<string>bank100000000043</string>
<string>bank100000000028</string>
<string>bank100000000086</string>
<string>bank100000000011</string>
<string>bank100000000044</string>
<string>bank100000000049</string>
<string>bank100000000500</string>
<string>bank100000000095</string>
<string>bank100000000900</string>
<string>bank100000000056</string>
<string>bank100000000053</string>
<string>bank100000000121</string>
<string>bank100000000082</string>
<string>bank100000000127</string>
<string>bank100000000017</string>
<string>bank100000000087</string>
<string>bank100000000052</string>
<string>bank100000000006</string>
<string>bank100000000098</string>
<string>bank100000000092</string>
<string>bank100000000229</string>
<string>bank100000000027</string>
<string>bank100000000080</string>
<string>bank100000000122</string>
<string>bank100000000124</string>
<string>bank100000000118</string>
<string>bank100000000159</string>
<string>bank100000000146</string>
<string>bank100000000069</string>
<string>bank100000000140</string>
<string>bank100000000047</string>
<string>bank100000000099</string>
<string>bank100000000135</string>
<string>bank100000000139</string>
<string>bank100000000022</string>
</array>
<key>YAClientId</key>
<string>5399b03636104c6d920b87c1ad329254</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>YandexLoginSDK</string>
<key>CFBundleURLSchemes</key>
<array>
<string>yx5399b03636104c6d920b87c1ad329254</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Eatvio</string>
<key>CFBundleURLSchemes</key>
<array>
<string>eatvio</string>
</array>
</dict>
</array>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More