mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support limited formatting input in factcheck.
This commit is contained in:
parent
a3ef36f9f7
commit
97a5e0c6ea
16 changed files with 151 additions and 106 deletions
|
@ -1044,7 +1044,7 @@ not_null<Ui::InputField*> CreatePollBox::setupSolution(
|
||||||
solution->setInstantReplaces(Ui::InstantReplaces::Default());
|
solution->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
solution->setInstantReplacesEnabled(
|
solution->setInstantReplacesEnabled(
|
||||||
Core::App().settings().replaceEmojiValue());
|
Core::App().settings().replaceEmojiValue());
|
||||||
solution->setMarkdownReplacesEnabled(rpl::single(true));
|
solution->setMarkdownReplacesEnabled(true);
|
||||||
solution->setEditLinkCallback(
|
solution->setEditLinkCallback(
|
||||||
DefaultEditLinkCallback(_controller->uiShow(), solution));
|
DefaultEditLinkCallback(_controller->uiShow(), solution));
|
||||||
solution->customTab(true);
|
solution->customTab(true);
|
||||||
|
|
|
@ -60,60 +60,43 @@ constexpr auto kTypesDuration = 4 * crl::time(1000);
|
||||||
|
|
||||||
// For mention / custom emoji tags save and validate selfId,
|
// For mention / custom emoji tags save and validate selfId,
|
||||||
// ignore tags for different users.
|
// ignore tags for different users.
|
||||||
class FieldTagMimeProcessor final {
|
[[nodiscard]] Fn<QString(QStringView)> FieldTagMimeProcessor(
|
||||||
public:
|
not_null<Main::Session*> session,
|
||||||
FieldTagMimeProcessor(
|
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji) {
|
||||||
not_null<Main::Session*> _session,
|
return [=](QStringView mimeTag) {
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji);
|
const auto id = session->userId().bare;
|
||||||
|
auto all = TextUtilities::SplitTags(mimeTag);
|
||||||
QString operator()(QStringView mimeTag);
|
auto premiumSkipped = (DocumentData*)nullptr;
|
||||||
|
for (auto i = all.begin(); i != all.end();) {
|
||||||
private:
|
const auto tag = *i;
|
||||||
const not_null<Main::Session*> _session;
|
if (TextUtilities::IsMentionLink(tag)
|
||||||
const Fn<bool(not_null<DocumentData*>)> _allowPremiumEmoji;
|
&& TextUtilities::MentionNameDataToFields(tag).selfId != id) {
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
FieldTagMimeProcessor::FieldTagMimeProcessor(
|
|
||||||
not_null<Main::Session*> session,
|
|
||||||
Fn<bool(not_null<DocumentData*>)> allowPremiumEmoji)
|
|
||||||
: _session(session)
|
|
||||||
, _allowPremiumEmoji(allowPremiumEmoji) {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FieldTagMimeProcessor::operator()(QStringView mimeTag) {
|
|
||||||
const auto id = _session->userId().bare;
|
|
||||||
auto all = TextUtilities::SplitTags(mimeTag);
|
|
||||||
auto premiumSkipped = (DocumentData*)nullptr;
|
|
||||||
for (auto i = all.begin(); i != all.end();) {
|
|
||||||
const auto tag = *i;
|
|
||||||
if (TextUtilities::IsMentionLink(tag)
|
|
||||||
&& TextUtilities::MentionNameDataToFields(tag).selfId != id) {
|
|
||||||
i = all.erase(i);
|
|
||||||
continue;
|
|
||||||
} else if (Ui::InputField::IsCustomEmojiLink(tag)) {
|
|
||||||
const auto data = Ui::InputField::CustomEmojiEntityData(tag);
|
|
||||||
const auto emoji = Data::ParseCustomEmojiData(data);
|
|
||||||
if (!emoji) {
|
|
||||||
i = all.erase(i);
|
i = all.erase(i);
|
||||||
continue;
|
continue;
|
||||||
} else if (!_session->premium()) {
|
} else if (Ui::InputField::IsCustomEmojiLink(tag)) {
|
||||||
const auto document = _session->data().document(emoji);
|
const auto data = Ui::InputField::CustomEmojiEntityData(tag);
|
||||||
if (document->isPremiumEmoji()) {
|
const auto emoji = Data::ParseCustomEmojiData(data);
|
||||||
if (!_allowPremiumEmoji
|
if (!emoji) {
|
||||||
|| premiumSkipped
|
i = all.erase(i);
|
||||||
|| !_session->premiumPossible()
|
continue;
|
||||||
|| !_allowPremiumEmoji(document)) {
|
} else if (!session->premium()) {
|
||||||
premiumSkipped = document;
|
const auto document = session->data().document(emoji);
|
||||||
i = all.erase(i);
|
if (document->isPremiumEmoji()) {
|
||||||
continue;
|
if (!allowPremiumEmoji
|
||||||
|
|| premiumSkipped
|
||||||
|
|| !session->premiumPossible()
|
||||||
|
|| !allowPremiumEmoji(document)) {
|
||||||
|
premiumSkipped = document;
|
||||||
|
i = all.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
++i;
|
return TextUtilities::JoinTag(all);
|
||||||
}
|
};
|
||||||
return TextUtilities::JoinTag(all);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool ValidateUrl(const QString &value) {
|
//bool ValidateUrl(const QString &value) {
|
||||||
|
@ -352,7 +335,7 @@ void InitMessageFieldHandlers(
|
||||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
field->setInstantReplacesEnabled(
|
field->setInstantReplacesEnabled(
|
||||||
Core::App().settings().replaceEmojiValue());
|
Core::App().settings().replaceEmojiValue());
|
||||||
field->setMarkdownReplacesEnabled(rpl::single(true));
|
field->setMarkdownReplacesEnabled(true);
|
||||||
if (show) {
|
if (show) {
|
||||||
field->setEditLinkCallback(
|
field->setEditLinkCallback(
|
||||||
DefaultEditLinkCallback(show, field, fieldStyle));
|
DefaultEditLinkCallback(show, field, fieldStyle));
|
||||||
|
@ -360,6 +343,42 @@ void InitMessageFieldHandlers(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fn<void(not_null<Ui::InputField*>)> FactcheckFieldIniter(
|
||||||
|
std::shared_ptr<Main::SessionShow> show) {
|
||||||
|
Expects(show != nullptr);
|
||||||
|
|
||||||
|
return [=](not_null<Ui::InputField*> field) {
|
||||||
|
field->setTagMimeProcessor([](QStringView mimeTag) {
|
||||||
|
using Field = Ui::InputField;
|
||||||
|
auto all = TextUtilities::SplitTags(mimeTag);
|
||||||
|
for (auto i = all.begin(); i != all.end();) {
|
||||||
|
const auto tag = *i;
|
||||||
|
if (tag != Field::kTagBold
|
||||||
|
&& tag != Field::kTagItalic
|
||||||
|
&& (!Field::IsValidMarkdownLink(mimeTag)
|
||||||
|
|| TextUtilities::IsMentionLink(mimeTag))) {
|
||||||
|
i = all.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return TextUtilities::JoinTag(all);
|
||||||
|
});
|
||||||
|
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
|
field->setInstantReplacesEnabled(
|
||||||
|
Core::App().settings().replaceEmojiValue());
|
||||||
|
field->setMarkdownReplacesEnabled(rpl::single(
|
||||||
|
Ui::MarkdownEnabledState{
|
||||||
|
Ui::MarkdownEnabled{
|
||||||
|
{ Ui::InputField::kTagBold, Ui::InputField::kTagItalic }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
field->setEditLinkCallback(DefaultEditLinkCallback(show, field));
|
||||||
|
InitSpellchecker(show, field);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void InitMessageFieldHandlers(
|
void InitMessageFieldHandlers(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Ui::InputField*> field,
|
not_null<Ui::InputField*> field,
|
||||||
|
|
|
@ -77,6 +77,9 @@ void InitSpellchecker(
|
||||||
not_null<Ui::InputField*> field,
|
not_null<Ui::InputField*> field,
|
||||||
bool skipDictionariesManager = false);
|
bool skipDictionariesManager = false);
|
||||||
|
|
||||||
|
[[nodiscard]] Fn<void(not_null<Ui::InputField*>)> FactcheckFieldIniter(
|
||||||
|
std::shared_ptr<Main::SessionShow> show);
|
||||||
|
|
||||||
bool HasSendText(not_null<const Ui::InputField*> field);
|
bool HasSendText(not_null<const Ui::InputField*> field);
|
||||||
|
|
||||||
void InitMessageFieldFade(
|
void InitMessageFieldFade(
|
||||||
|
|
|
@ -199,18 +199,20 @@ void Factchecks::save(
|
||||||
|
|
||||||
void Factchecks::save(
|
void Factchecks::save(
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
TextWithEntities was,
|
const TextWithEntities &was,
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
std::shared_ptr<Ui::Show> show) {
|
std::shared_ptr<Ui::Show> show) {
|
||||||
const auto done = [=](QString error) {
|
const auto wasEmpty = was.empty();
|
||||||
|
const auto textEmpty = text.empty();
|
||||||
|
save(itemId, std::move(text), [=](QString error) {
|
||||||
show->showToast(!error.isEmpty()
|
show->showToast(!error.isEmpty()
|
||||||
? error
|
? error
|
||||||
: was.empty()
|
: wasEmpty
|
||||||
? tr::lng_factcheck_remove_done(tr::now)
|
? tr::lng_factcheck_remove_done(tr::now)
|
||||||
: text.empty()
|
: textEmpty
|
||||||
? tr::lng_factcheck_add_done(tr::now)
|
? tr::lng_factcheck_add_done(tr::now)
|
||||||
: tr::lng_factcheck_edit_done(tr::now));
|
: tr::lng_factcheck_edit_done(tr::now));
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
Fn<void(QString)> done);
|
Fn<void(QString)> done);
|
||||||
void save(
|
void save(
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
TextWithEntities was,
|
const TextWithEntities &was,
|
||||||
TextWithEntities text,
|
TextWithEntities text,
|
||||||
std::shared_ptr<Ui::Show> show);
|
std::shared_ptr<Ui::Show> show);
|
||||||
|
|
||||||
|
|
|
@ -2184,7 +2184,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
TextWithEntities result) {
|
TextWithEntities result) {
|
||||||
const auto show = controller->uiShow();
|
const auto show = controller->uiShow();
|
||||||
session->factchecks().save(itemId, text, result, show);
|
session->factchecks().save(itemId, text, result, show);
|
||||||
}));
|
}, FactcheckFieldIniter(controller->uiShow())));
|
||||||
}, &st::menuIconFactcheck);
|
}, &st::menuIconFactcheck);
|
||||||
}
|
}
|
||||||
const auto pinItem = (item->canPin() && item->isPinned())
|
const auto pinItem = (item->canPin() && item->isPinned())
|
||||||
|
|
|
@ -69,6 +69,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_message_reactions.h"
|
#include "data/data_message_reactions.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
|
#include "chat_helpers/message_field.h" // FactcheckFieldIniter.
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
|
@ -736,7 +737,7 @@ void AddFactcheckAction(
|
||||||
TextWithEntities result) {
|
TextWithEntities result) {
|
||||||
const auto show = controller->uiShow();
|
const auto show = controller->uiShow();
|
||||||
session->factchecks().save(itemId, text, result, show);
|
session->factchecks().save(itemId, text, result, show);
|
||||||
}));
|
}, FactcheckFieldIniter(controller->uiShow())));
|
||||||
}, &st::menuIconFactcheck);
|
}, &st::menuIconFactcheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -448,7 +448,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
auto canSelectAll = false;
|
auto canSelectAll = false;
|
||||||
const auto mimeData = QGuiApplication::clipboard()->mimeData();
|
const auto mimeData = QGuiApplication::clipboard()->mimeData();
|
||||||
const auto clipboardHasText = mimeData ? mimeData->hasText() : false;
|
const auto clipboardHasText = mimeData ? mimeData->hasText() : false;
|
||||||
auto markdownEnabled = false;
|
auto markdownState = Ui::MarkdownEnabledState();
|
||||||
if (const auto edit = qobject_cast<QLineEdit*>(focused)) {
|
if (const auto edit = qobject_cast<QLineEdit*>(focused)) {
|
||||||
canCut = canCopy = canDelete = edit->hasSelectedText();
|
canCut = canCopy = canDelete = edit->hasSelectedText();
|
||||||
canSelectAll = !edit->text().isEmpty();
|
canSelectAll = !edit->text().isEmpty();
|
||||||
|
@ -464,7 +464,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
if (canCopy) {
|
if (canCopy) {
|
||||||
if (const auto inputField = dynamic_cast<Ui::InputField*>(
|
if (const auto inputField = dynamic_cast<Ui::InputField*>(
|
||||||
focused->parentWidget())) {
|
focused->parentWidget())) {
|
||||||
markdownEnabled = inputField->isMarkdownEnabled();
|
markdownState = inputField->markdownEnabledState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (const auto list = dynamic_cast<HistoryInner*>(focused)) {
|
} else if (const auto list = dynamic_cast<HistoryInner*>(focused)) {
|
||||||
|
@ -489,13 +489,19 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
ForceDisabled(psNewGroup, inactive || support);
|
ForceDisabled(psNewGroup, inactive || support);
|
||||||
ForceDisabled(psNewChannel, inactive || support);
|
ForceDisabled(psNewChannel, inactive || support);
|
||||||
|
|
||||||
ForceDisabled(psBold, !markdownEnabled);
|
const auto diabled = [=](const QString &tag) {
|
||||||
ForceDisabled(psItalic, !markdownEnabled);
|
return !markdownState.enabledForTag(tag);
|
||||||
ForceDisabled(psUnderline, !markdownEnabled);
|
};
|
||||||
ForceDisabled(psStrikeOut, !markdownEnabled);
|
using Field = Ui::InputField;
|
||||||
ForceDisabled(psBlockquote, !markdownEnabled);
|
ForceDisabled(psBold, diabled(Field::kTagBold));
|
||||||
ForceDisabled(psMonospace, !markdownEnabled);
|
ForceDisabled(psItalic, diabled(Field::kTagItalic));
|
||||||
ForceDisabled(psClearFormat, !markdownEnabled);
|
ForceDisabled(psUnderline, diabled(Field::kTagUnderline));
|
||||||
|
ForceDisabled(psStrikeOut, diabled(Field::kTagStrikeOut));
|
||||||
|
ForceDisabled(psBlockquote, diabled(Field::kTagBlockquote));
|
||||||
|
ForceDisabled(
|
||||||
|
psMonospace,
|
||||||
|
diabled(Field::kTagPre) || diabled(Field::kTagCode));
|
||||||
|
ForceDisabled(psClearFormat, markdownState.disabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
|
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
|
||||||
|
|
|
@ -64,8 +64,6 @@ private:
|
||||||
|
|
||||||
base::Timer _hideAfterFullScreenTimer;
|
base::Timer _hideAfterFullScreenTimer;
|
||||||
|
|
||||||
rpl::variable<bool> _canApplyMarkdown;
|
|
||||||
|
|
||||||
QMenuBar psMainMenu;
|
QMenuBar psMainMenu;
|
||||||
QAction *psLogout = nullptr;
|
QAction *psLogout = nullptr;
|
||||||
QAction *psUndo = nullptr;
|
QAction *psUndo = nullptr;
|
||||||
|
|
|
@ -92,10 +92,11 @@ public:
|
||||||
void setNativeWindow(NSWindow *window, NSView *view);
|
void setNativeWindow(NSWindow *window, NSView *view);
|
||||||
void initTouchBar(
|
void initTouchBar(
|
||||||
NSWindow *window,
|
NSWindow *window,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller);
|
||||||
rpl::producer<bool> canApplyMarkdown);
|
|
||||||
void setWindowBadge(const QString &str);
|
void setWindowBadge(const QString &str);
|
||||||
|
|
||||||
|
void setMarkdownEnabledState(Ui::MarkdownEnabledState state);
|
||||||
|
|
||||||
bool clipboardHasText();
|
bool clipboardHasText();
|
||||||
~Private();
|
~Private();
|
||||||
|
|
||||||
|
@ -103,6 +104,8 @@ private:
|
||||||
not_null<MainWindow*> _public;
|
not_null<MainWindow*> _public;
|
||||||
friend class MainWindow;
|
friend class MainWindow;
|
||||||
|
|
||||||
|
rpl::variable<Ui::MarkdownEnabledState> _markdownState;
|
||||||
|
|
||||||
NSWindow * __weak _nativeWindow = nil;
|
NSWindow * __weak _nativeWindow = nil;
|
||||||
NSView * __weak _nativeView = nil;
|
NSView * __weak _nativeView = nil;
|
||||||
|
|
||||||
|
@ -229,8 +232,7 @@ void MainWindow::Private::setNativeWindow(NSWindow *window, NSView *view) {
|
||||||
|
|
||||||
void MainWindow::Private::initTouchBar(
|
void MainWindow::Private::initTouchBar(
|
||||||
NSWindow *window,
|
NSWindow *window,
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller) {
|
||||||
rpl::producer<bool> canApplyMarkdown) {
|
|
||||||
if (!IsMac10_13OrGreater()) {
|
if (!IsMac10_13OrGreater()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -240,12 +242,17 @@ void MainWindow::Private::initTouchBar(
|
||||||
[window
|
[window
|
||||||
performSelectorOnMainThread:@selector(setTouchBar:)
|
performSelectorOnMainThread:@selector(setTouchBar:)
|
||||||
withObject:[[[RootTouchBar alloc]
|
withObject:[[[RootTouchBar alloc]
|
||||||
init:std::move(canApplyMarkdown)
|
init:_markdownState.value()
|
||||||
controller:controller
|
controller:controller
|
||||||
domain:(&Core::App().domain())] autorelease]
|
domain:(&Core::App().domain())] autorelease]
|
||||||
waitUntilDone:true];
|
waitUntilDone:true];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::Private::setMarkdownEnabledState(
|
||||||
|
Ui::MarkdownEnabledState state) {
|
||||||
|
_markdownState = state;
|
||||||
|
}
|
||||||
|
|
||||||
bool MainWindow::Private::clipboardHasText() {
|
bool MainWindow::Private::clipboardHasText() {
|
||||||
auto currentChangeCount = static_cast<int>([_generalPasteboard changeCount]);
|
auto currentChangeCount = static_cast<int>([_generalPasteboard changeCount]);
|
||||||
if (_generalPasteboardChangeCount != currentChangeCount) {
|
if (_generalPasteboardChangeCount != currentChangeCount) {
|
||||||
|
@ -289,10 +296,7 @@ void MainWindow::initHook() {
|
||||||
if (auto view = reinterpret_cast<NSView*>(winId())) {
|
if (auto view = reinterpret_cast<NSView*>(winId())) {
|
||||||
if (auto window = [view window]) {
|
if (auto window = [view window]) {
|
||||||
_private->setNativeWindow(window, view);
|
_private->setNativeWindow(window, view);
|
||||||
_private->initTouchBar(
|
_private->initTouchBar(window, &controller());
|
||||||
window,
|
|
||||||
&controller(),
|
|
||||||
_canApplyMarkdown.changes());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,7 +562,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
auto focused = QApplication::focusWidget();
|
auto focused = QApplication::focusWidget();
|
||||||
bool canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false;
|
bool canUndo = false, canRedo = false, canCut = false, canCopy = false, canPaste = false, canDelete = false, canSelectAll = false;
|
||||||
auto clipboardHasText = _private->clipboardHasText();
|
auto clipboardHasText = _private->clipboardHasText();
|
||||||
auto canApplyMarkdown = false;
|
auto markdownState = Ui::MarkdownEnabledState();
|
||||||
if (auto edit = qobject_cast<QLineEdit*>(focused)) {
|
if (auto edit = qobject_cast<QLineEdit*>(focused)) {
|
||||||
canCut = canCopy = canDelete = edit->hasSelectedText();
|
canCut = canCopy = canDelete = edit->hasSelectedText();
|
||||||
canSelectAll = !edit->text().isEmpty();
|
canSelectAll = !edit->text().isEmpty();
|
||||||
|
@ -574,7 +578,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
if (canCopy) {
|
if (canCopy) {
|
||||||
if (const auto inputField = dynamic_cast<Ui::InputField*>(
|
if (const auto inputField = dynamic_cast<Ui::InputField*>(
|
||||||
focused->parentWidget())) {
|
focused->parentWidget())) {
|
||||||
canApplyMarkdown = inputField->isMarkdownEnabled();
|
markdownState = inputField->markdownEnabledState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (auto list = dynamic_cast<HistoryInner*>(focused)) {
|
} else if (auto list = dynamic_cast<HistoryInner*>(focused)) {
|
||||||
|
@ -582,7 +586,7 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
canDelete = list->canDeleteSelected();
|
canDelete = list->canDeleteSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
_canApplyMarkdown = canApplyMarkdown;
|
_private->setMarkdownEnabledState(markdownState);
|
||||||
|
|
||||||
updateIsActive();
|
updateIsActive();
|
||||||
const auto logged = (sessionController() != nullptr);
|
const auto logged = (sessionController() != nullptr);
|
||||||
|
@ -603,13 +607,19 @@ void MainWindow::updateGlobalMenuHook() {
|
||||||
ForceDisabled(psNewChannel, inactive || support);
|
ForceDisabled(psNewChannel, inactive || support);
|
||||||
ForceDisabled(psShowTelegram, isActive());
|
ForceDisabled(psShowTelegram, isActive());
|
||||||
|
|
||||||
ForceDisabled(psBold, !canApplyMarkdown);
|
const auto diabled = [=](const QString &tag) {
|
||||||
ForceDisabled(psItalic, !canApplyMarkdown);
|
return !markdownState.enabledForTag(tag);
|
||||||
ForceDisabled(psUnderline, !canApplyMarkdown);
|
};
|
||||||
ForceDisabled(psStrikeOut, !canApplyMarkdown);
|
using Field = Ui::InputField;
|
||||||
ForceDisabled(psBlockquote, !canApplyMarkdown);
|
ForceDisabled(psBold, diabled(Field::kTagBold));
|
||||||
ForceDisabled(psMonospace, !canApplyMarkdown);
|
ForceDisabled(psItalic, diabled(Field::kTagItalic));
|
||||||
ForceDisabled(psClearFormat, !canApplyMarkdown);
|
ForceDisabled(psUnderline, diabled(Field::kTagUnderline));
|
||||||
|
ForceDisabled(psStrikeOut, diabled(Field::kTagStrikeOut));
|
||||||
|
ForceDisabled(psBlockquote, diabled(Field::kTagBlockquote));
|
||||||
|
ForceDisabled(
|
||||||
|
psMonospace,
|
||||||
|
diabled(Field::kTagPre) || diabled(Field::kTagCode));
|
||||||
|
ForceDisabled(psClearFormat, markdownState.disabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
|
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
|
||||||
|
|
|
@ -17,9 +17,13 @@ namespace Window {
|
||||||
class Controller;
|
class Controller;
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
struct MarkdownEnabledState;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
API_AVAILABLE(macos(10.12.2))
|
API_AVAILABLE(macos(10.12.2))
|
||||||
@interface RootTouchBar : NSTouchBar<NSTouchBarDelegate>
|
@interface RootTouchBar : NSTouchBar<NSTouchBarDelegate>
|
||||||
- (id)init:(rpl::producer<bool>)canApplyMarkdown
|
- (id)init:(rpl::producer<Ui::MarkdownEnabledState>)markdownState
|
||||||
controller:(not_null<Window::Controller*>)controller
|
controller:(not_null<Window::Controller*>)controller
|
||||||
domain:(not_null<Main::Domain*>)domain;
|
domain:(not_null<Main::Domain*>)domain;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "platform/mac/touchbar/mac_touchbar_audio.h"
|
#include "platform/mac/touchbar/mac_touchbar_audio.h"
|
||||||
#include "platform/mac/touchbar/mac_touchbar_common.h"
|
#include "platform/mac/touchbar/mac_touchbar_common.h"
|
||||||
#include "platform/mac/touchbar/mac_touchbar_main.h"
|
#include "platform/mac/touchbar/mac_touchbar_main.h"
|
||||||
|
#include "ui/widgets/fields/input_field.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
|
||||||
|
@ -57,13 +58,12 @@ const auto kAudioItemIdentifier = @"touchbarAudio";
|
||||||
Main::Session *_session;
|
Main::Session *_session;
|
||||||
Window::Controller *_controller;
|
Window::Controller *_controller;
|
||||||
|
|
||||||
bool _canApplyMarkdownLast;
|
rpl::variable<Ui::MarkdownEnabledState> _markdownState;
|
||||||
rpl::event_stream<bool> _canApplyMarkdown;
|
|
||||||
rpl::event_stream<> _touchBarSwitches;
|
rpl::event_stream<> _touchBarSwitches;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init:(rpl::producer<bool>)canApplyMarkdown
|
- (id)init:(rpl::producer<Ui::MarkdownEnabledState>)markdownState
|
||||||
controller:(not_null<Window::Controller*>)controller
|
controller:(not_null<Window::Controller*>)controller
|
||||||
domain:(not_null<Main::Domain*>)domain {
|
domain:(not_null<Main::Domain*>)domain {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
@ -75,10 +75,7 @@ const auto kAudioItemIdentifier = @"touchbarAudio";
|
||||||
self.defaultItemIdentifiers = @[];
|
self.defaultItemIdentifiers = @[];
|
||||||
});
|
});
|
||||||
_controller = controller;
|
_controller = controller;
|
||||||
_canApplyMarkdownLast = false;
|
_markdownState = std::move(markdownState);
|
||||||
std::move(
|
|
||||||
canApplyMarkdown
|
|
||||||
) | rpl::start_to_stream(_canApplyMarkdown, _lifetime);
|
|
||||||
|
|
||||||
auto sessionChanges = domain->activeSessionChanges(
|
auto sessionChanges = domain->activeSessionChanges(
|
||||||
) | rpl::map([=](Main::Session *session) {
|
) | rpl::map([=](Main::Session *session) {
|
||||||
|
@ -140,8 +137,7 @@ const auto kAudioItemIdentifier = @"touchbarAudio";
|
||||||
init:_controller
|
init:_controller
|
||||||
touchBarSwitches:_touchBarSwitches.events()] autorelease];
|
touchBarSwitches:_touchBarSwitches.events()] autorelease];
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
_canApplyMarkdown.events_starting_with_copy(
|
_markdownState.value(),
|
||||||
_canApplyMarkdownLast),
|
|
||||||
_controller->sessionController()->activeChatValue(
|
_controller->sessionController()->activeChatValue(
|
||||||
) | rpl::map([](Dialogs::Key k) {
|
) | rpl::map([](Dialogs::Key k) {
|
||||||
const auto topic = k.topic();
|
const auto topic = k.topic();
|
||||||
|
@ -153,16 +149,15 @@ const auto kAudioItemIdentifier = @"touchbarAudio";
|
||||||
: (peer && Data::CanSendAnyOf(peer, rights));
|
: (peer && Data::CanSendAnyOf(peer, rights));
|
||||||
}) | rpl::distinct_until_changed()
|
}) | rpl::distinct_until_changed()
|
||||||
) | rpl::start_with_next([=](
|
) | rpl::start_with_next([=](
|
||||||
bool canApplyMarkdown,
|
Ui::MarkdownEnabledState state,
|
||||||
bool hasActiveChat) {
|
bool hasActiveChat) {
|
||||||
_canApplyMarkdownLast = canApplyMarkdown;
|
|
||||||
item.groupTouchBar.defaultItemIdentifiers = @[
|
item.groupTouchBar.defaultItemIdentifiers = @[
|
||||||
kPinnedPanelItemIdentifier,
|
kPinnedPanelItemIdentifier,
|
||||||
canApplyMarkdown
|
(!state.disabled()
|
||||||
? kPopoverInputItemIdentifier
|
? kPopoverInputItemIdentifier
|
||||||
: hasActiveChat
|
: hasActiveChat
|
||||||
? kPopoverPickerItemIdentifier
|
? kPopoverPickerItemIdentifier
|
||||||
: @""];
|
: @"")];
|
||||||
}, [item lifetime]);
|
}, [item lifetime]);
|
||||||
|
|
||||||
return [item autorelease];
|
return [item autorelease];
|
||||||
|
|
|
@ -88,7 +88,7 @@ EditInfoBox::EditInfoBox(
|
||||||
_field->setInstantReplaces(Ui::InstantReplaces::Default());
|
_field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
_field->setInstantReplacesEnabled(
|
_field->setInstantReplacesEnabled(
|
||||||
Core::App().settings().replaceEmojiValue());
|
Core::App().settings().replaceEmojiValue());
|
||||||
_field->setMarkdownReplacesEnabled(rpl::single(true));
|
_field->setMarkdownReplacesEnabled(true);
|
||||||
_field->setEditLinkCallback(
|
_field->setEditLinkCallback(
|
||||||
DefaultEditLinkCallback(controller->uiShow(), _field));
|
DefaultEditLinkCallback(controller->uiShow(), _field));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ void EditFactcheckBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
TextWithEntities current,
|
TextWithEntities current,
|
||||||
int limit,
|
int limit,
|
||||||
Fn<void(TextWithEntities)> save) {
|
Fn<void(TextWithEntities)> save,
|
||||||
|
Fn<void(not_null<Ui::InputField*>)> initField) {
|
||||||
box->setTitle(tr::lng_factcheck_title());
|
box->setTitle(tr::lng_factcheck_title());
|
||||||
|
|
||||||
const auto field = box->addRow(object_ptr<Ui::InputField>(
|
const auto field = box->addRow(object_ptr<Ui::InputField>(
|
||||||
|
@ -29,6 +30,7 @@ void EditFactcheckBox(
|
||||||
TextUtilities::ConvertEntitiesToTextTags(current.entities)
|
TextUtilities::ConvertEntitiesToTextTags(current.entities)
|
||||||
}));
|
}));
|
||||||
AddLengthLimitLabel(field, limit);
|
AddLengthLimitLabel(field, limit);
|
||||||
|
initField(field);
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
Initial,
|
Initial,
|
||||||
|
|
|
@ -9,8 +9,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class InputField;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
void EditFactcheckBox(
|
void EditFactcheckBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
TextWithEntities current,
|
TextWithEntities current,
|
||||||
int limit,
|
int limit,
|
||||||
Fn<void(TextWithEntities)> save);
|
Fn<void(TextWithEntities)> save,
|
||||||
|
Fn<void(not_null<Ui::InputField*>)> initField);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e7c598affe724322577ef46d9a07d1dcac3c617b
|
Subproject commit 0835adcc2d3cb1f2cf0d3630f6d95485864621f9
|
Loading…
Add table
Reference in a new issue