mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-11 22:23:49 +00:00
Improve details/summary design.
This commit is contained in:
@@ -688,10 +688,16 @@ HistoryItem::HistoryItem(
|
||||
const auto dropText = fields.ignoreForwardCaptions
|
||||
&& _media
|
||||
&& (_media->allowsEditCaption() || _media->poll());
|
||||
const auto forwardRichPage = dropText
|
||||
? std::shared_ptr<const Iv::RichPage>()
|
||||
: original->richPage();
|
||||
const auto forwardText = [&] {
|
||||
if (dropText) {
|
||||
return TextWithEntities();
|
||||
}
|
||||
if (forwardRichPage) {
|
||||
return Iv::FlattenRichPageSummary(forwardRichPage);
|
||||
}
|
||||
const auto &text = original->originalText();
|
||||
if (!text.text.isEmpty()) {
|
||||
return dropForwardInfo
|
||||
@@ -703,6 +709,9 @@ HistoryItem::HistoryItem(
|
||||
}
|
||||
return TextWithEntities();
|
||||
}();
|
||||
if (forwardRichPage) {
|
||||
setRichPage(forwardRichPage);
|
||||
}
|
||||
setText(forwardText);
|
||||
|
||||
if (fields.groupedId) {
|
||||
|
||||
@@ -418,7 +418,7 @@ defaultMarkdownDetails: MarkdownDetails {
|
||||
summaryFg: windowFg;
|
||||
radius: 6px;
|
||||
summaryStyle: defaultMarkdownDetailsSummaryStyle;
|
||||
icon: icon {{ "history_comments_open", windowSubTextFg }};
|
||||
icon: icon {{ "history_down_arrow", windowSubTextFg }};
|
||||
iconSkip: 8px;
|
||||
}
|
||||
defaultMarkdownEmbedPostAuthorStyle: TextStyle(defaultMarkdownBodyStyle) {
|
||||
@@ -709,10 +709,8 @@ messageMarkdownHeading6Style: TextStyle(messageMarkdownBodyStyle) {
|
||||
font: font(14px semibold);
|
||||
lineHeight: 19px;
|
||||
}
|
||||
messageMarkdownDetailsSummaryStyle: TextStyle(defaultTextStyle) {
|
||||
font: font(11px);
|
||||
messageMarkdownDetailsSummaryStyle: TextStyle(messageMarkdownBodyStyle) {
|
||||
linkUnderline: kLinkUnderlineNever;
|
||||
lineHeight: 16px;
|
||||
}
|
||||
messageMarkdownAudioTitleStyle: TextStyle(messageMarkdownBodyStyle) {
|
||||
font: font(14px semibold);
|
||||
@@ -739,15 +737,15 @@ messageMarkdownBlockSkips: MarkdownBlockSkips {
|
||||
placeholder: 8px;
|
||||
}
|
||||
messageMarkdownQuoteBgOpacity: 0.12;
|
||||
messageMarkdownDetailsIcon: icon{{ "history_comments_open", msgInReplyBarColor }};
|
||||
messageMarkdownDetailsIcon: icon{{ "history_down_arrow", msgInDateFg }};
|
||||
messageMarkdownDetailsIconSelected: icon{{
|
||||
"history_comments_open",
|
||||
msgInReplyBarSelColor
|
||||
"history_down_arrow",
|
||||
msgInDateFgSelected
|
||||
}};
|
||||
messageMarkdownDetailsIconOut: icon{{ "history_comments_open", msgOutReplyBarColor }};
|
||||
messageMarkdownDetailsIconOut: icon{{ "history_down_arrow", msgOutDateFg }};
|
||||
messageMarkdownDetailsIconOutSelected: icon{{
|
||||
"history_comments_open",
|
||||
msgOutReplyBarSelColor
|
||||
"history_down_arrow",
|
||||
msgOutDateFgSelected
|
||||
}};
|
||||
messageMarkdownNavPreviousIcon: icon{{ "box_button_back", msgInDateFg }};
|
||||
messageMarkdownNavPreviousIconSelected: icon{{
|
||||
@@ -810,14 +808,14 @@ messageMarkdownDisplayMath: MarkdownDisplayMath(defaultMarkdownDisplayMath) {
|
||||
overflowFg: msgInDateFg;
|
||||
}
|
||||
messageMarkdownDetails: MarkdownDetails(defaultMarkdownDetails) {
|
||||
headerPadding: margins(6px, 8px, 6px, 8px);
|
||||
bodyPadding: margins(8px, 8px, 8px, 8px);
|
||||
headerPadding: margins(4px, 11px, 4px, 11px);
|
||||
bodyPadding: margins(4px, 11px, 6px, 11px);
|
||||
bodyBg: msgInBg;
|
||||
summaryFg: historyTextInFg;
|
||||
radius: 8px;
|
||||
summaryStyle: messageMarkdownDetailsSummaryStyle;
|
||||
icon: messageMarkdownDetailsIcon;
|
||||
iconSkip: 6px;
|
||||
iconSkip: 8px;
|
||||
}
|
||||
messageMarkdownPhoto: MarkdownPhoto(defaultMarkdownPhoto) {
|
||||
captionSkip: 8px;
|
||||
|
||||
@@ -612,6 +612,10 @@ int BlockSkip(
|
||||
const PreparedBlock &block,
|
||||
LayoutContext context,
|
||||
const style::Markdown &st) {
|
||||
if (previous.kind == PreparedBlockKind::Details
|
||||
&& block.kind == PreparedBlockKind::Details) {
|
||||
return 0;
|
||||
}
|
||||
if (context.tightList
|
||||
&& IsFlowKind(previous.kind)
|
||||
&& IsFlowKind(block.kind)) {
|
||||
|
||||
@@ -53,18 +53,18 @@ namespace {
|
||||
case PreparedBlockKind::Channel:
|
||||
case PreparedBlockKind::GroupedMedia:
|
||||
case PreparedBlockKind::RelatedArticle:
|
||||
case PreparedBlockKind::Rule:
|
||||
case PreparedBlockKind::Details:
|
||||
return true;
|
||||
case PreparedBlockKind::Paragraph:
|
||||
case PreparedBlockKind::Thinking:
|
||||
case PreparedBlockKind::Heading:
|
||||
case PreparedBlockKind::CodeBlock:
|
||||
case PreparedBlockKind::Rule:
|
||||
case PreparedBlockKind::List:
|
||||
case PreparedBlockKind::ListItem:
|
||||
case PreparedBlockKind::Quote:
|
||||
case PreparedBlockKind::DisplayMath:
|
||||
case PreparedBlockKind::Table:
|
||||
case PreparedBlockKind::Details:
|
||||
case PreparedBlockKind::Placeholder:
|
||||
case PreparedBlockKind::EmbedPost:
|
||||
return false;
|
||||
@@ -460,18 +460,35 @@ void PrepareNestedContext(
|
||||
block.collapsed = prepared.collapsed;
|
||||
block.supplementary = prepared.supplementary;
|
||||
const auto &details = st.details;
|
||||
const auto headerPadding = context.useArticleBands
|
||||
? QMargins(
|
||||
st.textPadding.left(),
|
||||
details.headerPadding.top(),
|
||||
st.textPadding.right(),
|
||||
details.headerPadding.bottom())
|
||||
: details.headerPadding;
|
||||
const auto bodyPadding = context.useArticleBands
|
||||
? QMargins(
|
||||
st.textPadding.left(),
|
||||
details.bodyPadding.top(),
|
||||
st.textPadding.right(),
|
||||
details.bodyPadding.bottom())
|
||||
: details.bodyPadding;
|
||||
const auto headerWidth = std::max(width, 1);
|
||||
const auto iconWidth = details.icon.width();
|
||||
const auto iconHeight = details.icon.height();
|
||||
const auto iconSize = details.icon.empty()
|
||||
? 0
|
||||
: TextLineHeight(details.summaryStyle);
|
||||
const auto iconWidth = iconSize;
|
||||
const auto iconHeight = iconSize;
|
||||
const auto iconSkip = iconWidth ? details.iconSkip : 0;
|
||||
const auto textLeft = left
|
||||
+ details.headerPadding.left()
|
||||
+ headerPadding.left()
|
||||
+ iconWidth
|
||||
+ iconSkip;
|
||||
block.textWidth = std::max(
|
||||
headerWidth
|
||||
- details.headerPadding.left()
|
||||
- details.headerPadding.right()
|
||||
- headerPadding.left()
|
||||
- headerPadding.right()
|
||||
- iconWidth
|
||||
- iconSkip,
|
||||
1);
|
||||
@@ -491,20 +508,20 @@ void PrepareNestedContext(
|
||||
block.leaf.countHeight(block.textWidth, true),
|
||||
TextLineHeight(details.summaryStyle));
|
||||
const auto headerContentHeight = std::max(summaryHeight, iconHeight);
|
||||
const auto headerHeight = details.headerPadding.top()
|
||||
const auto headerHeight = headerPadding.top()
|
||||
+ headerContentHeight
|
||||
+ details.headerPadding.bottom();
|
||||
+ headerPadding.bottom();
|
||||
block.headerRect = QRect(left, top, headerWidth, headerHeight);
|
||||
if (iconWidth > 0 && iconHeight > 0) {
|
||||
block.iconRect = QRect(
|
||||
left + details.headerPadding.left(),
|
||||
left + headerPadding.left(),
|
||||
top + (headerHeight - iconHeight) / 2,
|
||||
iconWidth,
|
||||
iconHeight);
|
||||
}
|
||||
block.textRect = QRect(
|
||||
textLeft,
|
||||
top + details.headerPadding.top()
|
||||
top + headerPadding.top()
|
||||
+ std::max((headerContentHeight - summaryHeight) / 2, 0),
|
||||
block.textWidth,
|
||||
summaryHeight);
|
||||
@@ -515,12 +532,12 @@ void PrepareNestedContext(
|
||||
|
||||
auto bottom = top + headerHeight;
|
||||
if (!prepared.collapsed) {
|
||||
const auto childLeft = left + details.bodyPadding.left();
|
||||
const auto childTop = bottom + details.bodyPadding.top();
|
||||
const auto childLeft = left + bodyPadding.left();
|
||||
const auto childTop = bottom + bodyPadding.top();
|
||||
const auto childWidth = std::max(
|
||||
headerWidth
|
||||
- details.bodyPadding.left()
|
||||
- details.bodyPadding.right(),
|
||||
- bodyPadding.left()
|
||||
- bodyPadding.right(),
|
||||
1);
|
||||
auto childContext = context;
|
||||
PrepareNestedContext(&childContext, childLeft, childWidth);
|
||||
@@ -538,9 +555,9 @@ void PrepareNestedContext(
|
||||
childWidth,
|
||||
childContext);
|
||||
const auto contentHeight = std::max(childBottom - childTop, 0);
|
||||
const auto bodyHeight = details.bodyPadding.top()
|
||||
const auto bodyHeight = bodyPadding.top()
|
||||
+ contentHeight
|
||||
+ details.bodyPadding.bottom();
|
||||
+ bodyPadding.bottom();
|
||||
block.bodyRect = QRect(left, bottom, headerWidth, bodyHeight);
|
||||
block.contentRect = QRect(
|
||||
childLeft,
|
||||
|
||||
@@ -10,11 +10,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "iv/markdown/iv_markdown_article_text.h"
|
||||
#include "ui/dynamic_image.h"
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
#include "ui/effects/toggle_arrow.h"
|
||||
#include "ui/style/style_core_scale.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
|
||||
#include "styles/palette.h"
|
||||
#include "styles/style_iv.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
#include <QtGui/QPainterPath>
|
||||
@@ -409,6 +411,83 @@ void FillThinkingGradientImage(
|
||||
return WithOpacity(st.headerBg, st.headerBgOpacity);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool UseIncomingMessageDefaultPalette(
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
return !context.outbg
|
||||
&& (context.caches.st == &context.messageStyle()->richPageStyle);
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor ApplySelectedIncomingOverlay(
|
||||
QColor base,
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
if (!context.selected() || context.outbg) {
|
||||
return base;
|
||||
}
|
||||
auto overlay = context.st->msgSelectOverlay()->c;
|
||||
const auto alpha = overlay.alphaF();
|
||||
overlay.setAlpha(base.alpha());
|
||||
auto result = anim::color(base, overlay, alpha);
|
||||
result.setAlpha(base.alpha());
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor EffectiveTableHeaderBg(
|
||||
const style::Markdown &paintSt,
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
return UseIncomingMessageDefaultPalette(context)
|
||||
? ApplySelectedIncomingOverlay(
|
||||
TableHeaderBg(st::defaultMarkdown.table),
|
||||
context)
|
||||
: TableHeaderBg(paintSt.table);
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor EffectiveTableBorderFg(
|
||||
const style::Markdown &paintSt,
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
const auto useIncoming = UseIncomingMessageDefaultPalette(context);
|
||||
const auto &table = useIncoming
|
||||
? st::defaultMarkdown.table
|
||||
: paintSt.table;
|
||||
auto result = WithOpacity(table.borderFg, table.headerBgOpacity * 3);
|
||||
return useIncoming
|
||||
? ApplySelectedIncomingOverlay(result, context)
|
||||
: result;
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor EffectiveDividerFg(
|
||||
const style::Markdown &paintSt,
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
auto result = UseIncomingMessageDefaultPalette(context)
|
||||
? ApplySelectedIncomingOverlay(
|
||||
st::defaultMarkdown.rule.fg->c,
|
||||
context)
|
||||
: paintSt.rule.fg->c;
|
||||
if (context.outbg) {
|
||||
result.setAlphaF(result.alphaF() * 0.5);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PaintDetailsIcon(
|
||||
Painter &p,
|
||||
QRect rect,
|
||||
QColor color,
|
||||
bool collapsed) {
|
||||
const auto size = std::min(rect.width(), rect.height()) / 3.;
|
||||
if (size <= 0.) {
|
||||
return;
|
||||
}
|
||||
const auto center = QRectF(rect).center();
|
||||
const auto path = Ui::ToggleUpDownArrowPath(
|
||||
center.x(),
|
||||
center.y(),
|
||||
size,
|
||||
st::mainMenuToggleFourStrokes,
|
||||
collapsed ? 0. : 1.);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.fillPath(path, color);
|
||||
}
|
||||
|
||||
void RefreshBlockThumbnail(
|
||||
const LaidOutBlock &block,
|
||||
const MarkdownArticlePaintContext &context) {
|
||||
@@ -923,6 +1002,8 @@ void PaintWholeTable(
|
||||
const auto radius = st.table.radius;
|
||||
const auto shapePath = TableShapePath(block, border, radius);
|
||||
const auto &paintSt = PaintStyle(context, st);
|
||||
const auto headerBg = EffectiveTableHeaderBg(paintSt, context);
|
||||
const auto borderFg = EffectiveTableBorderFg(paintSt, context);
|
||||
|
||||
p.save();
|
||||
p.setClipRect(tableClip);
|
||||
@@ -937,7 +1018,7 @@ void PaintWholeTable(
|
||||
if (!cell.header && !striped) {
|
||||
continue;
|
||||
}
|
||||
p.fillRect(cell.outer, TableHeaderBg(paintSt.table));
|
||||
p.fillRect(cell.outer, headerBg);
|
||||
}
|
||||
}
|
||||
p.restore();
|
||||
@@ -945,11 +1026,7 @@ void PaintWholeTable(
|
||||
if (border > 0 && !block.tableRect.isEmpty()) {
|
||||
const auto path = TableBorderPath(block, border, shapePath);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
auto pen = QPen(
|
||||
WithOpacity(
|
||||
paintSt.table.borderFg,
|
||||
paintSt.table.headerBgOpacity * 3),
|
||||
border);
|
||||
auto pen = QPen(borderFg, border);
|
||||
p.setPen(pen);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawPath(path);
|
||||
@@ -1025,6 +1102,8 @@ void PaintTableRowBand(
|
||||
const auto radius = st.table.radius;
|
||||
const auto shapePath = TableShapePath(block, border, radius);
|
||||
const auto &paintSt = PaintStyle(context, st);
|
||||
const auto headerBg = EffectiveTableHeaderBg(paintSt, context);
|
||||
const auto borderFg = EffectiveTableBorderFg(paintSt, context);
|
||||
const auto cells = TableCellsForRowBand(ownership, rowIndex, rowBand);
|
||||
const auto rowContext = ClippedContext(
|
||||
RevealSuppressedContext(context),
|
||||
@@ -1042,18 +1121,14 @@ void PaintTableRowBand(
|
||||
if (!cell->header && !striped) {
|
||||
continue;
|
||||
}
|
||||
p.fillRect(cell->outer, TableHeaderBg(paintSt.table));
|
||||
p.fillRect(cell->outer, headerBg);
|
||||
}
|
||||
p.restore();
|
||||
|
||||
if (border > 0 && !block.tableRect.isEmpty()) {
|
||||
const auto path = TableBorderPath(block, border, shapePath);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
auto pen = QPen(
|
||||
WithOpacity(
|
||||
paintSt.table.borderFg,
|
||||
paintSt.table.headerBgOpacity * 3),
|
||||
border);
|
||||
auto pen = QPen(borderFg, border);
|
||||
p.setPen(pen);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawPath(path);
|
||||
@@ -1792,54 +1867,27 @@ void PaintDetailsBlock(
|
||||
|
||||
const auto &details = st.details;
|
||||
const auto &paintSt = PaintStyle(context, st);
|
||||
const auto &paintDetails = paintSt.details;
|
||||
const auto headerBg = TableHeaderBg(paintSt.table);
|
||||
const auto half = details.border / 2.;
|
||||
const auto outer = QRectF(block.outer).marginsRemoved({
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
});
|
||||
auto outerPath = QPainterPath();
|
||||
outerPath.addRoundedRect(outer, details.radius, details.radius);
|
||||
const auto lineHeight = details.border;
|
||||
const auto lineRect = QRect(
|
||||
block.outer.x(),
|
||||
block.outer.y() + block.outer.height() - lineHeight,
|
||||
block.outer.width(),
|
||||
lineHeight);
|
||||
const auto lineFg = EffectiveDividerFg(paintSt, context);
|
||||
|
||||
p.save();
|
||||
p.setClipRect(visible);
|
||||
{
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.fillPath(
|
||||
outerPath,
|
||||
paintDetails.bodyBg->c);
|
||||
p.save();
|
||||
p.setClipPath(outerPath, Qt::IntersectClip);
|
||||
p.fillRect(block.headerRect, TableHeaderBg(paintSt.table));
|
||||
auto pen = QPen(
|
||||
WithOpacity(
|
||||
paintSt.table.borderFg,
|
||||
paintSt.table.headerBgOpacity * 3),
|
||||
details.border);
|
||||
if (!block.bodyRect.isEmpty()) {
|
||||
p.setPen(pen);
|
||||
const auto separatorY = block.bodyRect.top() + half;
|
||||
p.drawLine(
|
||||
QPointF(outer.left(), separatorY),
|
||||
QPointF(outer.right(), separatorY));
|
||||
}
|
||||
p.restore();
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(pen);
|
||||
p.drawPath(outerPath);
|
||||
if (lineHeight > 0 && !lineRect.isEmpty()) {
|
||||
p.fillRect(lineRect, lineFg);
|
||||
}
|
||||
if (!block.iconRect.isEmpty()) {
|
||||
paintDetails.icon.paint(
|
||||
PaintDetailsIcon(
|
||||
p,
|
||||
block.iconRect.x(),
|
||||
block.iconRect.y(),
|
||||
outerWidth);
|
||||
block.iconRect,
|
||||
paintSt.supplementaryTextColor->c,
|
||||
block.collapsed);
|
||||
}
|
||||
p.setPen(paintDetails.summaryFg->c);
|
||||
p.setPen(paintSt.textColor->c);
|
||||
PaintTextLeaf(
|
||||
p,
|
||||
block.leaf,
|
||||
@@ -2020,8 +2068,8 @@ void PaintBlock(
|
||||
p,
|
||||
context,
|
||||
block.outer,
|
||||
[&](Painter &p, const MarkdownArticlePaintContext &) {
|
||||
p.fillRect(block.outer, paintSt.rule.fg->c);
|
||||
[&](Painter &p, const MarkdownArticlePaintContext &context) {
|
||||
p.fillRect(block.outer, EffectiveDividerFg(paintSt, context));
|
||||
});
|
||||
break;
|
||||
case PreparedBlockKind::List:
|
||||
|
||||
Reference in New Issue
Block a user