Added spoiler support to input field.
This commit is contained in:
parent
bcf16c6c80
commit
ee4a94c122
6 changed files with 45 additions and 0 deletions
|
|
@ -139,4 +139,8 @@ QString Integration::phraseFormattingMonospace() {
|
|||
return "Monospace";
|
||||
}
|
||||
|
||||
QString Integration::phraseFormattingSpoiler() {
|
||||
return "Spoiler";
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ public:
|
|||
[[nodiscard]] virtual QString phraseFormattingUnderline();
|
||||
[[nodiscard]] virtual QString phraseFormattingStrikeOut();
|
||||
[[nodiscard]] virtual QString phraseFormattingMonospace();
|
||||
[[nodiscard]] virtual QString phraseFormattingSpoiler();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ QString SeparatorsMono() {
|
|||
return Separators(QString::fromUtf8("*~/"));
|
||||
}
|
||||
|
||||
QString SeparatorsSpoiler() {
|
||||
return Separators(QString::fromUtf8("|*~/"));
|
||||
}
|
||||
|
||||
QString ExpressionHashtag() {
|
||||
return QString::fromUtf8("(^|[") + ExpressionSeparators(QString::fromUtf8("`\\*/")) + QString::fromUtf8("])#[\\w]{2,64}([\\W]|$)");
|
||||
}
|
||||
|
|
@ -1271,6 +1275,14 @@ QString MarkdownPreBadAfter() {
|
|||
return QString::fromLatin1("`");
|
||||
}
|
||||
|
||||
QString MarkdownSpoilerGoodBefore() {
|
||||
return SeparatorsSpoiler();
|
||||
}
|
||||
|
||||
QString MarkdownSpoilerBadAfter() {
|
||||
return QString::fromLatin1("|");
|
||||
}
|
||||
|
||||
bool IsValidProtocol(const QString &protocol) {
|
||||
static const auto list = CreateValidProtocols();
|
||||
return list.contains(base::crc32(protocol.constData(), protocol.size() * sizeof(QChar)));
|
||||
|
|
@ -2087,6 +2099,7 @@ EntitiesInText ConvertTextTagsToEntities(const TextWithTags::Tags &tags) {
|
|||
EntityType::Italic,
|
||||
EntityType::Underline,
|
||||
EntityType::StrikeOut,
|
||||
EntityType::Spoiler,
|
||||
EntityType::Code,
|
||||
EntityType::Pre,
|
||||
};
|
||||
|
|
@ -2193,6 +2206,8 @@ EntitiesInText ConvertTextTagsToEntities(const TextWithTags::Tags &tags) {
|
|||
result.set(EntityType::Code);
|
||||
} else if (single == Ui::InputField::kTagPre) {
|
||||
result.set(EntityType::Pre);
|
||||
} else if (single == Ui::InputField::kTagSpoiler) {
|
||||
result.set(EntityType::Spoiler);
|
||||
} else {
|
||||
result.link = single.toString();
|
||||
}
|
||||
|
|
@ -2281,6 +2296,7 @@ TextWithTags::Tags ConvertEntitiesToTextTags(
|
|||
break;
|
||||
case EntityType::Code: push(Ui::InputField::kTagCode); break; // #TODO entities
|
||||
case EntityType::Pre: push(Ui::InputField::kTagPre); break;
|
||||
case EntityType::Spoiler: push(Ui::InputField::kTagSpoiler); break;
|
||||
}
|
||||
}
|
||||
if (!toRemove.empty()) {
|
||||
|
|
|
|||
|
|
@ -291,6 +291,8 @@ QString MarkdownCodeGoodBefore();
|
|||
QString MarkdownCodeBadAfter();
|
||||
QString MarkdownPreGoodBefore();
|
||||
QString MarkdownPreBadAfter();
|
||||
QString MarkdownSpoilerGoodBefore();
|
||||
QString MarkdownSpoilerBadAfter();
|
||||
|
||||
// Text preprocess.
|
||||
QString Clean(const QString &text);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ const auto &kTagUnderline = InputField::kTagUnderline;
|
|||
const auto &kTagStrikeOut = InputField::kTagStrikeOut;
|
||||
const auto &kTagCode = InputField::kTagCode;
|
||||
const auto &kTagPre = InputField::kTagPre;
|
||||
const auto &kTagSpoiler = InputField::kTagSpoiler;
|
||||
const auto kTagCheckLinkMeta = QString("^:/:/:^");
|
||||
const auto kNewlineChars = QString("\r\n")
|
||||
+ QChar(0xfdd0) // QTextBeginningOfFrame
|
||||
|
|
@ -230,6 +231,7 @@ constexpr auto kTagItalicIndex = 1;
|
|||
constexpr auto kTagStrikeOutIndex = 2;
|
||||
constexpr auto kTagCodeIndex = 3;
|
||||
constexpr auto kTagPreIndex = 4;
|
||||
constexpr auto kTagSpoilerIndex = 5;
|
||||
constexpr auto kInvalidPosition = std::numeric_limits<int>::max() / 2;
|
||||
|
||||
class TagSearchItem {
|
||||
|
|
@ -373,6 +375,13 @@ const std::vector<TagStartExpression> &TagStartExpressions() {
|
|||
TextUtilities::MarkdownPreBadAfter(),
|
||||
TextUtilities::MarkdownPreGoodBefore()
|
||||
},
|
||||
{
|
||||
kTagSpoiler,
|
||||
TextUtilities::MarkdownSpoilerGoodBefore(),
|
||||
TextUtilities::MarkdownSpoilerBadAfter(),
|
||||
TextUtilities::MarkdownSpoilerBadAfter(),
|
||||
TextUtilities::MarkdownSpoilerGoodBefore()
|
||||
},
|
||||
};
|
||||
return cached;
|
||||
}
|
||||
|
|
@ -385,6 +394,7 @@ const std::map<QString, int> &TagIndices() {
|
|||
{ kTagStrikeOut, kTagStrikeOutIndex },
|
||||
{ kTagCode, kTagCodeIndex },
|
||||
{ kTagPre, kTagPreIndex },
|
||||
{ kTagSpoiler, kTagSpoilerIndex },
|
||||
};
|
||||
return cached;
|
||||
}
|
||||
|
|
@ -702,6 +712,7 @@ QTextCharFormat PrepareTagFormat(
|
|||
auto result = QTextCharFormat();
|
||||
auto font = st.font;
|
||||
auto color = std::optional<style::color>();
|
||||
auto bg = std::optional<style::color>();
|
||||
const auto applyOne = [&](QStringView tag) {
|
||||
if (IsValidMarkdownLink(tag)) {
|
||||
color = st::defaultTextPalette.linkFg;
|
||||
|
|
@ -716,6 +727,8 @@ QTextCharFormat PrepareTagFormat(
|
|||
} else if (tag == kTagCode || tag == kTagPre) {
|
||||
color = st::defaultTextPalette.monoFg;
|
||||
font = font->monospace();
|
||||
} else if (tag == kTagSpoiler) {
|
||||
bg = st::defaultTextPalette.spoilerActiveBg;
|
||||
}
|
||||
};
|
||||
for (const auto &tag : TextUtilities::SplitTags(tag)) {
|
||||
|
|
@ -724,6 +737,9 @@ QTextCharFormat PrepareTagFormat(
|
|||
result.setFont(font);
|
||||
result.setForeground(color.value_or(st.textFg));
|
||||
result.setProperty(kTagProperty, tag);
|
||||
if (bg) {
|
||||
result.setBackground(*bg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -842,6 +858,7 @@ const QString InputField::kTagUnderline = QStringLiteral("^^");
|
|||
const QString InputField::kTagStrikeOut = QStringLiteral("~~");
|
||||
const QString InputField::kTagCode = QStringLiteral("`");
|
||||
const QString InputField::kTagPre = QStringLiteral("```");
|
||||
const QString InputField::kTagSpoiler = QStringLiteral("||");
|
||||
|
||||
class InputField::Inner final : public QTextEdit {
|
||||
public:
|
||||
|
|
@ -2819,6 +2836,8 @@ bool InputField::handleMarkdownKey(QKeyEvent *e) {
|
|||
toggleSelectionMarkdown(kTagStrikeOut);
|
||||
} else if (matches(kMonospaceSequence)) {
|
||||
toggleSelectionMarkdown(kTagCode);
|
||||
} else if (matches(kSpoilerSequence)) {
|
||||
toggleSelectionMarkdown(kTagSpoiler);
|
||||
} else if (matches(kClearFormatSequence)) {
|
||||
clearSelectionMarkdown();
|
||||
} else if (matches(kEditLinkSequence) && _editLinkCallback) {
|
||||
|
|
@ -3578,6 +3597,7 @@ void InputField::addMarkdownActions(
|
|||
addtag(integration.phraseFormattingUnderline(), QKeySequence::Underline, kTagUnderline);
|
||||
addtag(integration.phraseFormattingStrikeOut(), kStrikeOutSequence, kTagStrikeOut);
|
||||
addtag(integration.phraseFormattingMonospace(), kMonospaceSequence, kTagCode);
|
||||
addtag(integration.phraseFormattingSpoiler(), kSpoilerSequence, kTagSpoiler);
|
||||
|
||||
if (_editLinkCallback) {
|
||||
submenu->addSeparator();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ const auto kClearFormatSequence = QKeySequence("ctrl+shift+n");
|
|||
const auto kStrikeOutSequence = QKeySequence("ctrl+shift+x");
|
||||
const auto kMonospaceSequence = QKeySequence("ctrl+shift+m");
|
||||
const auto kEditLinkSequence = QKeySequence("ctrl+k");
|
||||
const auto kSpoilerSequence = QKeySequence("ctrl+shift+p");
|
||||
|
||||
class PopupMenu;
|
||||
|
||||
|
|
@ -171,6 +172,7 @@ public:
|
|||
static const QString kTagStrikeOut;
|
||||
static const QString kTagCode;
|
||||
static const QString kTagPre;
|
||||
static const QString kTagSpoiler;
|
||||
|
||||
InputField(
|
||||
QWidget *parent,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue