@pi-spi/app 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/lib/module/l10n/app_localizations.js.map +1 -1
  2. package/lib/module/l10n/app_localizations_en.js +32 -8
  3. package/lib/module/l10n/app_localizations_en.js.map +1 -1
  4. package/lib/module/l10n/app_localizations_fr.js +41 -14
  5. package/lib/module/l10n/app_localizations_fr.js.map +1 -1
  6. package/lib/module/l10n/app_localizations_pt.js +33 -7
  7. package/lib/module/l10n/app_localizations_pt.js.map +1 -1
  8. package/lib/module/modules/alias/domain/models/alias_revendication.js +4 -2
  9. package/lib/module/modules/alias/domain/models/alias_revendication.js.map +1 -1
  10. package/lib/module/modules/alias/infra/alias_output_local.js +11 -0
  11. package/lib/module/modules/alias/infra/alias_output_local.js.map +1 -1
  12. package/lib/module/modules/alias/infra/alias_output_repository.js +9 -8
  13. package/lib/module/modules/alias/infra/alias_output_repository.js.map +1 -1
  14. package/lib/module/modules/alias/presentation/pages/alias_delete_btn_widget.js +14 -18
  15. package/lib/module/modules/alias/presentation/pages/alias_delete_btn_widget.js.map +1 -1
  16. package/lib/module/modules/alias/presentation/pages/alias_page_claim.js +113 -60
  17. package/lib/module/modules/alias/presentation/pages/alias_page_claim.js.map +1 -1
  18. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_form.js +151 -76
  19. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_form.js.map +1 -1
  20. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_timer.js +38 -24
  21. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_timer.js.map +1 -1
  22. package/lib/module/modules/alias/presentation/pages/alias_page_create_options.js +28 -26
  23. package/lib/module/modules/alias/presentation/pages/alias_page_create_options.js.map +1 -1
  24. package/lib/module/modules/alias/presentation/pages/alias_page_otp.js +27 -110
  25. package/lib/module/modules/alias/presentation/pages/alias_page_otp.js.map +1 -1
  26. package/lib/module/modules/categorie/domain/services/categorie_service.js +2 -1
  27. package/lib/module/modules/categorie/domain/services/categorie_service.js.map +1 -1
  28. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js +38 -42
  29. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js.map +1 -1
  30. package/lib/module/modules/categorie/presentation/pages/categorie_form_pages.js +88 -80
  31. package/lib/module/modules/categorie/presentation/pages/categorie_form_pages.js.map +1 -1
  32. package/lib/module/modules/categorie/presentation/pages/categorie_icon.js +39 -0
  33. package/lib/module/modules/categorie/presentation/pages/categorie_icon.js.map +1 -1
  34. package/lib/module/modules/categorie/presentation/pages/categorie_liste_widget.js +55 -27
  35. package/lib/module/modules/categorie/presentation/pages/categorie_liste_widget.js.map +1 -1
  36. package/lib/module/modules/categorie/presentation/pages/categorie_select_page.js +21 -81
  37. package/lib/module/modules/categorie/presentation/pages/categorie_select_page.js.map +1 -1
  38. package/lib/module/modules/categorie/presentation/pages/categorie_select_widget.js +53 -16
  39. package/lib/module/modules/categorie/presentation/pages/categorie_select_widget.js.map +1 -1
  40. package/lib/module/modules/config/domain/models/config_keys.js +2 -0
  41. package/lib/module/modules/config/domain/models/config_keys.js.map +1 -1
  42. package/lib/module/modules/contacts/domain/contact_pi.js +3 -5
  43. package/lib/module/modules/contacts/domain/contact_pi.js.map +1 -1
  44. package/lib/module/modules/contacts/presentation/bloc/contact_bloc.js +30 -14
  45. package/lib/module/modules/contacts/presentation/bloc/contact_bloc.js.map +1 -1
  46. package/lib/module/modules/contacts/presentation/pages/contact_actions_sheet.js +106 -0
  47. package/lib/module/modules/contacts/presentation/pages/contact_actions_sheet.js.map +1 -0
  48. package/lib/module/modules/contacts/presentation/pages/contact_list_alias_widget.js +17 -7
  49. package/lib/module/modules/contacts/presentation/pages/contact_list_alias_widget.js.map +1 -1
  50. package/lib/module/modules/contacts/presentation/pages/contact_list_phone_widget.js +5 -4
  51. package/lib/module/modules/contacts/presentation/pages/contact_list_phone_widget.js.map +1 -1
  52. package/lib/module/modules/contacts/presentation/pages/contact_list_widget_item.js +76 -67
  53. package/lib/module/modules/contacts/presentation/pages/contact_list_widget_item.js.map +1 -1
  54. package/lib/module/modules/contacts/presentation/pages/contact_section.js +14 -4
  55. package/lib/module/modules/contacts/presentation/pages/contact_section.js.map +1 -1
  56. package/lib/module/modules/contacts/presentation/pages/contact_select_page.js +131 -110
  57. package/lib/module/modules/contacts/presentation/pages/contact_select_page.js.map +1 -1
  58. package/lib/module/modules/contacts/presentation/pages/create/contact_create_page.js +118 -59
  59. package/lib/module/modules/contacts/presentation/pages/create/contact_create_page.js.map +1 -1
  60. package/lib/module/modules/home/presentation/pages/home_page.js +3 -13
  61. package/lib/module/modules/home/presentation/pages/home_page.js.map +1 -1
  62. package/lib/module/modules/introduction/presentation/pages/introduction.js +17 -4
  63. package/lib/module/modules/introduction/presentation/pages/introduction.js.map +1 -1
  64. package/lib/module/modules/introduction/presentation/pages/introduction_footer.js +15 -53
  65. package/lib/module/modules/introduction/presentation/pages/introduction_footer.js.map +1 -1
  66. package/lib/module/modules/introduction/presentation/pages/introduction_page.js +22 -4
  67. package/lib/module/modules/introduction/presentation/pages/introduction_page.js.map +1 -1
  68. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.js +2 -2
  69. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.js.map +1 -1
  70. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.js +1 -1
  71. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.js.map +1 -1
  72. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js +2 -2
  73. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js.map +1 -1
  74. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js +14 -52
  75. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js.map +1 -1
  76. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js +11 -1
  77. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js.map +1 -1
  78. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js +3 -3
  79. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js.map +1 -1
  80. package/lib/module/modules/search/domain/models/fonctionnalite.js +51 -0
  81. package/lib/module/modules/search/domain/models/fonctionnalite.js.map +1 -1
  82. package/lib/module/modules/search/presentation/pages/search_btn_widget.js +136 -0
  83. package/lib/module/modules/search/presentation/pages/search_btn_widget.js.map +1 -0
  84. package/lib/module/modules/search/presentation/pages/search_fonctionnalites.js +21 -1
  85. package/lib/module/modules/search/presentation/pages/search_fonctionnalites.js.map +1 -1
  86. package/lib/module/modules/search/presentation/pages/search_page.js +266 -97
  87. package/lib/module/modules/search/presentation/pages/search_page.js.map +1 -1
  88. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page.js +5 -3
  89. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page.js.map +1 -1
  90. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.js +5 -6
  91. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.js.map +1 -1
  92. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js +3 -3
  93. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js.map +1 -1
  94. package/lib/module/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.js +1 -2
  95. package/lib/module/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.js.map +1 -1
  96. package/lib/module/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.js +17 -0
  97. package/lib/module/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.js.map +1 -1
  98. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.js +30 -23
  99. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.js.map +1 -1
  100. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js +6 -6
  101. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js.map +1 -1
  102. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js +6 -6
  103. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js.map +1 -1
  104. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page.js +16 -4
  105. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page.js.map +1 -1
  106. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.js +11 -9
  107. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.js.map +1 -1
  108. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js +9 -7
  109. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js.map +1 -1
  110. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.js +8 -10
  111. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.js.map +1 -1
  112. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js +127 -105
  113. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js.map +1 -1
  114. package/lib/module/modules/transactions/presentation/pages/transaction_search/transaction_search_page.js +9 -15
  115. package/lib/module/modules/transactions/presentation/pages/transaction_search/transaction_search_page.js.map +1 -1
  116. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.js +5 -11
  117. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.js.map +1 -1
  118. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.js +9 -9
  119. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.js.map +1 -1
  120. package/lib/module/shared/widgets/alias_widget.js +33 -12
  121. package/lib/module/shared/widgets/alias_widget.js.map +1 -1
  122. package/lib/module/shared/widgets/auth_code_field.js +89 -0
  123. package/lib/module/shared/widgets/auth_code_field.js.map +1 -0
  124. package/lib/module/shared/widgets/calendar_date_picker.js +21 -16
  125. package/lib/module/shared/widgets/calendar_date_picker.js.map +1 -1
  126. package/lib/module/shared/widgets/confirm_action_sheet_widget.js +20 -1
  127. package/lib/module/shared/widgets/confirm_action_sheet_widget.js.map +1 -1
  128. package/lib/module/shared/widgets/emoji_select_widget.js +34 -39
  129. package/lib/module/shared/widgets/emoji_select_widget.js.map +1 -1
  130. package/lib/module/shared/widgets/frequence_input_widget.js +18 -29
  131. package/lib/module/shared/widgets/frequence_input_widget.js.map +1 -1
  132. package/lib/module/shared/widgets/frequence_select_widget.js +233 -140
  133. package/lib/module/shared/widgets/frequence_select_widget.js.map +1 -1
  134. package/lib/module/shared/widgets/image_select_widget.js +4 -4
  135. package/lib/module/shared/widgets/image_select_widget.js.map +1 -1
  136. package/lib/module/shared/widgets/input_text.js +1 -1
  137. package/lib/module/shared/widgets/input_text.js.map +1 -1
  138. package/lib/module/shared/widgets/notification_dialog.js +3 -2
  139. package/lib/module/shared/widgets/notification_dialog.js.map +1 -1
  140. package/lib/module/shared/widgets/pin_entete.js +114 -0
  141. package/lib/module/shared/widgets/pin_entete.js.map +1 -0
  142. package/lib/module/shared/widgets/select_date_widget.js +74 -59
  143. package/lib/module/shared/widgets/select_date_widget.js.map +1 -1
  144. package/lib/module/shared/widgets/selection.js +21 -16
  145. package/lib/module/shared/widgets/selection.js.map +1 -1
  146. package/lib/typescript/src/l10n/app_localizations.d.ts +59 -11
  147. package/lib/typescript/src/l10n/app_localizations.d.ts.map +1 -1
  148. package/lib/typescript/src/l10n/app_localizations_en.d.ts.map +1 -1
  149. package/lib/typescript/src/l10n/app_localizations_fr.d.ts.map +1 -1
  150. package/lib/typescript/src/l10n/app_localizations_pt.d.ts.map +1 -1
  151. package/lib/typescript/src/modules/alias/domain/models/alias_revendication.d.ts.map +1 -1
  152. package/lib/typescript/src/modules/alias/infra/alias_output_local.d.ts +5 -0
  153. package/lib/typescript/src/modules/alias/infra/alias_output_local.d.ts.map +1 -1
  154. package/lib/typescript/src/modules/alias/infra/alias_output_repository.d.ts.map +1 -1
  155. package/lib/typescript/src/modules/alias/presentation/pages/alias_delete_btn_widget.d.ts.map +1 -1
  156. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_claim.d.ts.map +1 -1
  157. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_form.d.ts.map +1 -1
  158. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.d.ts +1 -1
  159. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.d.ts.map +1 -1
  160. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_options.d.ts +4 -1
  161. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_options.d.ts.map +1 -1
  162. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_otp.d.ts +9 -5
  163. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_otp.d.ts.map +1 -1
  164. package/lib/typescript/src/modules/categorie/domain/services/categorie_service.d.ts.map +1 -1
  165. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.d.ts +3 -0
  166. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.d.ts.map +1 -1
  167. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_form_pages.d.ts.map +1 -1
  168. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_icon.d.ts +9 -0
  169. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_icon.d.ts.map +1 -1
  170. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_liste_widget.d.ts +7 -2
  171. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_liste_widget.d.ts.map +1 -1
  172. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_page.d.ts.map +1 -1
  173. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_widget.d.ts +10 -2
  174. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_widget.d.ts.map +1 -1
  175. package/lib/typescript/src/modules/config/domain/models/config_keys.d.ts +3 -1
  176. package/lib/typescript/src/modules/config/domain/models/config_keys.d.ts.map +1 -1
  177. package/lib/typescript/src/modules/contacts/domain/contact_pi.d.ts +0 -2
  178. package/lib/typescript/src/modules/contacts/domain/contact_pi.d.ts.map +1 -1
  179. package/lib/typescript/src/modules/contacts/presentation/bloc/contact_bloc.d.ts +7 -0
  180. package/lib/typescript/src/modules/contacts/presentation/bloc/contact_bloc.d.ts.map +1 -1
  181. package/lib/typescript/src/modules/contacts/presentation/pages/contact_actions_sheet.d.ts +14 -0
  182. package/lib/typescript/src/modules/contacts/presentation/pages/contact_actions_sheet.d.ts.map +1 -0
  183. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_alias_widget.d.ts +4 -2
  184. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_alias_widget.d.ts.map +1 -1
  185. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_phone_widget.d.ts.map +1 -1
  186. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_widget_item.d.ts +6 -4
  187. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_widget_item.d.ts.map +1 -1
  188. package/lib/typescript/src/modules/contacts/presentation/pages/contact_section.d.ts +3 -1
  189. package/lib/typescript/src/modules/contacts/presentation/pages/contact_section.d.ts.map +1 -1
  190. package/lib/typescript/src/modules/contacts/presentation/pages/contact_select_page.d.ts.map +1 -1
  191. package/lib/typescript/src/modules/contacts/presentation/pages/create/contact_create_page.d.ts.map +1 -1
  192. package/lib/typescript/src/modules/home/presentation/pages/home_page.d.ts.map +1 -1
  193. package/lib/typescript/src/modules/introduction/presentation/pages/introduction.d.ts.map +1 -1
  194. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_footer.d.ts +5 -1
  195. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_footer.d.ts.map +1 -1
  196. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_page.d.ts.map +1 -1
  197. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts.d.ts.map +1 -1
  198. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts_actions.d.ts.map +1 -1
  199. package/lib/typescript/src/modules/search/domain/models/fonctionnalite.d.ts +20 -0
  200. package/lib/typescript/src/modules/search/domain/models/fonctionnalite.d.ts.map +1 -1
  201. package/lib/typescript/src/modules/search/presentation/pages/search_btn_widget.d.ts +11 -0
  202. package/lib/typescript/src/modules/search/presentation/pages/search_btn_widget.d.ts.map +1 -0
  203. package/lib/typescript/src/modules/search/presentation/pages/search_fonctionnalites.d.ts.map +1 -1
  204. package/lib/typescript/src/modules/search/presentation/pages/search_page.d.ts.map +1 -1
  205. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page.d.ts.map +1 -1
  206. package/lib/typescript/src/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.d.ts.map +1 -1
  207. package/lib/typescript/src/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.d.ts.map +1 -1
  208. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.d.ts +4 -1
  209. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.d.ts.map +1 -1
  210. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.d.ts +4 -0
  211. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.d.ts.map +1 -1
  212. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.d.ts.map +1 -1
  213. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.d.ts.map +1 -1
  214. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.d.ts.map +1 -1
  215. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_search/transaction_search_page.d.ts.map +1 -1
  216. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.d.ts.map +1 -1
  217. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.d.ts.map +1 -1
  218. package/lib/typescript/src/shared/widgets/alias_widget.d.ts +2 -2
  219. package/lib/typescript/src/shared/widgets/alias_widget.d.ts.map +1 -1
  220. package/lib/typescript/src/shared/widgets/auth_code_field.d.ts +17 -0
  221. package/lib/typescript/src/shared/widgets/auth_code_field.d.ts.map +1 -0
  222. package/lib/typescript/src/shared/widgets/calendar_date_picker.d.ts.map +1 -1
  223. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts +12 -1
  224. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts.map +1 -1
  225. package/lib/typescript/src/shared/widgets/emoji_select_widget.d.ts.map +1 -1
  226. package/lib/typescript/src/shared/widgets/frequence_input_widget.d.ts +6 -3
  227. package/lib/typescript/src/shared/widgets/frequence_input_widget.d.ts.map +1 -1
  228. package/lib/typescript/src/shared/widgets/frequence_select_widget.d.ts +23 -5
  229. package/lib/typescript/src/shared/widgets/frequence_select_widget.d.ts.map +1 -1
  230. package/lib/typescript/src/shared/widgets/image_select_widget.d.ts +1 -1
  231. package/lib/typescript/src/shared/widgets/input_text.d.ts +2 -0
  232. package/lib/typescript/src/shared/widgets/input_text.d.ts.map +1 -1
  233. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts +3 -1
  234. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts.map +1 -1
  235. package/lib/typescript/src/shared/widgets/pin_entete.d.ts +15 -0
  236. package/lib/typescript/src/shared/widgets/pin_entete.d.ts.map +1 -0
  237. package/lib/typescript/src/shared/widgets/select_date_widget.d.ts +4 -0
  238. package/lib/typescript/src/shared/widgets/select_date_widget.d.ts.map +1 -1
  239. package/lib/typescript/src/shared/widgets/selection.d.ts +11 -7
  240. package/lib/typescript/src/shared/widgets/selection.d.ts.map +1 -1
  241. package/package.json +1 -1
  242. package/src/l10n/app_localizations.ts +59 -11
  243. package/src/l10n/app_localizations_en.ts +32 -8
  244. package/src/l10n/app_localizations_fr.ts +38 -14
  245. package/src/l10n/app_localizations_pt.ts +31 -7
  246. package/src/modules/alias/domain/models/alias_revendication.ts +4 -2
  247. package/src/modules/alias/infra/alias_output_local.ts +11 -0
  248. package/src/modules/alias/infra/alias_output_repository.ts +9 -8
  249. package/src/modules/alias/presentation/pages/alias_delete_btn_widget.tsx +17 -24
  250. package/src/modules/alias/presentation/pages/alias_page_claim.tsx +76 -48
  251. package/src/modules/alias/presentation/pages/alias_page_create_mbno_form.tsx +113 -65
  252. package/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.tsx +34 -25
  253. package/src/modules/alias/presentation/pages/alias_page_create_options.tsx +29 -36
  254. package/src/modules/alias/presentation/pages/alias_page_otp.tsx +24 -88
  255. package/src/modules/categorie/domain/services/categorie_service.ts +2 -1
  256. package/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.tsx +38 -28
  257. package/src/modules/categorie/presentation/pages/categorie_form_pages.tsx +71 -41
  258. package/src/modules/categorie/presentation/pages/categorie_icon.tsx +26 -0
  259. package/src/modules/categorie/presentation/pages/categorie_liste_widget.tsx +45 -24
  260. package/src/modules/categorie/presentation/pages/categorie_select_page.tsx +10 -46
  261. package/src/modules/categorie/presentation/pages/categorie_select_widget.tsx +54 -13
  262. package/src/modules/config/domain/models/config_keys.ts +3 -0
  263. package/src/modules/contacts/domain/contact_pi.ts +3 -6
  264. package/src/modules/contacts/presentation/bloc/contact_bloc.ts +37 -20
  265. package/src/modules/contacts/presentation/pages/contact_actions_sheet.tsx +69 -0
  266. package/src/modules/contacts/presentation/pages/contact_list_alias_widget.tsx +26 -4
  267. package/src/modules/contacts/presentation/pages/contact_list_phone_widget.tsx +3 -0
  268. package/src/modules/contacts/presentation/pages/contact_list_widget_item.tsx +54 -65
  269. package/src/modules/contacts/presentation/pages/contact_section.tsx +13 -3
  270. package/src/modules/contacts/presentation/pages/contact_select_page.tsx +106 -74
  271. package/src/modules/contacts/presentation/pages/create/contact_create_page.tsx +86 -47
  272. package/src/modules/home/presentation/pages/home_page.tsx +2 -9
  273. package/src/modules/introduction/presentation/pages/introduction.tsx +8 -0
  274. package/src/modules/introduction/presentation/pages/introduction_footer.tsx +16 -36
  275. package/src/modules/introduction/presentation/pages/introduction_page.tsx +17 -5
  276. package/src/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.tsx +2 -2
  277. package/src/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.tsx +1 -1
  278. package/src/modules/profile/presentation/pages/profile_page_avatar.tsx +2 -2
  279. package/src/modules/profile/presentation/pages/profile_page_contacts.tsx +12 -19
  280. package/src/modules/profile/presentation/pages/profile_page_contacts_actions.tsx +10 -1
  281. package/src/modules/qrcode/presentation/pages/qrcode_alias_page_share.tsx +3 -3
  282. package/src/modules/search/domain/models/fonctionnalite.ts +56 -0
  283. package/src/modules/search/presentation/pages/search_btn_widget.tsx +91 -0
  284. package/src/modules/search/presentation/pages/search_fonctionnalites.ts +21 -1
  285. package/src/modules/search/presentation/pages/search_page.tsx +166 -57
  286. package/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page.tsx +4 -2
  287. package/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.tsx +5 -5
  288. package/src/modules/subscription/presentation/pages/subscription_menu_widget.tsx +3 -3
  289. package/src/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.ts +1 -2
  290. package/src/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.ts +17 -0
  291. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.tsx +26 -17
  292. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.tsx +9 -9
  293. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.tsx +9 -9
  294. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page.tsx +20 -2
  295. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.tsx +6 -8
  296. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.tsx +5 -5
  297. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.tsx +5 -7
  298. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.tsx +112 -103
  299. package/src/modules/transactions/presentation/pages/transaction_search/transaction_search_page.tsx +6 -10
  300. package/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.tsx +3 -6
  301. package/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.tsx +5 -5
  302. package/src/shared/widgets/alias_widget.tsx +45 -18
  303. package/src/shared/widgets/auth_code_field.tsx +89 -0
  304. package/src/shared/widgets/calendar_date_picker.tsx +12 -11
  305. package/src/shared/widgets/confirm_action_sheet_widget.tsx +19 -1
  306. package/src/shared/widgets/emoji_select_widget.tsx +31 -29
  307. package/src/shared/widgets/frequence_input_widget.tsx +18 -24
  308. package/src/shared/widgets/frequence_select_widget.tsx +237 -117
  309. package/src/shared/widgets/image_select_widget.tsx +4 -4
  310. package/src/shared/widgets/input_text.tsx +3 -0
  311. package/src/shared/widgets/notification_dialog.tsx +4 -1
  312. package/src/shared/widgets/pin_entete.tsx +74 -0
  313. package/src/shared/widgets/select_date_widget.tsx +66 -34
  314. package/src/shared/widgets/selection.tsx +23 -12
