From 9b3a0b4aa08343d0abe11640ee604bbada3e57c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Wed, 10 Jan 2024 16:50:37 +0100 Subject: [PATCH] [FIX] mail: no crash on edit message in mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, editing a message in message in a conversation and then pressing on the paper plane icon was throwing the following error: ``` TypeError: null is not an object (evaluating 'thread.model') @_sendMessage ``` This happens because this button was in "send" message mode rather than in edit mode. Since we cannot post a message while editing a message, the crash happens because composer is not related to thread but the message. This button is not visible in desktop mode, and user should use suggested keyboard shortcuts or click on links to either save edit or discard it. In mobile, these interactions are not intuitive. This commit fixes the issue by keeping the paper-plane button while editing in mobile but it acts as "save". The labels to save/discard was not appropriate in mobile, so it has been turned to a simple button to discard editing. opw-3670482 closes odoo/odoo#148918 Signed-off-by: Alexandre Kühn (aku) --- addons/mail/i18n/mail.pot | 278 +++--------------- .../mail/static/src/core/common/composer.js | 65 +++- .../static/tests/message/message_tests.js | 33 +++ 3 files changed, 124 insertions(+), 252 deletions(-) diff --git a/addons/mail/i18n/mail.pot b/addons/mail/i18n/mail.pot index 8065f167c37..89ae66751d7 100644 --- a/addons/mail/i18n/mail.pot +++ b/addons/mail/i18n/mail.pot @@ -105,6 +105,37 @@ msgid "" "%(bold_start)s/command%(bold_end)s to execute a command." msgstr "" +#. module: mail +#. odoo-javascript +#: code:addons/mail/static/src/core/common/composer.js:0 +#, python-format +msgid "" +"%(open_button)s%(icon)s%(open_em)sDiscard " +"editing%(close_em)s%(close_button)s" +msgstr "" + +#. module: mail +#. odoo-javascript +#: code:addons/mail/static/src/core/common/composer.js:0 +#, python-format +msgid "" +"%(open_samp)sEscape%(close_samp)s %(open_em)sto " +"%(open_cancel)scancel%(close_cancel)s%(close_em)s, %(open_samp)sCTRL-" +"Enter%(close_samp)s %(open_em)sto " +"%(open_save)ssave%(close_save)s%(close_em)s" +msgstr "" + +#. module: mail +#. odoo-javascript +#: code:addons/mail/static/src/core/common/composer.js:0 +#, python-format +msgid "" +"%(open_samp)sEscape%(close_samp)s %(open_em)sto " +"%(open_cancel)scancel%(close_cancel)s%(close_em)s, " +"%(open_samp)sEnter%(close_samp)s %(open_em)sto " +"%(open_save)ssave%(close_save)s%(close_em)s" +msgstr "" + #. module: mail #. odoo-javascript #: code:addons/mail/static/src/discuss/core/web/discuss_core_web_service.js:0 @@ -337,16 +368,6 @@ msgstr "" msgid "" msgstr "" -#. module: mail -#. odoo-javascript -#: code:addons/mail/static/src/core/common/composer.js:0 -#, python-format -msgid "" -"%(cancel_keybind)s to cancel, %(save_keybind)s to " -"save" -msgstr "" - #. module: mail #. odoo-javascript #: code:addons/mail/static/src/core/common/composer.js:0 @@ -880,53 +901,9 @@ msgid "Advanced Options" msgstr "" #. module: mail -#: model:ir.model.fields.selection,name:mail.selection__account_journal__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__account_move__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__account_payment__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__crm_lead__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__event_booth__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__event_event__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__event_registration__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__event_sponsor__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__event_track__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_contract__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_services__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_applicant__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_contract__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_employee__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_expense__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_expense_sheet__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_leave__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__hr_leave_allocation__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__lunch_supplier__activity_exception_decoration__warning #: model:ir.model.fields.selection,name:mail.selection__mail_activity_mixin__activity_exception_decoration__warning #: model:ir.model.fields.selection,name:mail.selection__mail_activity_type__decoration_type__warning -#: model:ir.model.fields.selection,name:mail.selection__mailing_mailing__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__maintenance_equipment__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__maintenance_request__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__mrp_production__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__mrp_unbuild__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__pos_session__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__product_pricelist__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__product_product__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__product_template__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__project_project__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__project_task__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__project_update__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__purchase_order__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__purchase_requisition__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__repair_order__activity_exception_decoration__warning #: model:ir.model.fields.selection,name:mail.selection__res_partner__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__res_partner_bank__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__sale_order__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__slide_channel__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__stock_landed_cost__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__stock_lot__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__stock_picking__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__stock_picking_batch__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__survey_survey__activity_exception_decoration__warning -#: model:ir.model.fields.selection,name:mail.selection__survey_user_input__activity_exception_decoration__warning msgid "Alert" msgstr "" @@ -2807,7 +2784,6 @@ msgstr "" msgid "Dismiss" msgstr "" - #. module: mail #: model:ir.model.fields,field_description:mail.field_discuss_channel__display_name #: model:ir.model.fields,field_description:mail.field_discuss_channel_member__display_name @@ -3354,53 +3330,9 @@ msgstr "" #. odoo-javascript #: code:addons/mail/static/src/core/common/notification_model.js:0 #: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__error -#: model:ir.model.fields.selection,name:mail.selection__account_journal__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__account_move__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__account_payment__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__crm_lead__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__event_booth__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__event_event__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__event_registration__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__event_sponsor__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__event_track__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_contract__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_services__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_applicant__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_contract__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_employee__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_expense__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_expense_sheet__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_leave__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__hr_leave_allocation__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__lunch_supplier__activity_exception_decoration__danger #: model:ir.model.fields.selection,name:mail.selection__mail_activity_mixin__activity_exception_decoration__danger #: model:ir.model.fields.selection,name:mail.selection__mail_activity_type__decoration_type__danger -#: model:ir.model.fields.selection,name:mail.selection__mailing_mailing__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__maintenance_equipment__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__maintenance_request__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__mrp_production__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__mrp_unbuild__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__pos_session__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__product_pricelist__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__product_product__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__product_template__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__project_project__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__project_task__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__project_update__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__purchase_order__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__purchase_requisition__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__repair_order__activity_exception_decoration__danger #: model:ir.model.fields.selection,name:mail.selection__res_partner__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__res_partner_bank__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__sale_order__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__slide_channel__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__stock_landed_cost__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__stock_lot__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__stock_picking__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__stock_picking_batch__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__survey_survey__activity_exception_decoration__danger -#: model:ir.model.fields.selection,name:mail.selection__survey_user_input__activity_exception_decoration__danger #, python-format msgid "Error" msgstr "" @@ -5246,7 +5178,7 @@ msgstr "" #. odoo-javascript #: code:addons/mail/static/src/discuss/core/public/welcome_page.js:0 #, python-format -msgid "Logged in as" +msgid "Logged in as %s" msgstr "" #. module: mail @@ -6128,6 +6060,13 @@ msgstr "" msgid "No messages found" msgstr "" +#. module: mail +#. odoo-javascript +#: code:addons/mail/static/src/core/web/chatter.js:0 +#, python-format +msgid "No recipient" +msgstr "" + #. module: mail #. odoo-python #: code:addons/mail/wizard/mail_compose_message.py:0 @@ -6685,53 +6624,9 @@ msgstr "" #. module: mail #. odoo-javascript #: code:addons/mail/static/src/core/web/activity_list_popover.xml:0 -#: model:ir.model.fields.selection,name:mail.selection__account_journal__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__account_move__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__account_payment__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__crm_lead__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__event_booth__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__event_event__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__event_registration__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__event_sponsor__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__event_track__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_contract__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_services__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_applicant__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_contract__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_employee__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_expense__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_expense_sheet__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_leave__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__hr_leave_allocation__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__lunch_supplier__activity_state__overdue #: model:ir.model.fields.selection,name:mail.selection__mail_activity__state__overdue #: model:ir.model.fields.selection,name:mail.selection__mail_activity_mixin__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__mailing_mailing__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__maintenance_equipment__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__maintenance_request__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__mrp_production__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__mrp_unbuild__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__pos_session__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__product_pricelist__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__product_product__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__product_template__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__project_project__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__project_task__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__project_update__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__purchase_order__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__purchase_requisition__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__repair_order__activity_state__overdue #: model:ir.model.fields.selection,name:mail.selection__res_partner__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__res_partner_bank__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__sale_order__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__slide_channel__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__stock_landed_cost__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__stock_lot__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__stock_picking__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__stock_picking_batch__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__survey_survey__activity_state__overdue -#: model:ir.model.fields.selection,name:mail.selection__survey_user_input__activity_state__overdue #, python-format msgid "Overdue" msgstr "" @@ -6959,53 +6854,9 @@ msgstr "" #. module: mail #. odoo-javascript #: code:addons/mail/static/src/core/web/activity_list_popover.xml:0 -#: model:ir.model.fields.selection,name:mail.selection__account_journal__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__account_move__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__account_payment__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__crm_lead__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__event_booth__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__event_event__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__event_registration__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__event_sponsor__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__event_track__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_contract__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_services__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_applicant__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_contract__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_employee__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_expense__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_expense_sheet__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_leave__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__hr_leave_allocation__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__lunch_supplier__activity_state__planned #: model:ir.model.fields.selection,name:mail.selection__mail_activity__state__planned #: model:ir.model.fields.selection,name:mail.selection__mail_activity_mixin__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__mailing_mailing__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__maintenance_equipment__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__maintenance_request__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__mrp_production__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__mrp_unbuild__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__pos_session__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__product_pricelist__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__product_product__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__product_template__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__project_project__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__project_task__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__project_update__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__purchase_order__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__purchase_requisition__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__repair_order__activity_state__planned #: model:ir.model.fields.selection,name:mail.selection__res_partner__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__res_partner_bank__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__sale_order__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__slide_channel__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__stock_landed_cost__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__stock_lot__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__stock_picking__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__stock_picking_batch__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__survey_survey__activity_state__planned -#: model:ir.model.fields.selection,name:mail.selection__survey_user_input__activity_state__planned #, python-format msgid "Planned" msgstr "" @@ -9247,53 +9098,9 @@ msgstr "" #: code:addons/mail/static/src/core/web/activity_list_popover.xml:0 #: code:addons/mail/static/src/core/web/activity_list_popover_item.js:0 #: code:addons/mail/static/src/core/web/activity_menu.xml:0 -#: model:ir.model.fields.selection,name:mail.selection__account_journal__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__account_move__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__account_payment__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__crm_lead__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__event_booth__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__event_event__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__event_registration__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__event_sponsor__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__event_track__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_contract__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__fleet_vehicle_log_services__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_applicant__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_contract__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_employee__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_expense__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_expense_sheet__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_leave__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__hr_leave_allocation__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__lunch_supplier__activity_state__today #: model:ir.model.fields.selection,name:mail.selection__mail_activity__state__today #: model:ir.model.fields.selection,name:mail.selection__mail_activity_mixin__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__mailing_mailing__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__maintenance_equipment__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__maintenance_request__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__mrp_production__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__mrp_unbuild__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__pos_session__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__product_pricelist__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__product_product__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__product_template__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__project_project__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__project_task__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__project_update__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__purchase_order__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__purchase_requisition__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__repair_order__activity_state__today #: model:ir.model.fields.selection,name:mail.selection__res_partner__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__res_partner_bank__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__sale_order__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__slide_channel__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__stock_landed_cost__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__stock_lot__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__stock_picking__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__stock_picking_batch__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__survey_survey__activity_state__today -#: model:ir.model.fields.selection,name:mail.selection__survey_user_input__activity_state__today #, python-format msgid "Today" msgstr "" @@ -11056,10 +10863,3 @@ msgstr "" #, python-format msgid "“%(member_name)s” in “%(channel_name)s”" msgstr "" - -#. module: mail -#. odoo-javascript -#: code:addons/mail/static/src/core/web/chatter.js:0 -#, python-format -msgid "No recipient" -msgstr "" diff --git a/addons/mail/static/src/core/common/composer.js b/addons/mail/static/src/core/common/composer.js index f2bd6cbb62b..c56bdb713cb 100644 --- a/addons/mail/static/src/core/common/composer.js +++ b/addons/mail/static/src/core/common/composer.js @@ -25,6 +25,7 @@ import { import { _t } from "@web/core/l10n/translation"; import { useService } from "@web/core/utils/hooks"; import { FileUploader } from "@web/views/fields/file_handler"; +import { escape, sprintf } from "@web/core/utils/strings"; const EDIT_CLICK_TYPE = { CANCEL: "cancel", @@ -59,7 +60,7 @@ export class Composer extends Component { className: "", sidebar: true, showFullComposer: true, - allowUpload: true + allowUpload: true, }; static props = [ "composer", @@ -76,7 +77,7 @@ export class Composer extends Component { "sidebar?", "type?", "showFullComposer?", - "allowUpload?" + "allowUpload?", ]; static template = "mail.Composer"; @@ -209,17 +210,51 @@ export class Composer extends Component { } get CANCEL_OR_SAVE_EDIT_TEXT() { - return markup( - _t( - "%(cancel_keybind)s to cancel, %(save_keybind)s to save", - { - cancel_keybind: _t("Escape"), - cancel_type: EDIT_CLICK_TYPE.CANCEL, - save_keybind: this.sendKeybind, - save_type: EDIT_CLICK_TYPE.SAVE, - } - ) - ); + if (this.ui.isSmall) { + return markup( + sprintf( + escape( + _t( + "%(open_button)s%(icon)s%(open_em)sDiscard editing%(close_em)s%(close_button)s" + ) + ), + { + open_button: `", + icon: ``, + open_em: ``, + close_em: "", + } + ) + ); + } else { + const translation1 = _t( + "%(open_samp)sEscape%(close_samp)s %(open_em)sto %(open_cancel)scancel%(close_cancel)s%(close_em)s, %(open_samp)sCTRL-Enter%(close_samp)s %(open_em)sto %(open_save)ssave%(close_save)s%(close_em)s" + ); + const translation2 = _t( + "%(open_samp)sEscape%(close_samp)s %(open_em)sto %(open_cancel)scancel%(close_cancel)s%(close_em)s, %(open_samp)sEnter%(close_samp)s %(open_em)sto %(open_save)ssave%(close_save)s%(close_em)s" + ); + return markup( + sprintf(escape(this.props.mode === "extended" ? translation1 : translation2), { + open_samp: "", + close_samp: "", + open_em: "", + close_em: "", + open_cancel: ``, + close_cancel: "", + open_save: ``, + close_save: "", + }) + ); + } } get SEND_TEXT() { @@ -518,6 +553,10 @@ export class Composer extends Component { } async sendMessage() { + if (this.props.composer.message) { + this.editMessage(); + return; + } await this.processMessage(async (value) => { const postData = { attachments: this.props.composer.attachments, diff --git a/addons/mail/static/tests/message/message_tests.js b/addons/mail/static/tests/message/message_tests.js index 3ef64cf8031..ec948b33f52 100644 --- a/addons/mail/static/tests/message/message_tests.js +++ b/addons/mail/static/tests/message/message_tests.js @@ -9,6 +9,7 @@ import { deserializeDateTime } from "@web/core/l10n/dates"; import { getOrigin } from "@web/core/utils/urls"; import { makeDeferred, patchWithCleanup, triggerHotkey } from "@web/../tests/helpers/utils"; import { click, contains, insertText } from "@web/../tests/utils"; +import { SIZES, patchUiSize } from "../helpers/patch_ui_size"; const { DateTime } = luxon; @@ -34,6 +35,38 @@ QUnit.test("Start edition on click edit", async () => { await contains(".o-mail-Message-editable .o-mail-Composer-input", { value: "Hello world" }); }); +QUnit.test("Edit message (mobile)", async () => { + patchUiSize({ size: SIZES.SM }); + const pyEnv = await startServer(); + const channelId = pyEnv["discuss.channel"].create({ + name: "general", + channel_type: "channel", + }); + pyEnv["mail.message"].create({ + author_id: pyEnv.currentPartnerId, + body: "Hello world", + model: "discuss.channel", + res_id: channelId, + message_type: "comment", + }); + const { openDiscuss } = await start(); + await openDiscuss(); + await click("button", { text: "Channel" }); + await click("button", { text: "general" }); + await contains(".o-mail-Message"); + await click(".o-mail-Message [title='Expand']"); + await click(".o-mail-Message [title='Edit']"); + await contains(".o-mail-Message-editable .o-mail-Composer-input", { value: "Hello world" }); + await click("button", { text: "Discard editing" }); + await contains(".o-mail-Message-editable .o-mail-Composer", { count: 0 }); + await contains(".o-mail-Message-content", { text: "Hello world" }); + await click(".o-mail-Message [title='Expand']"); + await click(".o-mail-Message [title='Edit']"); + await insertText(".o-mail-Message .o-mail-Composer-input", "edited message", { replace: true }); + await click(".o-mail-Message .fa-paper-plane-o"); + await contains(".o-mail-Message-content", { text: "edited message" }); +}); + QUnit.test("Can edit message comment in chatter", async () => { const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({ name: "TestPartner" });