Блоки кода как в Telegram (скрин): тёмно-синий пузырь #3b5a7a, время и галочки
- Bubble: background #3b5a7a (как на скрине #2e4d6a), radius 12, padding 10/14/6, max-width 88%, shadow, язык uppercase #8a9ba8 10px слева, кнопка 📋 справа (rgba 0.15, radius 12, border 0.2)
- Код: контейнер rgba(0,0,0,0.18) radius 8, padding 10/12, JetBrains Mono 13px/1.45/tab-size 4, color #fff, подсветка форсирована тёмной темой (highlight(...,true) -> Breeze Dark)
- Время: QTime::currentTime hh:mm + ✓✓ #5eb1f6 внизу справа, как в сообщении ТГ (20:31 ✓✓)
- Сохранено автовыравнивание/скобки/отступы из предыдущего коммита (Tab 4 пробела, Enter сохраняет indent, Backspace удаляет 4, авто-закрытие ()[]{}''""<> и </tag>)
This commit is contained in:
+33
-32
@@ -23,6 +23,7 @@
|
|||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QTime>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
using KSyntaxHighlighting::AbstractHighlighter;
|
using KSyntaxHighlighting::AbstractHighlighter;
|
||||||
@@ -194,7 +195,7 @@ public:
|
|||||||
m_segments.append(seg);
|
m_segments.append(seg);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString highlight(const QString &code, const QString &lang)
|
QString highlight(const QString &code, const QString &lang, bool forceDark = false)
|
||||||
{
|
{
|
||||||
m_segments.clear();
|
m_segments.clear();
|
||||||
Definition def = m_repo->definitionForName(lang);
|
Definition def = m_repo->definitionForName(lang);
|
||||||
@@ -203,10 +204,11 @@ public:
|
|||||||
setDefinition(def);
|
setDefinition(def);
|
||||||
// Выбираем тему подсветки в зависимости от темы приложения (тёмная/светлая)
|
// Выбираем тему подсветки в зависимости от темы приложения (тёмная/светлая)
|
||||||
Theme chosen = m_repo->defaultTheme();
|
Theme chosen = m_repo->defaultTheme();
|
||||||
// Попытка получить тему из настроек (ui/theme)
|
// Попытка получить тему из настроек (ui/theme) или форсировать тёмную для пузырей
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
if (s.value("ui/theme").toString() == "dark") {
|
bool wantDark = forceDark || s.value("ui/theme").toString() == "dark";
|
||||||
|
if (wantDark) {
|
||||||
for (auto t : m_repo->themes()) {
|
for (auto t : m_repo->themes()) {
|
||||||
if (t.name().contains("dark", Qt::CaseInsensitive) || t.name().contains("Dark")) {
|
if (t.name().contains("dark", Qt::CaseInsensitive) || t.name().contains("Dark")) {
|
||||||
chosen = t;
|
chosen = t;
|
||||||
@@ -476,47 +478,46 @@ private:
|
|||||||
const char *info = cmark_node_get_fence_info(n);
|
const char *info = cmark_node_get_fence_info(n);
|
||||||
const QString lang = normalizeLang(QString::fromUtf8(info ? info : ""));
|
const QString lang = normalizeLang(QString::fromUtf8(info ? info : ""));
|
||||||
const QString code = QString::fromUtf8(cmark_node_get_literal(n));
|
const QString code = QString::fromUtf8(cmark_node_get_literal(n));
|
||||||
CodeHighlighter hl(m_repo);
|
// Telegram-стиль как на скрине: тёмно-синий пузырь (#2e4d6a) с кодом, время и галочки внизу справа
|
||||||
const QString highlighted = hl.highlight(code, lang);
|
// Сохраняем оригинал для копирования
|
||||||
|
|
||||||
// сохраняем оригинал для копирования
|
|
||||||
QString codeId;
|
QString codeId;
|
||||||
if (m_impl) {
|
if (m_impl) {
|
||||||
codeId = QStringLiteral("code_%1").arg(m_impl->codeCounter++);
|
codeId = QStringLiteral("code_%1").arg(m_impl->codeCounter++);
|
||||||
m_impl->codeBlocks.insert(codeId, code);
|
m_impl->codeBlocks.insert(codeId, code);
|
||||||
}
|
}
|
||||||
|
// Форсируем тёмную тему подсветки для контраста на синем фоне Telegram-пузыря
|
||||||
// Telegram-стиль: пузырь сообщения с кодом, как в мессенджере
|
CodeHighlighter hl(m_repo);
|
||||||
QSettings s;
|
const QString highlighted = hl.highlight(code, lang, true);
|
||||||
const bool isDark = s.value("ui/theme").toString() == "dark";
|
// Переопределяем lang после highlight (highlight уже сделал)
|
||||||
// Telegram-like цвета: светлая — #f5f5f7, тёмная — #1a1a1a / #212121
|
|
||||||
const QString bg = isDark ? "#212121" : "#f5f5f7";
|
|
||||||
const QString headerBg = isDark ? "#2a2a2a" : "#e8e8ea";
|
|
||||||
const QString headerBorder = isDark ? "#333333" : "#d0d0d0";
|
|
||||||
const QString headerText = isDark ? "#8e8e93" : "#6d6d72";
|
|
||||||
const QString codeTextColor = isDark ? "#e0e0e0" : "#24292f";
|
|
||||||
const QString langDisplay = lang.isEmpty() ? "text" : esc(lang);
|
const QString langDisplay = lang.isEmpty() ? "text" : esc(lang);
|
||||||
const QString cls = lang.isEmpty() ? QString() : QStringLiteral(" class=\"language-%1\"").arg(esc(lang));
|
const QString cls = lang.isEmpty() ? QString() : QStringLiteral(" class=\"language-%1\"").arg(esc(lang));
|
||||||
// Кнопка копирования - Telegram стиль: маленькая, с hover/active
|
|
||||||
const QString copyBtnStyle = isDark
|
|
||||||
? "display:inline-block;background:#333333;color:#8e8e93;text-decoration:none;font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid #404040;font-family: -apple-system, sans-serif;"
|
|
||||||
: "display:inline-block;background:#ffffff;color:#0088cc;text-decoration:none;font-size:12px;padding:4px 10px;border-radius:6px;border:1px solid #d0d0d0;font-family: -apple-system, sans-serif;";
|
|
||||||
const QString copyLink = codeId.isEmpty() ? QString()
|
|
||||||
: QStringLiteral("<a href=\"flora://copycode/%1\" style=\"%2\" title=\"Копировать\">📋 Копировать</a>").arg(codeId, copyBtnStyle);
|
|
||||||
|
|
||||||
// Пузырь как в Telegram: скругления 12px, тень, граница, header отделен
|
// Время как в Telegram — текущее время рендера (можно заменить на lastModified)
|
||||||
|
const QString timeStr = QTime::currentTime().toString("hh:mm");
|
||||||
|
// Telegram bubble: #3a5068 или #2e4d6a, скругления 12, тень, max-width 85%
|
||||||
|
const QString bubbleBg = "#3b5a7a"; // тёмно-синий как на скрине #2e4d6a → #3b5a7a чуть светлее
|
||||||
|
const QString codeColor = "#ffffff";
|
||||||
|
// Кнопка копирования — в правом верхнем углу пузыря, как в ТГ при наведении
|
||||||
|
// Делаем её заметной: полупрозрачная, скруглённая, с hover/active через CSS
|
||||||
|
const QString copyLink = codeId.isEmpty() ? QString()
|
||||||
|
: QStringLiteral("<a href=\"flora://copycode/%1\" style=\"display:inline-block;background:rgba(255,255,255,0.15);color:#ffffff;text-decoration:none;font-size:12px;padding:3px 8px;border-radius:12px;border:1px solid rgba(255,255,255,0.2);font-family:-apple-system,sans-serif;\" title=\"Копировать\">📋</a>").arg(codeId);
|
||||||
|
|
||||||
|
// Пузырь Telegram: используем таблицу для совместимости с QTextDocument (не поддерживает position:absolute)
|
||||||
|
// Верхняя строка — язык слева и кнопка справа, средняя — код, нижняя — время и галочки справа
|
||||||
return QStringLiteral(
|
return QStringLiteral(
|
||||||
"<div style=\"background:%1;border:1px solid %2;border-radius:12px;overflow:hidden;margin:16px 0;box-shadow:0 1px 2px rgba(0,0,0,0.08)\">"
|
"<div style=\"background:%1;border-radius:12px;padding:10px 14px 6px 14px;margin:12px 0;max-width:88%%;box-shadow:0 1px 2px rgba(0,0,0,0.15)\">"
|
||||||
"<div style=\"background:%3;padding:7px 12px;border-bottom:1px solid %2\">"
|
"<table width=\"100%%\" cellspacing=\"0\" cellpadding=\"0\" style=\"margin-bottom:6px\">"
|
||||||
"<table width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tr>"
|
"<tr>"
|
||||||
"<td style=\"text-align:left;color:%4;font-size:11px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;\">%5</td>"
|
"<td style=\"text-align:left;color:#8a9ba8;font-size:10px;font-weight:600;letter-spacing:0.4px;text-transform:uppercase;opacity:0.9\">%2</td>"
|
||||||
"<td style=\"text-align:right\">%6</td>"
|
"<td style=\"text-align:right\">%3</td>"
|
||||||
"</tr></table>"
|
"</tr></table>"
|
||||||
|
"<div style=\"background:rgba(0,0,0,0.18);border-radius:8px;padding:10px 12px;margin:6px 0 8px 0\">"
|
||||||
|
"<pre style=\"margin:0;font-family:'JetBrains Mono','Fira Code','Menlo',Consolas,monospace;font-size:13px;line-height:1.45;tab-size:4;color:%4;white-space:pre-wrap;word-wrap:break-word\">"
|
||||||
|
"<code%6>%5</code></pre>"
|
||||||
"</div>"
|
"</div>"
|
||||||
"<div style=\"background:%1;padding:12px 14px;overflow-x:auto\"><pre style=\"margin:0;font-family:'JetBrains Mono','Fira Code','Menlo','Consolas',monospace;font-size:13px;line-height:1.5;tab-size:4;color:%7;white-space:pre-wrap;word-wrap:break-word\">"
|
"<div style=\"text-align:right;color:#8a9ba8;font-size:11px;margin-top:2px;opacity:0.95\">%7 <span style=\"color:#5eb1f6\">✓✓</span></div>"
|
||||||
"<code%9>%8</code></pre></div>"
|
|
||||||
"</div>"
|
"</div>"
|
||||||
).arg(bg, headerBorder, headerBg, headerText, langDisplay, copyLink, codeTextColor, highlighted, cls);
|
).arg(bubbleBg, langDisplay, copyLink, codeColor, highlighted, cls, timeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString inlineAll(cmark_node *n)
|
QString inlineAll(cmark_node *n)
|
||||||
|
|||||||
Reference in New Issue
Block a user