@@ -2,17 +2,15 @@ import { MaterialIcons } from '@expo/vector-icons';
2
2
  import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
3
3
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
4
 
5
- import { useBloc, useBlocBuilder, useBlocListener } from '../../../../core/bloc_react';
5
+ import { useBloc, useBlocListener } from '../../../../core/bloc_react';
6
6
  import { AppRouter, useAppRouter } from '../../../../core/router';
7
- import { Themer, useTheme } from '../../../../core/theme';
7
+ import { useTheme } from '../../../../core/theme';
8
8
  import { useAppLocalizations } from '../../../../l10n/localizations';
9
- import { Card } from '../../../../shared/material/card';
10
- import { Divider } from '../../../../shared/material/divider';
11
- import { Categorie } from '../../domain/models/categorie';
9
+ import type { Categorie } from '../../domain/models/categorie';
12
10
  import { CategorieBloc } from '../bloc/categorie_bloc';
13
- import { CategorieAddEvent, CategorieListEvent } from '../bloc/categorie_event';
11
+ import { CategorieListEvent } from '../bloc/categorie_event';
14
12
  import { CategorieCreationState, CategorieEditState, CategorieInitialState } from '../bloc/categorie_state';
15
- import { CategorieListeWidget } from './categorie_liste_widget';
13
+ import { CategorieSelectWidget } from './categorie_select_widget';
16
14
 
