mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 15:17:07 +02:00
Add initial code syntax highlighting.
Thanks PrismJS and Fela for porting it to C++.
This commit is contained in:
parent
da768ac1d1
commit
2414e927bd
15 changed files with 112 additions and 5 deletions
Telegram
|
@ -1540,6 +1540,7 @@ elseif (APPLE)
|
|||
PRE_LINK
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
COMMAND cp ${CMAKE_BINARY_DIR}/lib_ui.rcc $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
COMMAND cp ${CMAKE_BINARY_DIR}/lib_spellcheck.rcc $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
)
|
||||
if (NOT build_macstore)
|
||||
add_custom_command(TARGET Telegram
|
||||
|
|
|
@ -80,6 +80,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/unixtime.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/random.h"
|
||||
#include "spellcheck/spellcheck_highlight_syntax.h"
|
||||
#include "styles/style_boxes.h" // st::backgroundSize
|
||||
|
||||
namespace Data {
|
||||
|
@ -300,6 +301,11 @@ Session::Session(not_null<Main::Session*> session)
|
|||
}
|
||||
}, _lifetime);
|
||||
|
||||
Spellchecker::HighlightReady(
|
||||
) | rpl::start_with_next([=](uint64 processId) {
|
||||
highlightProcessDone(processId);
|
||||
}, _lifetime);
|
||||
|
||||
subscribeForTopicRepliesLists();
|
||||
|
||||
crl::on_main(_session, [=] {
|
||||
|
@ -1760,6 +1766,27 @@ void Session::requestItemTextRefresh(not_null<HistoryItem*> item) {
|
|||
}
|
||||
}
|
||||
|
||||
void Session::registerHighlightProcess(
|
||||
uint64 processId,
|
||||
not_null<HistoryItem*> item) {
|
||||
Expects(item->inHighlightProcess());
|
||||
|
||||
const auto [i, ok] = _highlightings.emplace(processId, item);
|
||||
|
||||
Ensures(ok);
|
||||
}
|
||||
|
||||
void Session::highlightProcessDone(uint64 processId) {
|
||||
if (const auto done = _highlightings.take(processId)) {
|
||||
for (const auto &[id, item] : _highlightings) {
|
||||
if (item == *done) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
(*done)->highlightProcessDone();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::requestUnreadReactionsAnimation(not_null<HistoryItem*> item) {
|
||||
enumerateItemViews(item, [&](not_null<ViewElement*> view) {
|
||||
view->animateUnreadReactions();
|
||||
|
@ -2415,6 +2442,13 @@ void Session::unregisterMessage(not_null<HistoryItem*> item) {
|
|||
Data::MessageUpdate::Flag::Destroyed);
|
||||
groups().unregisterMessage(item);
|
||||
removeDependencyMessage(item);
|
||||
for (auto i = begin(_highlightings); i != end(_highlightings);) {
|
||||
if (i->second == item) {
|
||||
i = _highlightings.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
messagesListForInsert(peerId)->erase(itemId);
|
||||
|
||||
if (!peerIsChannel(peerId) && IsServerMsgId(itemId)) {
|
||||
|
|
|
@ -299,6 +299,10 @@ public:
|
|||
void notifyPinnedDialogsOrderUpdated();
|
||||
[[nodiscard]] rpl::producer<> pinnedDialogsOrderUpdated() const;
|
||||
|
||||
void registerHighlightProcess(
|
||||
uint64 processId,
|
||||
not_null<HistoryItem*> item);
|
||||
|
||||
void registerHeavyViewPart(not_null<ViewElement*> view);
|
||||
void unregisterHeavyViewPart(not_null<ViewElement*> view);
|
||||
void unloadHeavyViewParts(
|
||||
|
@ -845,6 +849,7 @@ private:
|
|||
TimeId date);
|
||||
|
||||
void setWallpapers(const QVector<MTPWallPaper> &data, uint64 hash);
|
||||
void highlightProcessDone(uint64 processId);
|
||||
|
||||
void checkPollsClosings();
|
||||
|
||||
|
@ -955,6 +960,7 @@ private:
|
|||
std::unordered_map<
|
||||
FullStoryId,
|
||||
base::flat_set<not_null<HistoryItem*>>> _storyItems;
|
||||
base::flat_map<uint64, not_null<HistoryItem*>> _highlightings;
|
||||
|
||||
base::flat_set<not_null<WebPageData*>> _webpagesUpdated;
|
||||
base::flat_set<not_null<GameData*>> _gamesUpdated;
|
||||
|
|
|
@ -303,6 +303,8 @@ enum class MessageFlag : uint64 {
|
|||
FakeBotAbout = (1ULL << 36),
|
||||
|
||||
StoryItem = (1ULL << 37),
|
||||
|
||||
InHighlightProcess = (1ULL << 38),
|
||||
};
|
||||
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
||||
using MessageFlags = base::flags<MessageFlag>;
|
||||
|
|
|
@ -67,6 +67,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_web_page.h"
|
||||
#include "chat_helpers/stickers_gift_box_pack.h"
|
||||
#include "payments/payments_checkout_process.h" // CheckoutProcess::Start.
|
||||
#include "spellcheck/spellcheck_highlight_syntax.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
namespace {
|
||||
|
@ -2871,15 +2872,32 @@ void HistoryItem::setText(const TextWithEntities &textWithEntities) {
|
|||
: std::move(textWithEntities));
|
||||
}
|
||||
|
||||
void HistoryItem::setTextValue(TextWithEntities text) {
|
||||
void HistoryItem::setTextValue(TextWithEntities text, bool force) {
|
||||
if (const auto processId = Spellchecker::TryHighlightSyntax(text)) {
|
||||
_flags |= MessageFlag::InHighlightProcess;
|
||||
history()->owner().registerHighlightProcess(processId, this);
|
||||
}
|
||||
const auto had = !_text.empty();
|
||||
_text = std::move(text);
|
||||
RemoveComponents(HistoryMessageTranslation::Bit());
|
||||
if (had) {
|
||||
if (had || force) {
|
||||
history()->owner().requestItemTextRefresh(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryItem::inHighlightProcess() const {
|
||||
return _flags & MessageFlag::InHighlightProcess;
|
||||
}
|
||||
|
||||
void HistoryItem::highlightProcessDone() {
|
||||
Expects(inHighlightProcess());
|
||||
|
||||
_flags &= ~MessageFlag::InHighlightProcess;
|
||||
if (!_text.empty()) {
|
||||
setTextValue(base::take(_text), true);
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryItem::showNotification() const {
|
||||
const auto channel = _history->peer->asChannel();
|
||||
if (channel && !channel->amIn()) {
|
||||
|
|
|
@ -322,6 +322,8 @@ public:
|
|||
[[nodiscard]] bool repliesAreComments() const;
|
||||
[[nodiscard]] bool externalReply() const;
|
||||
[[nodiscard]] bool hasExtendedMediaPreview() const;
|
||||
[[nodiscard]] bool inHighlightProcess() const;
|
||||
void highlightProcessDone();
|
||||
|
||||
void setCommentsInboxReadTill(MsgId readTillId);
|
||||
void setCommentsMaxId(MsgId maxId);
|
||||
|
@ -537,7 +539,7 @@ private:
|
|||
[[nodiscard]] bool generateLocalEntitiesByReply() const;
|
||||
[[nodiscard]] TextWithEntities withLocalEntities(
|
||||
const TextWithEntities &textWithEntities) const;
|
||||
void setTextValue(TextWithEntities text);
|
||||
void setTextValue(TextWithEntities text, bool force = false);
|
||||
[[nodiscard]] bool isTooOldForEdit(TimeId now) const;
|
||||
[[nodiscard]] bool isLegacyMessage() const {
|
||||
return _flags & MessageFlag::Legacy;
|
||||
|
|
|
@ -1622,6 +1622,7 @@ void Message::paintText(
|
|||
.position = trect.topLeft(),
|
||||
.availableWidth = trect.width(),
|
||||
.palette = &stm->textPalette,
|
||||
.colors = context.st->highlightColors(),
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
|
|
|
@ -748,6 +748,7 @@ void Document::draw(
|
|||
.position = { st::msgPadding.left(), captiontop },
|
||||
.availableWidth = captionw,
|
||||
.palette = &stm->textPalette,
|
||||
.colors = context.st->highlightColors(),
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
|
|
|
@ -235,6 +235,7 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
|
|||
painty + painth + st::mediaCaptionSkip),
|
||||
.availableWidth = captionw,
|
||||
.palette = &stm->textPalette,
|
||||
.colors = context.st->highlightColors(),
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
|
|
|
@ -709,6 +709,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
|
|||
.position = QPoint(st::msgPadding.left(), top),
|
||||
.availableWidth = captionw,
|
||||
.palette = &stm->textPalette,
|
||||
.colors = context.st->highlightColors(),
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
|
|
|
@ -405,6 +405,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
|
|||
.position = QPoint(st::msgPadding.left(), top),
|
||||
.availableWidth = captionw,
|
||||
.palette = &stm->textPalette,
|
||||
.colors = context.st->highlightColors(),
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
|
|
|
@ -446,6 +446,41 @@ void ChatStyle::applyAdjustedServiceBg(QColor serviceBg) {
|
|||
msgServiceBg().set(uchar(r), uchar(g), uchar(b), uchar(a));
|
||||
}
|
||||
|
||||
std::span<Ui::Text::SpecialColor> ChatStyle::highlightColors() const {
|
||||
if (_highlightColors.empty()) {
|
||||
const auto push = [&](const style::color &color) {
|
||||
_highlightColors.push_back({ &color->p, &color->p });
|
||||
};
|
||||
|
||||
// comment, block-comment, prolog, doctype, cdata
|
||||
push(statisticsChartLineLightblue());
|
||||
|
||||
// punctuation
|
||||
push(statisticsChartLineRed());
|
||||
|
||||
// property, tag, boolean, number,
|
||||
// constant, symbol, deleted
|
||||
push(statisticsChartLineRed());
|
||||
|
||||
// selector, attr-name, string, char, builtin, inserted
|
||||
push(statisticsChartLineOrange());
|
||||
|
||||
// operator, entity, url
|
||||
push(statisticsChartLineRed());
|
||||
|
||||
// atrule, attr-value, keyword, function
|
||||
push(statisticsChartLineBlue());
|
||||
|
||||
// class-name
|
||||
push(statisticsChartLinePurple());
|
||||
|
||||
//push(statisticsChartLineLightgreen());
|
||||
//push(statisticsChartLineGreen());
|
||||
//push(statisticsChartLineGolden());
|
||||
}
|
||||
return _highlightColors;
|
||||
}
|
||||
|
||||
void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
|
||||
*static_cast<style::palette*>(this) = *palette;
|
||||
style::internal::resetIcons();
|
||||
|
|
|
@ -168,6 +168,8 @@ public:
|
|||
void applyCustomPalette(const style::palette *palette);
|
||||
void applyAdjustedServiceBg(QColor serviceBg);
|
||||
|
||||
[[nodiscard]] std::span<Ui::Text::SpecialColor> highlightColors() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<> paletteChanged() const {
|
||||
return _paletteChanged.events();
|
||||
}
|
||||
|
@ -332,6 +334,8 @@ private:
|
|||
mutable CornersPixmaps _msgSelectOverlayCorners[
|
||||
int(CachedCornerRadius::kCount)];
|
||||
|
||||
mutable std::vector<Ui::Text::SpecialColor> _highlightColors;
|
||||
|
||||
style::TextPalette _historyPsaForwardPalette;
|
||||
style::TextPalette _imgReplyTextPalette;
|
||||
style::TextPalette _serviceTextPalette;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ab2a9d1c19b948a05b216801f8ba4fea0759428a
|
||||
Subproject commit a9fb0310132bc645ffcfb3734bd2ca53f1fb39fa
|
|
@ -1 +1 @@
|
|||
Subproject commit 02440524eaa2b1bd6d1909ff4aa2ca207a282b2c
|
||||
Subproject commit 0d8717d48ac3f2228399a1de78a28f0a7bbd0023
|
Loading…
Add table
Reference in a new issue