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";
|
return "Monospace";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Integration::phraseFormattingSpoiler() {
|
||||||
|
return "Spoiler";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue