Added spoiler support to input field.

This commit is contained in:
23rd 2021-12-19 17:06:21 +03:00
parent bcf16c6c80
commit ee4a94c122
6 changed files with 45 additions and 0 deletions

View file

@ -139,4 +139,8 @@ QString Integration::phraseFormattingMonospace() {
return "Monospace"; return "Monospace";
} }
QString Integration::phraseFormattingSpoiler() {
return "Spoiler";
}
} // namespace Ui } // namespace Ui

View file

@ -70,6 +70,7 @@ public:
[[nodiscard]] virtual QString phraseFormattingUnderline(); [[nodiscard]] virtual QString phraseFormattingUnderline();
[[nodiscard]] virtual QString phraseFormattingStrikeOut(); [[nodiscard]] virtual QString phraseFormattingStrikeOut();
[[nodiscard]] virtual QString phraseFormattingMonospace(); [[nodiscard]] virtual QString phraseFormattingMonospace();
[[nodiscard]] virtual QString phraseFormattingSpoiler();
}; };

View file

@ -70,6 +70,10 @@ QString SeparatorsMono() {
return Separators(QString::fromUtf8("*~/")); return Separators(QString::fromUtf8("*~/"));
} }
QString SeparatorsSpoiler() {
return Separators(QString::fromUtf8("|*~/"));
}
QString ExpressionHashtag() { QString ExpressionHashtag() {
return QString::fromUtf8("(^|[") + ExpressionSeparators(QString::fromUtf8("`\\*/")) + QString::fromUtf8("])#[\\w]{2,64}([\\W]|$)"); return QString::fromUtf8("(^|[") + ExpressionSeparators(QString::fromUtf8("`\\*/")) + QString::fromUtf8("])#[\\w]{2,64}([\\W]|$)");
} }
@ -1271,6 +1275,14 @@ QString MarkdownPreBadAfter() {
return QString::fromLatin1("`"); return QString::fromLatin1("`");
} }
QString MarkdownSpoilerGoodBefore() {
return SeparatorsSpoiler();
}
QString MarkdownSpoilerBadAfter() {
return QString::fromLatin1("|");
}
bool IsValidProtocol(const QString &protocol) { bool IsValidProtocol(const QString &protocol) {
static const auto list = CreateValidProtocols(); static const auto list = CreateValidProtocols();
return list.contains(base::crc32(protocol.constData(), protocol.size() * sizeof(QChar))); return list.contains(base::crc32(protocol.constData(), protocol.size() * sizeof(QChar)));
@ -2087,6 +2099,7 @@ EntitiesInText ConvertTextTagsToEntities(const TextWithTags::Tags &tags) {
EntityType::Italic, EntityType::Italic,
EntityType::Underline, EntityType::Underline,
EntityType::StrikeOut, EntityType::StrikeOut,
EntityType::Spoiler,
EntityType::Code, EntityType::Code,
EntityType::Pre, EntityType::Pre,
}; };
@ -2193,6 +2206,8 @@ EntitiesInText ConvertTextTagsToEntities(const TextWithTags::Tags &tags) {
result.set(EntityType::Code); result.set(EntityType::Code);
} else if (single == Ui::InputField::kTagPre) { } else if (single == Ui::InputField::kTagPre) {
result.set(EntityType::Pre); result.set(EntityType::Pre);
} else if (single == Ui::InputField::kTagSpoiler) {
result.set(EntityType::Spoiler);
} else { } else {
result.link = single.toString(); result.link = single.toString();
} }
@ -2281,6 +2296,7 @@ TextWithTags::Tags ConvertEntitiesToTextTags(
break; break;
case EntityType::Code: push(Ui::InputField::kTagCode); break; // #TODO entities case EntityType::Code: push(Ui::InputField::kTagCode); break; // #TODO entities
case EntityType::Pre: push(Ui::InputField::kTagPre); break; case EntityType::Pre: push(Ui::InputField::kTagPre); break;
case EntityType::Spoiler: push(Ui::InputField::kTagSpoiler); break;
} }
} }
if (!toRemove.empty()) { if (!toRemove.empty()) {

View file

@ -291,6 +291,8 @@ QString MarkdownCodeGoodBefore();
QString MarkdownCodeBadAfter(); QString MarkdownCodeBadAfter();
QString MarkdownPreGoodBefore(); QString MarkdownPreGoodBefore();
QString MarkdownPreBadAfter(); QString MarkdownPreBadAfter();
QString MarkdownSpoilerGoodBefore();
QString MarkdownSpoilerBadAfter();
// Text preprocess. // Text preprocess.
QString Clean(const QString &text); QString Clean(const QString &text);

View file

@ -44,6 +44,7 @@ const auto &kTagUnderline = InputField::kTagUnderline;
const auto &kTagStrikeOut = InputField::kTagStrikeOut; const auto &kTagStrikeOut = InputField::kTagStrikeOut;
const auto &kTagCode = InputField::kTagCode; const auto &kTagCode = InputField::kTagCode;
const auto &kTagPre = InputField::kTagPre; const auto &kTagPre = InputField::kTagPre;
const auto &kTagSpoiler = InputField::kTagSpoiler;
const auto kTagCheckLinkMeta = QString("^:/:/:^"); const auto kTagCheckLinkMeta = QString("^:/:/:^");
const auto kNewlineChars = QString("\r\n") const auto kNewlineChars = QString("\r\n")
+ QChar(0xfdd0) // QTextBeginningOfFrame + QChar(0xfdd0) // QTextBeginningOfFrame
@ -230,6 +231,7 @@ constexpr auto kTagItalicIndex = 1;
constexpr auto kTagStrikeOutIndex = 2; constexpr auto kTagStrikeOutIndex = 2;
constexpr auto kTagCodeIndex = 3; constexpr auto kTagCodeIndex = 3;
constexpr auto kTagPreIndex = 4; constexpr auto kTagPreIndex = 4;
constexpr auto kTagSpoilerIndex = 5;
constexpr auto kInvalidPosition = std::numeric_limits<int>::max() / 2; constexpr auto kInvalidPosition = std::numeric_limits<int>::max() / 2;
class TagSearchItem { class TagSearchItem {
@ -373,6 +375,13 @@ const std::vector<TagStartExpression> &TagStartExpressions() {
TextUtilities::MarkdownPreBadAfter(), TextUtilities::MarkdownPreBadAfter(),
TextUtilities::MarkdownPreGoodBefore() TextUtilities::MarkdownPreGoodBefore()
}, },
{
kTagSpoiler,
TextUtilities::MarkdownSpoilerGoodBefore(),
TextUtilities::MarkdownSpoilerBadAfter(),
TextUtilities::MarkdownSpoilerBadAfter(),
TextUtilities::MarkdownSpoilerGoodBefore()
},
}; };
return cached; return cached;
} }
@ -385,6 +394,7 @@ const std::map<QString, int> &TagIndices() {
{ kTagStrikeOut, kTagStrikeOutIndex }, { kTagStrikeOut, kTagStrikeOutIndex },
{ kTagCode, kTagCodeIndex }, { kTagCode, kTagCodeIndex },
{ kTagPre, kTagPreIndex }, { kTagPre, kTagPreIndex },
{ kTagSpoiler, kTagSpoilerIndex },
}; };
return cached; return cached;
} }
@ -702,6 +712,7 @@ QTextCharFormat PrepareTagFormat(
auto result = QTextCharFormat(); auto result = QTextCharFormat();
auto font = st.font; auto font = st.font;
auto color = std::optional<style::color>(); auto color = std::optional<style::color>();
auto bg = std::optional<style::color>();
const auto applyOne = [&](QStringView tag) { const auto applyOne = [&](QStringView tag) {
if (IsValidMarkdownLink(tag)) { if (IsValidMarkdownLink(tag)) {
color = st::defaultTextPalette.linkFg; color = st::defaultTextPalette.linkFg;
@ -716,6 +727,8 @@ QTextCharFormat PrepareTagFormat(
} else if (tag == kTagCode || tag == kTagPre) { } else if (tag == kTagCode || tag == kTagPre) {
color = st::defaultTextPalette.monoFg; color = st::defaultTextPalette.monoFg;
font = font->monospace(); font = font->monospace();
} else if (tag == kTagSpoiler) {
bg = st::defaultTextPalette.spoilerActiveBg;
} }
}; };
for (const auto &tag : TextUtilities::SplitTags(tag)) { for (const auto &tag : TextUtilities::SplitTags(tag)) {
@ -724,6 +737,9 @@ QTextCharFormat PrepareTagFormat(
result.setFont(font); result.setFont(font);
result.setForeground(color.value_or(st.textFg)); result.setForeground(color.value_or(st.textFg));
result.setProperty(kTagProperty, tag); result.setProperty(kTagProperty, tag);
if (bg) {
result.setBackground(*bg);
}
return result; return result;
} }
@ -842,6 +858,7 @@ const QString InputField::kTagUnderline = QStringLiteral("^^");
const QString InputField::kTagStrikeOut = QStringLiteral("~~"); const QString InputField::kTagStrikeOut = QStringLiteral("~~");
const QString InputField::kTagCode = QStringLiteral("`"); const QString InputField::kTagCode = QStringLiteral("`");
const QString InputField::kTagPre = QStringLiteral("```"); const QString InputField::kTagPre = QStringLiteral("```");
const QString InputField::kTagSpoiler = QStringLiteral("||");
class InputField::Inner final : public QTextEdit { class InputField::Inner final : public QTextEdit {
public: public:
@ -2819,6 +2836,8 @@ bool InputField::handleMarkdownKey(QKeyEvent *e) {
toggleSelectionMarkdown(kTagStrikeOut); toggleSelectionMarkdown(kTagStrikeOut);
} else if (matches(kMonospaceSequence)) { } else if (matches(kMonospaceSequence)) {
toggleSelectionMarkdown(kTagCode); toggleSelectionMarkdown(kTagCode);
} else if (matches(kSpoilerSequence)) {
toggleSelectionMarkdown(kTagSpoiler);
} else if (matches(kClearFormatSequence)) { } else if (matches(kClearFormatSequence)) {
clearSelectionMarkdown(); clearSelectionMarkdown();
} else if (matches(kEditLinkSequence) && _editLinkCallback) { } else if (matches(kEditLinkSequence) && _editLinkCallback) {
@ -3578,6 +3597,7 @@ void InputField::addMarkdownActions(
addtag(integration.phraseFormattingUnderline(), QKeySequence::Underline, kTagUnderline); addtag(integration.phraseFormattingUnderline(), QKeySequence::Underline, kTagUnderline);
addtag(integration.phraseFormattingStrikeOut(), kStrikeOutSequence, kTagStrikeOut); addtag(integration.phraseFormattingStrikeOut(), kStrikeOutSequence, kTagStrikeOut);
addtag(integration.phraseFormattingMonospace(), kMonospaceSequence, kTagCode); addtag(integration.phraseFormattingMonospace(), kMonospaceSequence, kTagCode);
addtag(integration.phraseFormattingSpoiler(), kSpoilerSequence, kTagSpoiler);
if (_editLinkCallback) { if (_editLinkCallback) {
submenu->addSeparator(); submenu->addSeparator();

View file

@ -26,6 +26,7 @@ const auto kClearFormatSequence = QKeySequence("ctrl+shift+n");
const auto kStrikeOutSequence = QKeySequence("ctrl+shift+x"); const auto kStrikeOutSequence = QKeySequence("ctrl+shift+x");
const auto kMonospaceSequence = QKeySequence("ctrl+shift+m"); const auto kMonospaceSequence = QKeySequence("ctrl+shift+m");
const auto kEditLinkSequence = QKeySequence("ctrl+k"); const auto kEditLinkSequence = QKeySequence("ctrl+k");
const auto kSpoilerSequence = QKeySequence("ctrl+shift+p");
class PopupMenu; class PopupMenu;
@ -171,6 +172,7 @@ public:
static const QString kTagStrikeOut; static const QString kTagStrikeOut;
static const QString kTagCode; static const QString kTagCode;
static const QString kTagPre; static const QString kTagPre;
static const QString kTagSpoiler;
InputField( InputField(
QWidget *parent, QWidget *parent,