17
15
  /** Choix d'une catégorie : la catégorie choisie est retournée à l'écran appelant. */
18
16
  export function CategorieSelectPage() {
@@ -21,7 +19,6 @@ export function CategorieSelectPage() {
21
19
  const router = useAppRouter();
22
20
  const insets = useSafeAreaInsets();
23
21
  const categorieBloc = useBloc(CategorieBloc);
24
- const state = useBlocBuilder(categorieBloc);
25
22
 
26
23
  useBlocListener(
27
24
  categorieBloc,
@@ -54,39 +51,10 @@ export function CategorieSelectPage() {
54
51
  <MaterialIcons name="arrow-back" size={24} color={theme.colorScheme.onSurface} />
55
52
  </Pressable>
56
53
  </View>
54
+ {/* Titre */}
55
+ <Text style={[theme.textTheme.headlineLarge, styles.titre]}>{traductions.categorieSelectionUniqueTitle}</Text>
57
56
  <ScrollView contentContainerStyle={styles.content}>
58
- {/* Catégories personnalisées */}
59
- <Text style={theme.textTheme.headlineSmall}>{traductions.categorieCustomTitle}</Text>
60
- <View style={styles.gap14} />
61
- <Card>
62
- {/* Bouton ajouter */}
63
- <Pressable accessibilityRole="button" onPress={() => categorieBloc.add(new CategorieAddEvent())} style={styles.addRow}>
64
- <View style={[styles.addIcon, { backgroundColor: theme.colorScheme.surface }]}>
65
- <MaterialIcons name="add" size={24} color={theme.colorScheme.onSurface} />
66
- </View>
67
- <Text style={theme.textTheme.headlineSmall}>{traductions.categorieCustomAdd}</Text>
68
- </Pressable>
69
- {/* Catégories personnalisées */}
70
- {state.categories.length > 0 && (
71
- <>
72
- <View style={styles.divider}>
73
- <Divider color={Themer.neural01Color} />
74
- </View>
75
- <CategorieListeWidget
76
- key={state.categories.map((c) => c.id + c.label).join()}
77
- liste={state.categories}
78
- editable
79
- defaultSelectedCategories={[]}
80
- onSelectionChanged={onSelected}
81
- />
82
- </>
83
- )}
84
- </Card>
85
- <View style={styles.gap32} />
86
- {/* Catégories par défaut */}
87
- <Text style={theme.textTheme.headlineSmall}>{traductions.categorieDefaultTitle}</Text>
88
- <View style={styles.gap14} />
89
- <CategorieListeWidget liste={Categorie.defaultListe} defaultSelectedCategories={[]} onSelectionChanged={onSelected} />
57
+ <CategorieSelectWidget canAdd editable showTitles selectionUnique selectedCategories={[]} onSelectionChanged={onSelected} />
90
58
  </ScrollView>
91
59
  </View>
92
60
  );
@@ -96,10 +64,6 @@ const styles = StyleSheet.create({
96
64
  flex: { flex: 1 },
97
65
  backRow: { flexDirection: 'row' },
98
66
  back: { padding: 12 },
99
- content: { paddingHorizontal: 12, paddingTop: 12 },
100
- addRow: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 16, gap: 16 },
101
- addIcon: { width: 45, height: 45, borderRadius: 14, alignItems: 'center', justifyContent: 'center' },
102
- divider: { paddingHorizontal: 16 },
103
- gap14: { height: 14 },
104
- gap32: { height: 32 },
67
+ titre: { paddingHorizontal: 20, paddingBottom: 16 },
68
+ content: { paddingHorizontal: 16, paddingBottom: 20 },
105
69
  });
@@ -1,37 +1,74 @@
1
- import { StyleSheet, View } from 'react-native';
1
+ import { StyleSheet, Text, View } from 'react-native';
2
2
 
3
3
  import { useBloc, useBlocBuilder } from '../../../../core/bloc_react';
4
+ import { Themer, useTheme } from '../../../../core/theme';
5
+ import { useAppLocalizations } from '../../../../l10n/localizations';
6
+ import { SelectionOption } from '../../../../shared/widgets/selection';
4
7
  import { Categorie } from '../../domain/models/categorie';
5
8
  import { CategorieBloc } from '../bloc/categorie_bloc';
9
+ import { CategorieAddEvent } from '../bloc/categorie_event';
6
10
  import { CategorieListeWidget } from './categorie_liste_widget';
7
11
 
8
- /** Sélection de catégories (personnalisées puis prédéfinies), utilisée par les filtres. */
12
+ /**
13
+ * Catégories personnalisées (avec ajout et modification si demandé) puis
14
+ * catégories par défaut ; utilisée par la page de choix et les filtres.
15
+ */
9
16
  export function CategorieSelectWidget({
10
17
  onSelectionChanged,
11
18
  selectedCategories,
19
+ editable = false,
20
+ canAdd = false,
21
+ showTitles = false,
22
+ selectionUnique = false,
12
23
  }: {
13
24
  onSelectionChanged: (categorie: Categorie, checked: boolean) => void;
14
25
  selectedCategories: string[];
26
+ editable?: boolean;
27
+ canAdd?: boolean;
28
+ showTitles?: boolean;
29
+ /** Toucher une catégorie la choisit, sans rond coché */
30
+ selectionUnique?: boolean;
15
31
  }) {
32
+ const traductions = useAppLocalizations();
33
+ const theme = useTheme();
16
34
  const categorieBloc = useBloc(CategorieBloc);
17
35
  const state = useBlocBuilder(categorieBloc);
36
+ const personnalisees = canAdd || state.categories.length > 0;
37
+
38
+ const titre = (texte: string) => (
39
+ <Text style={[theme.textTheme.displayMedium, styles.titre, { color: Themer.neural03Color }]}>{texte}</Text>
40
+ );
41
+
18
42
  return (
19
43
  <View>
20
- {/* Catégories personnalisées (pas de carte vide s'il n'y en a pas) */}
21
- {state.categories.length > 0 && (
22
- <>
23
- <CategorieListeWidget
24
- liste={state.categories}
25
- editable={false}
26
- defaultSelectedCategories={selectedCategories}
27
- onSelectionChanged={onSelectionChanged}
44
+ {/* Catégories personnalisées */}
45
+ {showTitles && personnalisees && titre(traductions.categorieCustomTitle)}
46
+ {canAdd && (
47
+ <View style={styles.ajout}>
48
+ <SelectionOption
49
+ icone="add"
50
+ titre={traductions.categorieCustomAdd}
51
+ onPress={() => categorieBloc.add(new CategorieAddEvent())}
28
52
  />
29
- <View style={styles.gap16} />
30
- </>
53
+ </View>
54
+ )}
55
+ {state.categories.length > 0 && (
56
+ <CategorieListeWidget
57
+ // Nouvelle liste quand une catégorie est ajoutée ou renommée
58
+ key={state.categories.map((c) => c.id + c.label).join()}
59
+ liste={state.categories}
60
+ editable={editable}
61
+ selectionUnique={selectionUnique}
62
+ defaultSelectedCategories={selectedCategories}
63
+ onSelectionChanged={onSelectionChanged}
64
+ />
31
65
  )}
66
+ {personnalisees && <View style={styles.gap24} />}
32
67
  {/* Catégories par défaut */}
68
+ {showTitles && titre(traductions.categorieDefaultTitle)}
33
69
  <CategorieListeWidget
34
70
  liste={Categorie.defaultListe}
71
+ selectionUnique={selectionUnique}
35
72
  defaultSelectedCategories={selectedCategories}
36
73
  onSelectionChanged={onSelectionChanged}
37
74
  />
@@ -39,4 +76,8 @@ export function CategorieSelectWidget({
39
76
  );
40
77
  }
41
78
 
42
- const styles = StyleSheet.create({ gap16: { height: 16 } });
79
+ const styles = StyleSheet.create({
80
+ titre: { fontWeight: '700', paddingHorizontal: 4, paddingBottom: 10 },
81
+ ajout: { marginBottom: 10 },
82
+ gap24: { height: 24 },
83
+ });
@@ -38,6 +38,9 @@ export enum ConfigKey {
38
38
 
39
39
  /** L'utilisateur a passé l'introduction du module économie */
40
40
  economieIntroductionPassed = 'ECONOMIE_INTRODUCTION_PASSED',
41
+
42
+ /** Nombre d'affichages de l'accueil où la recherche a pulsé (3 : terminé) */
43
+ searchHintCount = 'SEARCH_HINT_COUNT',
41
44
  }
42
45
 
43
46
  /** Toutes les clés, dans l'ordre de déclaration (≈ `ConfigKey.values`). */
@@ -1,9 +1,6 @@
1
- import { Logger } from '../../../core/logger';
2
1
  import { getAliasValue, type PhoneContact } from './phone_contact';
3
2
 
4
3
  export class ContactPI {
5
- static readonly logger = new Logger();
6
-
7
4
  name: string;
8
5
  phoneNumber: string;
9
6
  alias?: string | null;
@@ -25,8 +22,8 @@ export class ContactPI {
25
22
 
26
23
  /** Récupère la valeur de l'alias */
27
24
  static getAlias(contact: PhoneContact): string | null {
28
- const alias = getAliasValue(contact);
29
- if (alias == null) ContactPI.logger.i(`No alias found for contact ${contact.displayName}`);
30
- return alias;
25
+ // Pas de log : la plupart des contacts n'ont pas d'alias, et cette
26
+ // fonction est appelée pour chaque contact affiché
27
+ return getAliasValue(contact);
31
28
  }
32
29
  }
@@ -105,16 +105,19 @@ export class ContactBloc extends Bloc<ContactEvent, ContactState> {
105
105
  /** Contacts dont le nom, l'alias ou un numéro contient [keyword] */
106
106
  private filter(contacts: PhoneContact[], keyword: string): PhoneContact[] {
107
107
  const lower = keyword.toLowerCase();
108
- return contacts.filter((contact) => {
109
- const alias = getAliasValue(contact);
110
- return (
111
- contact.displayName.toLowerCase().includes(lower) ||
112
- (alias != null && alias.toLowerCase().includes(lower)) ||
113
- contact.phones.some(
114
- (phone) => phone.number.trim().replace(/ /g, '').includes(lower) || normalizedNumber(phone).includes(lower),
115
- )
116
- );
117
- });
108
+ return contacts.filter((contact) => this.correspond(contact, lower));
109
+ }
110
+
111
+ /** [contact] correspond-il à [keyword] (en minuscules) : nom, alias ou numéro ? */
112
+ correspond(contact: PhoneContact, keyword: string): boolean {
113
+ const alias = getAliasValue(contact);
114
+ return (
115
+ contact.displayName.toLowerCase().includes(keyword) ||
116
+ (alias != null && alias.toLowerCase().includes(keyword)) ||
117
+ contact.phones.some(
118
+ (phone) => phone.number.trim().replace(/ /g, '').includes(keyword) || normalizedNumber(phone).includes(keyword),
119
+ )
120
+ );
118
121
  }
119
122
 
120
123
  /** Vérifier si un alias existe dans la liste des contacts */
@@ -133,19 +136,33 @@ export class ContactBloc extends Bloc<ContactEvent, ContactState> {
133
136
  // (AliasWidget, liste des transactions...).
134
137
  private contactsByAliasSource: PhoneContact[] | null = null;
135
138
  private contactsByAliasCache = new Map<string, PhoneContact>();
139
+ private contactsPiCache: PhoneContact[] = [];
136
140
 
137
141
  private get contactsByAlias(): Map<string, PhoneContact> {
142
+ this.indexer();
143
+ return this.contactsByAliasCache;
144
+ }
145
+
146
+ /** Contacts qui ont un alias PI-SPI, dans l'ordre de la liste ; calculé avec l'index, une fois par liste */
147
+ get contactsPi(): PhoneContact[] {
148
+ this.indexer();
149
+ return this.contactsPiCache;
150
+ }
151
+
152
+ private indexer(): void {
138
153
  const contacts = this.state.contactsAll;
139
- if (contacts !== this.contactsByAliasSource) {
140
- this.contactsByAliasSource = contacts;
141
- const index = new Map<string, PhoneContact>();
142
- for (const contact of contacts ?? []) {
143
- const alias = getAliasValue(contact);
144
- // Premier contact trouvé pour un alias
145
- if (alias != null && !index.has(alias)) index.set(alias, contact);
146
- }
147
- this.contactsByAliasCache = index;
154
+ if (contacts === this.contactsByAliasSource) return;
155
+ this.contactsByAliasSource = contacts;
156
+ const index = new Map<string, PhoneContact>();
157
+ const pis: PhoneContact[] = [];
158
+ for (const contact of contacts ?? []) {
159
+ const alias = getAliasValue(contact);
160
+ if (alias == null) continue;
161
+ pis.push(contact);
162
+ // Premier contact trouvé pour un alias
163
+ if (!index.has(alias)) index.set(alias, contact);
148
164
  }
149
- return this.contactsByAliasCache;
165
+ this.contactsByAliasCache = index;
166
+ this.contactsPiCache = pis;
150
167
  }
151
168
  }
@@ -0,0 +1,69 @@
1
+ import { Platform, ScrollView, Share, StyleSheet, Text, View } from 'react-native';
2
+
3
+ import { AppRouter, useAppRouter, type SdkRouter } from '../../../../core/router';
4
+ import { Themer, useTheme } from '../../../../core/theme';
5
+ import { useAppLocalizations } from '../../../../l10n/localizations';
6
+ import { showModalBottomSheet } from '../../../../shared/material/overlays';
7
+ import { CircleAvatarWidget } from '../../../../shared/widgets/circle_avatar_widget';
8
+ import { ClipboardWidget } from '../../../../shared/widgets/clipboard_widget';
9
+ import { SelectionOption, SelectionSheet } from '../../../../shared/widgets/selection';
10
+
11
+ /** Ouvre la feuille d'actions d'un contact PI : copier ou partager son alias. */
12
+ export function ouvrirActionsContact(router: SdkRouter, props: { nom: string; alias: string; photo?: string | null }) {
13
+ void showModalBottomSheet(router, { builder: () => <ContactActionsSheet {...props} /> });
14
+ }
15
+
16
+ /** Feuille d'actions sur un contact PI : avatar, nom et alias, puis copier ou partager l'alias. */
17
+ export function ContactActionsSheet({ nom, alias, photo }: { nom: string; alias: string; photo?: string | null }) {
18
+ const traductions = useAppLocalizations();
19
+ const theme = useTheme();
20
+ const router = useAppRouter();
21
+ return (
22
+ <SelectionSheet
23
+ contenu={
24
+ <ScrollView bounces={false} contentContainerStyle={styles.content}>
25
+ {/* Contact : avatar, nom et alias */}
26
+ <View style={styles.entete}>
27
+ <CircleAvatarWidget nom={nom} photo={photo} rounded radius={52} />
28
+ <View style={styles.textes}>
29
+ <Text numberOfLines={2} style={theme.textTheme.headlineSmall}>
30
+ {nom}
31
+ </Text>
32
+ <View style={styles.gap2} />
33
+ <Text style={[theme.textTheme.displayMedium, { color: Themer.neural03Color }]}>{alias}</Text>
34
+ </View>
35
+ </View>
36
+ <View style={styles.gap20} />
37
+ {/* Copier l'alias */}
38
+ <SelectionOption
39
+ icone="content-copy"
40
+ titre={traductions.contactActionsCopy}
41
+ onPress={() => {
42
+ void ClipboardWidget.setData(alias);
43
+ AppRouter.pop(router);
44
+ }}
45
+ />
46
+ <View style={styles.gap10} />
47
+ {/* Partager l'alias */}
48
+ <SelectionOption
49
+ icone={Platform.OS === 'ios' ? 'ios-share' : 'share'}
50
+ titre={traductions.contactActionsShare}
51
+ onPress={() => {
52
+ AppRouter.pop(router);
53
+ void Share.share({ title: traductions.qrcodePagePartageAliasMessage(nom), message: alias });
54
+ }}
55
+ />
56
+ </ScrollView>
57
+ }
58
+ />
59
+ );
60
+ }
61
+
62
+ const styles = StyleSheet.create({
63
+ content: { paddingHorizontal: 20, paddingTop: 4, paddingBottom: 16 },
64
+ entete: { flexDirection: 'row', alignItems: 'center' },
65
+ textes: { flex: 1, marginLeft: 14 },
66
+ gap2: { height: 2 },
67
+ gap10: { height: 10 },
68
+ gap20: { height: 20 },
69
+ });
@@ -7,7 +7,8 @@ import { Themer, useTheme } from '../../../../core/theme';
7
7
  import { useAppLocalizations } from '../../../../l10n/localizations';
8
8
  import { showModalBottomSheet } from '../../../../shared/material/overlays';
9
9
  import { NotificationDialog, NotificationType } from '../../../../shared/widgets/notification_dialog';
10
- import type { ContactPI } from '../../domain/contact_pi';
10
+ import { ContactList } from '../../domain/contact_list';
11
+ import { ContactPI } from '../../domain/contact_pi';
11
12
  import { ContactBloc } from '../bloc/contact_bloc';
12
13
  import { ContactListEvent, ContactMoreEvent } from '../bloc/contact_event';
13
14
  import { ContactListState } from '../bloc/contact_state';
@@ -15,6 +16,7 @@ import { groupContacts } from './contact_groups';
15
16
  import type { ContactSelectHandler } from './contact_list_widget_item';
16
17
  import { ContactSection } from './contact_section';
17
18
  import { PaginatedScrollView } from '../../../../shared/widgets/paginated_scroll_view';
19
+ import { PaginationLoaderWidget } from '../../../../shared/widgets/pagination_loader_widget';
18
20
 
19
21
  /**
20
22
  * Liste des contacts du téléphone, regroupés par lettre (un contact par
@@ -30,6 +32,7 @@ export function ContactAliasListWidget({
30
32
  expanded = false,
31
33
  smallItem = false,
32
34
  searchKeyword,
35
+ showActions = true,
33
36
  }: {
34
37
  onSelect?: ContactSelectHandler;
35
38
  selectedContacts?: ContactPI[] | null;
@@ -38,6 +41,8 @@ export function ContactAliasListWidget({
38
41
  expanded?: boolean;
39
42
  smallItem?: boolean;
40
43
  searchKeyword?: string | null;
44
+ /** Bouton « ⋯ » vers les actions sur l'alias de chaque contact */
45
+ showActions?: boolean;
41
46
  }) {
42
47
  const traductions = useAppLocalizations();
43
48
  const theme = useTheme();
@@ -76,7 +81,15 @@ export function ContactAliasListWidget({
76
81
 
77
82
  const contacts = state.contacts.data;
78
83
  const next = state.contacts.meta.next as number | undefined;
79
- if (contacts.length === 0) return null;
84
+ // Contacts PI-SPI en tête (tous, filtrés par la recherche), puis les
85
+ // autres contacts chargés, par lettre
86
+ const motCle = (searchKeyword ?? '').trim().toLowerCase();
87
+ const pis = motCle.length === 0 ? contactBloc.contactsPi : contactBloc.contactsPi.filter((c) => contactBloc.correspond(c, motCle));
88
+ if (contacts.length === 0 && pis.length === 0) return null;
89
+ const groupes = [
90
+ ...(pis.length > 0 ? [new ContactList(traductions.contactSectionPi, pis)] : []),
91
+ ...groupContacts(contacts.filter((contact) => ContactPI.getAlias(contact) == null)),
92
+ ];
80
93
 
81
94
  const onEndReached = () => {
82
95
  if (next != null) contactBloc.add(new ContactMoreEvent(contacts, next, searchKeyword));
@@ -87,9 +100,18 @@ export function ContactAliasListWidget({
87
100
  onEndReached={onEndReached}
88
101
  style={expanded ? styles.flex : { minHeight: 100, maxHeight: maxHeight ?? window.height * 0.65, flexGrow: 0 }}
89
102
  >
90
- {groupContacts(contacts).map((group) => (
91
- <ContactSection key={group.header} group={group} onSelect={onSelect} selectedContacts={selectedContacts} smallItem={smallItem} />
103
+ {groupes.map((group) => (
104
+ <ContactSection
105
+ key={group.header}
106
+ group={group}
107
+ onSelect={onSelect}
108
+ selectedContacts={selectedContacts}
109
+ smallItem={smallItem}
110
+ showActions={showActions}
111
+ />
92
112
  ))}
113
+ {/* Loader tant qu'il reste des contacts à charger */}
114
+ {next != null && <PaginationLoaderWidget />}
93
115
  </PaginatedScrollView>
94
116
  );
95
117
 
@@ -8,6 +8,7 @@ import { groupContactPhones, groupContacts } from './contact_groups';
8
8
  import type { ContactSelectHandler } from './contact_list_widget_item';
9
9
  import { ContactSection } from './contact_section';
10
10
  import { PaginatedScrollView } from '../../../../shared/widgets/paginated_scroll_view';
11
+ import { PaginationLoaderWidget } from '../../../../shared/widgets/pagination_loader_widget';
11
12
 
12
13
  /**
13
14
  * Liste des numéros de téléphone des contacts, regroupés par lettre : un
@@ -45,6 +46,8 @@ export function ContactPhoneListWidget({
45
46
  {(enableAlias ? groupContacts(contacts) : groupContactPhones(contacts)).map((group) => (
46
47
  <ContactSection key={group.header} group={group} onSelect={onSelect} selectedContacts={selectedContacts} smallItem={smallItem} />
47
48
  ))}
49
+ {/* Loader tant qu'il reste des contacts à charger */}
50
+ {next != null && <PaginationLoaderWidget />}
48
51
  </PaginatedScrollView>
49
52
  );
50
53
  }
@@ -1,24 +1,25 @@
1
1
  import { MaterialIcons } from '@expo/vector-icons';
2
2
  import { Image } from 'expo-image';
3
- import { Platform, Pressable, Share, StyleSheet, Text, View, type GestureResponderEvent } from 'react-native';
3
+ import { Pressable, StyleSheet, Text, View } from 'react-native';
4
4
 
5
5
  import { Images } from '../../../../core/assets';
6
6
  import { useAppRouter } from '../../../../core/router';
7
7
  import { Themer, useTheme } from '../../../../core/theme';
8
8
  import { useAppLocalizations } from '../../../../l10n/localizations';
9
- import { showPopupMenu } from '../../../../shared/material/popup_menu';
9
+ import { withAlpha } from '../../../../shared/utils/color';
10
10
  import { CircleAvatarWidget } from '../../../../shared/widgets/circle_avatar_widget';
11
- import { ClipboardWidget } from '../../../../shared/widgets/clipboard_widget';
12
11
  import { ContactPI } from '../../domain/contact_pi';
13
12
  import type { PhoneContact } from '../../domain/phone_contact';
13
+ import { ouvrirActionsContact } from './contact_actions_sheet';
14
14
 
15
15
  export type ContactSelectHandler = (contact: PhoneContact, alias: string | null, isSelected: boolean | null) => void;
16
16
 
17
17
  /**
18
18
  * Un contact du téléphone : avatar (avec le badge π s'il a un alias
19
- * PI-SPI), nom, et alias ou à défaut premier numéro. Avec [showCheckbox],
20
- * une case à cocher précède la ligne ; sinon, un appui long sur un contact
21
- * ayant un alias ouvre un menu pour copier ou partager cet alias.
19
+ * PI-SPI), nom, et alias ou à défaut premier numéro. Avec [showCheckbox]
20
+ * (sélection multiple), la ligne choisie est surlignée avec un rond coché à
21
+ * droite ; sinon, un bouton « ⋯ » (et l'appui long) ouvre les actions sur
22
+ * l'alias (copier, partager) si [showActions].
22
23
  */
23
24
  export function ContactListWidgetItem({
24
25
  contact,
@@ -26,44 +27,43 @@ export function ContactListWidgetItem({
26
27
  showCheckbox = false,
27
28
  isSelected = false,
28
29
  smallItem = false,
30
+ showActions = true,
29
31
  }: {
30
32
  contact: PhoneContact;
31
33
  onSelect?: ContactSelectHandler;
32
34
  showCheckbox?: boolean;
33
35
  isSelected?: boolean;
34
36
  smallItem?: boolean;
37
+ showActions?: boolean;
35
38
  }) {
36
39
  const theme = useTheme();
37
40
  const router = useAppRouter();
38
41
  const traductions = useAppLocalizations();
42
+ const primaire = theme.colorScheme.primary;
39
43
  const alias = ContactPI.getAlias(contact);
40
- const avatarSize = smallItem ? 35 : 45;
44
+ const choisi = showCheckbox && isSelected;
45
+ const actions = !showCheckbox && showActions && alias != null;
46
+ const avatarSize = smallItem ? 36 : 44;
41
47
  const badgeSize = smallItem ? 14 : 18;
48
+ const ouvrirActions = () =>
49
+ ouvrirActionsContact(router, { nom: contact.displayName, alias: alias!, photo: contact.photo });
42
50
 
43
- const showLightMenu = (event: GestureResponderEvent) => {
44
- void showPopupMenu(router, {
45
- x: event.nativeEvent.pageX,
46
- y: event.nativeEvent.pageY,
47
- items: [
48
- {
49
- icon: 'content-copy',
50
- label: traductions.profileContactPageaActionCopy,
51
- onTap: () => void ClipboardWidget.setData(alias!),
52
- },
53
- {
54
- icon: Platform.OS === 'ios' ? 'ios-share' : 'share',
55
- label: traductions.profileContactPageaActionShare,
56
- onTap: () =>
57
- void Share.share({ title: traductions.qrcodePagePartageAliasMessage(contact.displayName), message: alias! }),
58
- },
59
- ],
60
- });
61
- };
62
-
63
- const tile = (
64
- <View style={[styles.tile, { minHeight: smallItem ? 48 : 64 }]}>
51
+ return (
52
+ <Pressable
53
+ accessibilityRole={showCheckbox ? 'checkbox' : 'button'}
54
+ accessibilityState={showCheckbox ? { checked: isSelected } : undefined}
55
+ // Sélection multiple : bascule ; sinon : choix direct
56
+ onPress={() => onSelect?.(contact, alias, showCheckbox ? !isSelected : null)}
57
+ // Copier ou partager l'alias d'un contact PI
58
+ onLongPress={actions ? ouvrirActions : undefined}
59
+ style={({ pressed }) => [
60
+ styles.row,
61
+ { paddingVertical: smallItem ? 6 : 8 },
62
+ { backgroundColor: choisi ? withAlpha(primaire, 0.08) : pressed ? theme.colorScheme.secondary : 'transparent' },
63
+ ]}
64
+ >
65
65
  {/* Avatar */}
66
- <View>
66
+ <View style={{ width: avatarSize, height: avatarSize }}>
67
67
  <CircleAvatarWidget nom={contact.displayName} photo={contact.photo} rounded radius={avatarSize} />
68
68
  {alias != null && (
69
69
  <View
@@ -84,53 +84,42 @@ export function ContactListWidgetItem({
84
84
  </View>
85
85
  <View style={styles.texts}>
86
86
  {/* Contact name */}
87
- <Text numberOfLines={1} style={smallItem ? theme.textTheme.displayMedium : theme.textTheme.headlineSmall}>
87
+ <Text
88
+ numberOfLines={1}
89
+ style={[smallItem ? theme.textTheme.displayMedium : theme.textTheme.displayLarge, { fontWeight: choisi ? '700' : '500' }]}
90
+ >
88
91
  {contact.displayName}
89
92
  </Text>
90
93
  {/* Phone number or alias */}
91
- <Text
92
- style={smallItem ? theme.textTheme.displaySmall : [theme.textTheme.displaySmall, { color: Themer.neural04Color }]}
93
- >
94
+ <Text numberOfLines={1} style={[theme.textTheme.displaySmall, styles.detail, { color: Themer.neural03Color }]}>
94
95
  {alias ?? contact.phones[0]?.number ?? ''}
95
96
  </Text>
96
97
  </View>
97
- </View>
98
- );
99
-
100
- if (showCheckbox) {
101
- return (
102
- <Pressable
103
- accessibilityRole="checkbox"
104
- accessibilityState={{ checked: isSelected }}
105
- onPress={() => onSelect?.(contact, alias, !isSelected)}
106
- style={styles.row}
107
- >
98
+ {/* Actions sur l'alias : copier, partager */}
99
+ {actions && (
100
+ <Pressable accessibilityRole="button" accessibilityLabel={traductions.contactActionsTooltip} hitSlop={8} onPress={ouvrirActions} style={styles.plus}>
101
+ <MaterialIcons name="more-horiz" size={22} color={Themer.neural03Color} />
102
+ </Pressable>
103
+ )}
104
+ {/* Sélection multiple : rond coché */}
105
+ {showCheckbox && (
108
106
  <MaterialIcons
109
- name={isSelected ? 'check-box' : 'check-box-outline-blank'}
110
- size={24}
111
- color={isSelected ? theme.colorScheme.primary : Themer.neural02Color}
107
+ name={choisi ? 'check-circle' : 'radio-button-unchecked'}
108
+ size={22}
109
+ color={choisi ? primaire : Themer.neural03Color}
110
+ style={styles.coche}
112
111
  />
113
- <View style={styles.gap16} />
114
- <View style={styles.flex}>{tile}</View>
115
- </Pressable>
116
- );
117
- }
118
-
119
- return (
120
- <Pressable
121
- onPress={() => onSelect?.(contact, alias, null)}
122
- onLongPress={alias != null ? showLightMenu : undefined}
123
- >
124
- {tile}
112
+ )}
125
113
  </Pressable>
126
114
  );
127
115
  }
128
116
 
129
117
  const styles = StyleSheet.create({
130
118
  flex: { flex: 1 },
131
- row: { flexDirection: 'row', alignItems: 'center' },
132
- tile: { flexDirection: 'row', alignItems: 'center', paddingVertical: 8 },
133
- texts: { flex: 1, marginLeft: 16 },
134
- badge: { position: 'absolute', right: 0, bottom: 0, borderWidth: 2, overflow: 'hidden' },
135
- gap16: { width: 16 },
119
+ row: { flexDirection: 'row', alignItems: 'center', marginVertical: 1, paddingHorizontal: 8, borderRadius: 14 },
120
+ texts: { flex: 1, marginLeft: 14 },
121
+ detail: { marginTop: 2 },
122
+ badge: { position: 'absolute', right: -2, bottom: -2, borderWidth: 2, overflow: 'hidden' },
123
+ plus: { padding: 6 },
124
+ coche: { marginLeft: 8, marginRight: 4 },
136
125
  });