diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index fa1aab1b8..7a3c42b06 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3582,6 +3582,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_formatting_link_text" = "Text"; "lng_formatting_link_url" = "URL"; "lng_formatting_link_create" = "Create"; +"lng_formatting_code_title" = "Code Language"; +"lng_formatting_code_language" = "Language for syntax highlighting."; +"lng_formatting_code_auto" = "Auto-Detect"; "lng_text_copied" = "Text copied to clipboard."; "lng_code_copied" = "Block copied to clipboard."; diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 46138e3fd..9ff85e099 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -1044,7 +1044,16 @@ not_null CreatePollBox::setupSolution( solution->setInstantReplaces(Ui::InstantReplaces::Default()); solution->setInstantReplacesEnabled( Core::App().settings().replaceEmojiValue()); - solution->setMarkdownReplacesEnabled(true); + solution->setMarkdownReplacesEnabled(rpl::single( + Ui::MarkdownEnabledState{ Ui::MarkdownEnabled{ { + Ui::InputField::kTagBold, + Ui::InputField::kTagItalic, + Ui::InputField::kTagUnderline, + Ui::InputField::kTagStrikeOut, + Ui::InputField::kTagCode, + Ui::InputField::kTagSpoiler, + } } } + )); solution->setEditLinkCallback( DefaultEditLinkCallback(_controller->uiShow(), solution)); solution->customTab(true); diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index cd7180218..d36d2c465 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_boxes.h" #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" +#include "styles/style_settings.h" #include "base/qt/qt_common_adapters.h" #include @@ -59,6 +60,7 @@ using EditLinkSelection = Ui::InputField::EditLinkSelection; constexpr auto kParseLinksTimeout = crl::time(1000); constexpr auto kTypesDuration = 4 * crl::time(1000); +constexpr auto kCodeLanguageLimit = 32; // For mention / custom emoji tags save and validate selfId, // ignore tags for different users. @@ -223,6 +225,51 @@ void EditLinkBox( }, text->lifetime()); } +void EditCodeLanguageBox( + not_null box, + QString now, + Fn save) { + Expects(save != nullptr); + + box->setTitle(tr::lng_formatting_code_title()); + box->addRow(object_ptr( + box, + tr::lng_formatting_code_language(), + st::settingsAddReplyLabel)); + const auto field = box->addRow(object_ptr( + box, + st::settingsAddReplyField, + tr::lng_formatting_code_auto(), + now.trimmed())); + box->setFocusCallback([=] { + field->setFocusFast(); + }); + field->selectAll(); + field->setMaxLength(kCodeLanguageLimit); + + Ui::AddLengthLimitLabel(field, kCodeLanguageLimit); + + const auto callback = [=] { + const auto name = field->getLastText().trimmed(); + const auto check = QRegularExpression("^[a-zA-Z0-9\\+\\-]+$"); + if (check.match(name).hasMatch()) { + auto weak = Ui::MakeWeak(box); + save(name); + if (const auto strong = weak.data()) { + strong->closeBox(); + } + } else { + field->showError(); + } + }; + field->submits( + ) | rpl::start_with_next(callback, field->lifetime()); + box->addButton(tr::lng_settings_save(), callback); + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); +} + TextWithEntities StripSupportHashtag(TextWithEntities text) { static const auto expression = QRegularExpression( u"\\n?#tsf[a-z0-9_-]*[\\s#a-z0-9_-]*$"_q, @@ -321,6 +368,13 @@ Fn save)> DefaultEditLanguageCallback( + std::shared_ptr show) { + return [=](QString now, Fn save) { + show->showBox(Box(EditCodeLanguageBox, now, save)); + }; +} + void InitMessageFieldHandlers( not_null session, std::shared_ptr show, @@ -343,6 +397,7 @@ void InitMessageFieldHandlers( if (show) { field->setEditLinkCallback( DefaultEditLinkCallback(show, field, fieldStyle)); + field->setEditLanguageCallback(DefaultEditLanguageCallback(show)); InitSpellchecker(show, field, fieldStyle != nullptr); } const auto style = field->lifetime().make_state( @@ -585,15 +640,19 @@ void InitMessageFieldFade( field->scrollTop().changes() | rpl::to_empty, field->sizeValue() | rpl::to_empty ) | rpl::start_with_next([=] { - const auto topHidden = !field->scrollTop().current(); - if (topFade->isHidden() != topHidden) { - topFade->setVisible(!topHidden); - } - const auto adjusted = field->scrollTop().current() + descent; - const auto bottomHidden = (adjusted >= field->scrollTopMax()); - if (bottomFade->isHidden() != bottomHidden) { - bottomFade->setVisible(!bottomHidden); - } + // InputField::changes fires before the auto-resize is being applied, + // so for the scroll values to be accurate we enqueue the check. + InvokeQueued(field, [=] { + const auto topHidden = !field->scrollTop().current(); + if (topFade->isHidden() != topHidden) { + topFade->setVisible(!topHidden); + } + const auto adjusted = field->scrollTop().current() + descent; + const auto bottomHidden = (adjusted >= field->scrollTopMax()); + if (bottomFade->isHidden() != bottomHidden) { + bottomFade->setVisible(!bottomHidden); + } + }); }, topFade->lifetime()); } diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index 1e67642a7..7efdb7d18 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -35,6 +35,7 @@ class Show; namespace Ui { class PopupMenu; +class Show; } // namespace Ui [[nodiscard]] QString PrepareMentionTag(not_null user); @@ -51,6 +52,8 @@ Fn show, not_null field, const style::InputField *fieldStyle = nullptr); +Fn save)> DefaultEditLanguageCallback( + std::shared_ptr show); void InitMessageFieldHandlers( not_null session, std::shared_ptr show, // may be null diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index cc4a91a1f..16a559689 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -1658,6 +1658,7 @@ void ComposeControls::initField() { InitMessageFieldFade(_field, _st.field.textBg); _field->setEditLinkCallback( DefaultEditLinkCallback(_show, _field, &_st.boxField)); + _field->setEditLanguageCallback(DefaultEditLanguageCallback(_show)); initAutocomplete(); const auto allow = [=](not_null emoji) { return _history diff --git a/Telegram/lib_ui b/Telegram/lib_ui index d4d51136c..20caa93a8 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit d4d51136cd5ff54b84b2863a7ece39693b5ce522 +Subproject commit 20caa93a8d2b5b279f36eb19d9200be071420ba3