mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Improved view style of contacts.
This commit is contained in:
parent
52c779bffa
commit
93d1a187ca
4 changed files with 425 additions and 119 deletions
|
@ -4724,6 +4724,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_boosts_prepaid_giveaway_status#one" = "{count} subscription {duration}";
|
||||
"lng_boosts_prepaid_giveaway_status#other" = "{count} subscriptions {duration}";
|
||||
|
||||
"lng_contact_add" = "Add";
|
||||
"lng_contact_send_message" = "message";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||
|
|
|
@ -1253,7 +1253,7 @@ const SharedContact *MediaContact::sharedContact() const {
|
|||
}
|
||||
|
||||
TextWithEntities MediaContact::notificationText() const {
|
||||
return tr::lng_in_dlg_contact(tr::now, Ui::Text::WithEntities);
|
||||
return Ui::Text::Colorized(tr::lng_in_dlg_contact(tr::now));
|
||||
}
|
||||
|
||||
QString MediaContact::pinnedTextSubstring() const {
|
||||
|
|
|
@ -7,28 +7,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "history/view/media/history_view_contact.h"
|
||||
|
||||
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout/layout_selection.h"
|
||||
#include "mainwindow.h"
|
||||
#include "boxes/add_contact_box.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/text/format_values.h" // Ui::FormatPhone
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/painter.h"
|
||||
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_cloud_file.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "history/view/history_view_reply.h"
|
||||
#include "history/view/media/history_view_media_common.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/text/format_values.h" // Ui::FormatPhone
|
||||
#include "ui/text/text_options.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
||||
namespace HistoryView {
|
||||
namespace {
|
||||
|
@ -81,17 +80,32 @@ Contact::Contact(
|
|||
const QString &last,
|
||||
const QString &phone)
|
||||
: Media(parent)
|
||||
, _userId(userId)
|
||||
, _fname(first)
|
||||
, _lname(last)
|
||||
, _phone(Ui::FormatPhone(phone)) {
|
||||
, _st(st::historyPagePreview)
|
||||
, _pixh(st::contactsPhotoSize)
|
||||
, _userId(userId) {
|
||||
history()->owner().registerContactView(userId, parent);
|
||||
|
||||
_name.setText(
|
||||
st::semiboldTextStyle,
|
||||
tr::lng_full_name(tr::now, lt_first_name, first, lt_last_name, last).trimmed(),
|
||||
Ui::NameTextOptions());
|
||||
_phonew = st::normalFont->width(_phone);
|
||||
_nameLine.setText(
|
||||
st::webPageTitleStyle,
|
||||
tr::lng_full_name(
|
||||
tr::now,
|
||||
lt_first_name,
|
||||
first,
|
||||
lt_last_name,
|
||||
last).trimmed(),
|
||||
Ui::WebpageTextTitleOptions());
|
||||
|
||||
_phoneLine.setText(
|
||||
st::webPageDescriptionStyle,
|
||||
Ui::FormatPhone(QString(phone).replace(QChar('+'), QString())),
|
||||
Ui::WebpageTextTitleOptions());
|
||||
|
||||
#if 0 // No info.
|
||||
_infoLine.setText(
|
||||
st::webPageDescriptionStyle,
|
||||
phone,
|
||||
Ui::WebpageTextTitleOptions());
|
||||
#endif
|
||||
}
|
||||
|
||||
Contact::~Contact() {
|
||||
|
@ -111,121 +125,300 @@ void Contact::updateSharedContactUserId(UserId userId) {
|
|||
}
|
||||
|
||||
QSize Contact::countOptimalSize() {
|
||||
const auto item = _parent->data();
|
||||
auto maxWidth = st::msgFileMinWidth;
|
||||
|
||||
_contact = _userId
|
||||
? item->history()->owner().userLoaded(_userId)
|
||||
? _parent->data()->history()->owner().userLoaded(_userId)
|
||||
: nullptr;
|
||||
if (_contact) {
|
||||
_contact->loadUserpic();
|
||||
} else {
|
||||
const auto full = _name.toString();
|
||||
const auto full = _nameLine.toString();
|
||||
_photoEmpty = std::make_unique<Ui::EmptyUserpic>(
|
||||
Ui::EmptyUserpic::UserpicColor(Data::DecideColorIndex(_userId
|
||||
? peerFromUser(_userId)
|
||||
: Data::FakePeerIdForJustName(full))),
|
||||
full);
|
||||
}
|
||||
if (_contact && _contact->isContact()) {
|
||||
_linkl = SendMessageClickHandler(_contact);
|
||||
_link = tr::lng_profile_send_message(tr::now).toUpper();
|
||||
} else if (_userId) {
|
||||
_linkl = AddContactClickHandler(_parent->data());
|
||||
_link = tr::lng_profile_add_contact(tr::now).toUpper();
|
||||
}
|
||||
_linkw = _link.isEmpty() ? 0 : st::semiboldFont->width(_link);
|
||||
|
||||
const auto &st = _userId ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
|
||||
const auto tleft = st.padding.left() + st.thumbSize + st.thumbSkip;
|
||||
const auto tright = st.padding.right();
|
||||
if (_userId) {
|
||||
accumulate_max(maxWidth, tleft + _phonew + tright);
|
||||
_buttons.clear();
|
||||
if (_contact) {
|
||||
const auto message = tr::lng_contact_send_message(tr::now).toUpper();
|
||||
_buttons.push_back({
|
||||
message,
|
||||
st::semiboldFont->width(message),
|
||||
SendMessageClickHandler(_contact),
|
||||
});
|
||||
if (!_contact->isContact()) {
|
||||
const auto add = tr::lng_contact_add(tr::now).toUpper();
|
||||
_buttons.push_back({
|
||||
add,
|
||||
st::semiboldFont->width(add),
|
||||
AddContactClickHandler(_parent->data()),
|
||||
});
|
||||
}
|
||||
_mainButton.link = _buttons.front().link;
|
||||
} else {
|
||||
accumulate_max(maxWidth, tleft + _phonew + _parent->skipBlockWidth() + st::msgPadding.right());
|
||||
#if 0 // Can't view contact.
|
||||
const auto view = tr::lng_profile_add_contact(tr::now).toUpper();
|
||||
_buttons.push_back({
|
||||
view,
|
||||
st::semiboldFont->width(view),
|
||||
AddContactClickHandler(_parent->data()),
|
||||
});
|
||||
#endif
|
||||
_mainButton.link = nullptr;
|
||||
}
|
||||
|
||||
accumulate_max(maxWidth, tleft + _name.maxWidth() + tright);
|
||||
accumulate_min(maxWidth, st::msgMaxWidth);
|
||||
auto minHeight = st.padding.top() + st.thumbSize + st.padding.bottom();
|
||||
if (_parent->bottomInfoIsWide()) {
|
||||
minHeight += st::msgDateFont->height - st::msgDateDelta.y();
|
||||
const auto padding = inBubblePadding() + innerMargin();
|
||||
const auto full = Rect(currentSize());
|
||||
const auto outer = full - inBubblePadding();
|
||||
const auto inner = outer - innerMargin();
|
||||
const auto lineLeft = inner.left() + _pixh + inner.left() - outer.left();
|
||||
const auto lineHeight = UnitedLineHeight();
|
||||
|
||||
auto maxWidth = _parent->skipBlockWidth();
|
||||
auto minHeight = 0;
|
||||
|
||||
auto textMinHeight = 0;
|
||||
if (!_nameLine.isEmpty()) {
|
||||
accumulate_max(maxWidth, lineLeft + _nameLine.maxWidth());
|
||||
textMinHeight += 1 * lineHeight;
|
||||
}
|
||||
if (!isBubbleTop()) {
|
||||
minHeight -= st::msgFileTopMinus;
|
||||
if (!_phoneLine.isEmpty()) {
|
||||
accumulate_max(maxWidth, lineLeft + _phoneLine.maxWidth());
|
||||
textMinHeight += 1 * lineHeight;
|
||||
}
|
||||
if (!_infoLine.isEmpty()) {
|
||||
accumulate_max(maxWidth, lineLeft + _infoLine.maxWidth());
|
||||
textMinHeight += std::min(_infoLine.minHeight(), 1 * lineHeight);
|
||||
}
|
||||
minHeight = std::max(textMinHeight, st::contactsPhotoSize);
|
||||
|
||||
if (!_buttons.empty()) {
|
||||
auto buttonsWidth = rect::m::sum::h(st::historyPageButtonPadding);
|
||||
for (const auto &button : _buttons) {
|
||||
buttonsWidth += button.width;
|
||||
}
|
||||
accumulate_max(maxWidth, buttonsWidth);
|
||||
}
|
||||
maxWidth += rect::m::sum::h(padding);
|
||||
minHeight += rect::m::sum::v(padding);
|
||||
|
||||
return { maxWidth, minHeight };
|
||||
}
|
||||
|
||||
void Contact::draw(Painter &p, const PaintContext &context) const {
|
||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||
auto paintw = width();
|
||||
if (width() < rect::m::sum::h(st::msgPadding) + 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto st = context.st;
|
||||
const auto sti = context.imageStyle();
|
||||
const auto stm = context.messageStyle();
|
||||
|
||||
accumulate_min(paintw, maxWidth());
|
||||
const auto bubble = st::msgPadding;
|
||||
const auto full = Rect(currentSize());
|
||||
const auto outer = full - inBubblePadding();
|
||||
const auto inner = outer - innerMargin();
|
||||
auto tshift = inner.top();
|
||||
|
||||
const auto &st = _userId ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
const auto topMinus = isBubbleTop() ? 0 : st::msgFileTopMinus;
|
||||
const auto nameleft = st.padding.left() + st.thumbSize + st.thumbSkip;
|
||||
const auto nametop = st.nameTop - topMinus;
|
||||
const auto nameright = st.padding.right();
|
||||
const auto statustop = st.statusTop - topMinus;
|
||||
const auto linkshift = st::msgDateFont->height / 2;
|
||||
const auto linktop = st.linkTop - topMinus - linkshift;
|
||||
if (_userId) {
|
||||
QRect rthumb(style::rtlrect(st.padding.left(), st.padding.top() - topMinus, st.thumbSize, st.thumbSize, paintw));
|
||||
if (_contact) {
|
||||
const auto was = !_userpic.null();
|
||||
_contact->paintUserpic(p, _userpic, rthumb.x(), rthumb.y(), st.thumbSize);
|
||||
if (!was && !_userpic.null()) {
|
||||
history()->owner().registerHeavyViewPart(_parent);
|
||||
const auto selected = context.selected();
|
||||
const auto view = parent();
|
||||
const auto colorIndex = _contact
|
||||
? _contact->colorIndex()
|
||||
: Data::DecideColorIndex(
|
||||
Data::FakePeerIdForJustName(_nameLine.toString()));
|
||||
const auto cache = context.outbg
|
||||
? stm->replyCache[st->colorPatternIndex(colorIndex)].get()
|
||||
: st->coloredReplyCache(selected, colorIndex).get();
|
||||
const auto backgroundEmojiId = _contact
|
||||
? _contact->backgroundEmojiId()
|
||||
: DocumentId();
|
||||
const auto backgroundEmoji = backgroundEmojiId
|
||||
? st->backgroundEmojiData(backgroundEmojiId).get()
|
||||
: nullptr;
|
||||
const auto backgroundEmojiCache = backgroundEmoji
|
||||
? &backgroundEmoji->caches[Ui::BackgroundEmojiData::CacheIndex(
|
||||
selected,
|
||||
context.outbg,
|
||||
true,
|
||||
colorIndex + 1)]
|
||||
: nullptr;
|
||||
Ui::Text::ValidateQuotePaintCache(*cache, _st);
|
||||
Ui::Text::FillQuotePaint(p, outer, *cache, _st);
|
||||
if (backgroundEmoji) {
|
||||
ValidateBackgroundEmoji(
|
||||
backgroundEmojiId,
|
||||
backgroundEmoji,
|
||||
backgroundEmojiCache,
|
||||
cache,
|
||||
view);
|
||||
if (!backgroundEmojiCache->frames[0].isNull()) {
|
||||
const auto end = rect::bottom(inner) + _st.padding.bottom();
|
||||
const auto r = outer
|
||||
- QMargins(0, 0, 0, rect::bottom(outer) - end);
|
||||
FillBackgroundEmoji(p, r, false, *backgroundEmojiCache);
|
||||
}
|
||||
}
|
||||
|
||||
if (_mainButton.ripple) {
|
||||
_mainButton.ripple->paint(
|
||||
p,
|
||||
outer.x(),
|
||||
outer.y(),
|
||||
width(),
|
||||
&cache->bg);
|
||||
if (_mainButton.ripple->empty()) {
|
||||
_mainButton.ripple = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto left = inner.left();
|
||||
const auto top = tshift;
|
||||
if (_userId) {
|
||||
if (_contact) {
|
||||
const auto was = !_userpic.null();
|
||||
_contact->paintUserpic(p, _userpic, left, top, _pixh);
|
||||
if (!was && !_userpic.null()) {
|
||||
history()->owner().registerHeavyViewPart(_parent);
|
||||
}
|
||||
} else {
|
||||
_photoEmpty->paintCircle(p, left, top, _pixh, _pixh);
|
||||
}
|
||||
} else {
|
||||
_photoEmpty->paintCircle(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
||||
_photoEmpty->paintCircle(p, left, top, _pixh, _pixh);
|
||||
}
|
||||
if (context.selected()) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setBrush(p.textPalette().selectOverlay);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(rthumb);
|
||||
p.drawEllipse(left, top, _pixh, _pixh);
|
||||
}
|
||||
|
||||
bool over = ClickHandler::showAsActive(_linkl);
|
||||
p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont);
|
||||
p.setPen(stm->msgFileThumbLinkFg);
|
||||
p.drawTextLeft(nameleft, linktop, paintw, _link, _linkw);
|
||||
} else {
|
||||
_photoEmpty->paintCircle(p, st.padding.left(), st.padding.top() - topMinus, paintw, st.thumbSize);
|
||||
}
|
||||
const auto namewidth = paintw - nameleft - nameright;
|
||||
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(stm->historyFileNameFg);
|
||||
_name.drawLeftElided(p, nameleft, nametop, namewidth, paintw);
|
||||
const auto lineHeight = UnitedLineHeight();
|
||||
const auto lineLeft = inner.left() + _pixh + inner.left() - outer.left();
|
||||
const auto lineWidth = rect::right(inner) - lineLeft;
|
||||
|
||||
p.setFont(st::normalFont);
|
||||
p.setPen(stm->mediaFg);
|
||||
p.drawTextLeft(nameleft, statustop, paintw, _phone);
|
||||
{
|
||||
p.setPen(cache->icon);
|
||||
p.setTextPalette(context.outbg
|
||||
? stm->semiboldPalette
|
||||
: st->coloredTextPalette(selected, colorIndex));
|
||||
|
||||
const auto endskip = _nameLine.hasSkipBlock()
|
||||
? _parent->skipBlockWidth()
|
||||
: 0;
|
||||
_nameLine.drawLeftElided(
|
||||
p,
|
||||
lineLeft,
|
||||
tshift,
|
||||
lineWidth,
|
||||
width(),
|
||||
1,
|
||||
style::al_left,
|
||||
0,
|
||||
-1,
|
||||
endskip,
|
||||
false,
|
||||
context.selection);
|
||||
tshift += lineHeight;
|
||||
|
||||
p.setTextPalette(stm->textPalette);
|
||||
}
|
||||
p.setPen(stm->historyTextFg);
|
||||
{
|
||||
tshift += st::lineWidth * 3; // Additional skip.
|
||||
const auto endskip = _phoneLine.hasSkipBlock()
|
||||
? _parent->skipBlockWidth()
|
||||
: 0;
|
||||
_phoneLine.drawLeftElided(
|
||||
p,
|
||||
lineLeft,
|
||||
tshift,
|
||||
lineWidth,
|
||||
width(),
|
||||
1,
|
||||
style::al_left,
|
||||
0,
|
||||
-1,
|
||||
endskip,
|
||||
false,
|
||||
toTitleSelection(context.selection));
|
||||
tshift += 1 * lineHeight;
|
||||
}
|
||||
if (!_infoLine.isEmpty()) {
|
||||
tshift += st::lineWidth * 3; // Additional skip.
|
||||
const auto endskip = _infoLine.hasSkipBlock()
|
||||
? _parent->skipBlockWidth()
|
||||
: 0;
|
||||
_parent->prepareCustomEmojiPaint(p, context, _infoLine);
|
||||
_infoLine.draw(p, {
|
||||
.position = { lineLeft, tshift },
|
||||
.outerWidth = width(),
|
||||
.availableWidth = lineWidth,
|
||||
.spoiler = Ui::Text::DefaultSpoilerCache(),
|
||||
.now = context.now,
|
||||
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
|
||||
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
|
||||
.selection = toDescriptionSelection(context.selection),
|
||||
.elisionHeight = (1 * lineHeight),
|
||||
.elisionRemoveFromEnd = endskip,
|
||||
});
|
||||
tshift += (1 * lineHeight);
|
||||
}
|
||||
|
||||
if (!_buttons.empty()) {
|
||||
p.setFont(st::semiboldFont);
|
||||
p.setPen(cache->icon);
|
||||
const auto end = rect::bottom(inner) + _st.padding.bottom();
|
||||
const auto line = st::historyPageButtonLine;
|
||||
auto color = cache->icon;
|
||||
color.setAlphaF(color.alphaF() * 0.3);
|
||||
const auto top = end + st::historyPageButtonPadding.top();
|
||||
const auto buttonWidth = inner.width() / float64(_buttons.size());
|
||||
p.fillRect(inner.x(), end, inner.width(), line, color);
|
||||
for (auto i = 0; i < _buttons.size(); i++) {
|
||||
const auto &button = _buttons[i];
|
||||
const auto left = inner.x() + i * buttonWidth;
|
||||
if (button.ripple) {
|
||||
button.ripple->paint(p, left, end, buttonWidth, &cache->bg);
|
||||
if (button.ripple->empty()) {
|
||||
_buttons[i].ripple = nullptr;
|
||||
}
|
||||
}
|
||||
p.drawText(
|
||||
left + (buttonWidth - button.width) / 2,
|
||||
top + st::semiboldFont->ascent,
|
||||
button.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextState Contact::textState(QPoint point, StateRequest request) const {
|
||||
auto result = TextState(_parent);
|
||||
|
||||
if (_userId) {
|
||||
const auto &st = _userId ? st::msgFileThumbLayout : st::msgFileLayout;
|
||||
const auto topMinus = isBubbleTop() ? 0 : st::msgFileTopMinus;
|
||||
const auto nameleft = st.padding.left() + st.thumbSize + st.thumbSkip;
|
||||
const auto linkshift = st::msgDateFont->height / 2;
|
||||
const auto linktop = st.linkTop - topMinus - linkshift;
|
||||
if (style::rtlrect(nameleft, linktop, _linkw, st::semiboldFont->height, width()).contains(point)) {
|
||||
result.link = _linkl;
|
||||
return result;
|
||||
const auto full = Rect(currentSize());
|
||||
const auto outer = full - inBubblePadding();
|
||||
const auto inner = outer - innerMargin();
|
||||
|
||||
_lastPoint = point;
|
||||
|
||||
if (_buttons.size() > 1) {
|
||||
const auto end = rect::bottom(inner) + _st.padding.bottom();
|
||||
const auto line = st::historyPageButtonLine;
|
||||
const auto bWidth = inner.width() / float64(_buttons.size());
|
||||
const auto bHeight = rect::bottom(outer) - end;
|
||||
for (auto i = 0; i < _buttons.size(); i++) {
|
||||
const auto left = inner.x() + i * bWidth;
|
||||
if (QRectF(left, end, bWidth, bHeight).contains(point)) {
|
||||
result.link = _buttons[i].link;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (QRect(0, 0, width(), height()).contains(point) && _contact) {
|
||||
result.link = _contact->openLink();
|
||||
if (outer.contains(point)) {
|
||||
result.link = _mainButton.link;
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
|
@ -239,4 +432,100 @@ bool Contact::hasHeavyPart() const {
|
|||
return !_userpic.null();
|
||||
}
|
||||
|
||||
void Contact::clickHandlerPressedChanged(
|
||||
const ClickHandlerPtr &p,
|
||||
bool pressed) {
|
||||
const auto full = Rect(currentSize());
|
||||
const auto outer = full - inBubblePadding();
|
||||
const auto inner = outer - innerMargin();
|
||||
const auto end = rect::bottom(inner) + _st.padding.bottom();
|
||||
if ((_lastPoint.y() < end) || (_buttons.size() <= 1)) {
|
||||
if (p != _mainButton.link) {
|
||||
return;
|
||||
}
|
||||
if (pressed) {
|
||||
if (!_mainButton.ripple) {
|
||||
const auto owner = &parent()->history()->owner();
|
||||
_mainButton.ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::defaultRippleAnimation,
|
||||
Ui::RippleAnimation::RoundRectMask(
|
||||
outer.size(),
|
||||
_st.radius),
|
||||
[=] { owner->requestViewRepaint(parent()); });
|
||||
}
|
||||
_mainButton.ripple->add(_lastPoint - outer.topLeft());
|
||||
} else if (_mainButton.ripple) {
|
||||
_mainButton.ripple->lastStop();
|
||||
}
|
||||
return;
|
||||
} else if (_buttons.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto bWidth = inner.width() / float64(_buttons.size());
|
||||
const auto bHeight = rect::bottom(outer) - end;
|
||||
for (auto i = 0; i < _buttons.size(); i++) {
|
||||
const auto &button = _buttons[i];
|
||||
if (p != button.link) {
|
||||
continue;
|
||||
}
|
||||
if (pressed) {
|
||||
if (!button.ripple) {
|
||||
const auto owner = &parent()->history()->owner();
|
||||
|
||||
_buttons[i].ripple = std::make_unique<Ui::RippleAnimation>(
|
||||
st::defaultRippleAnimation,
|
||||
Ui::RippleAnimation::MaskByDrawer(
|
||||
QSize(bWidth, bHeight),
|
||||
false,
|
||||
[=](QPainter &p) {
|
||||
p.drawRect(0, 0, bWidth, bHeight);
|
||||
}),
|
||||
[=] { owner->requestViewRepaint(parent()); });
|
||||
}
|
||||
button.ripple->add(_lastPoint
|
||||
- QPoint(inner.x() + i * bWidth, end));
|
||||
} else if (button.ripple) {
|
||||
button.ripple->lastStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMargins Contact::inBubblePadding() const {
|
||||
return {
|
||||
st::msgPadding.left(),
|
||||
isBubbleTop() ? st::msgPadding.left() : 0,
|
||||
st::msgPadding.right(),
|
||||
isBubbleBottom() ? (st::msgPadding.left() + bottomInfoPadding()) : 0
|
||||
};
|
||||
}
|
||||
|
||||
QMargins Contact::innerMargin() const {
|
||||
const auto button = _buttons.empty() ? 0 : st::historyPageButtonHeight;
|
||||
return _st.padding + QMargins(0, 0, 0, button);
|
||||
}
|
||||
|
||||
int Contact::bottomInfoPadding() const {
|
||||
if (!isBubbleBottom()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto result = st::msgDateFont->height;
|
||||
|
||||
// We use padding greater than st::msgPadding.bottom() in the
|
||||
// bottom of the bubble so that the left line looks pretty.
|
||||
// but if we have bottom skip because of the info display
|
||||
// we don't need that additional padding so we replace it
|
||||
// back with st::msgPadding.bottom() instead of left().
|
||||
result += st::msgPadding.bottom() - st::msgPadding.left();
|
||||
return result;
|
||||
}
|
||||
|
||||
TextSelection Contact::toTitleSelection(TextSelection selection) const {
|
||||
return UnshiftItemSelection(selection, _nameLine);
|
||||
}
|
||||
|
||||
TextSelection Contact::toDescriptionSelection(TextSelection selection) const {
|
||||
return UnshiftItemSelection(toTitleSelection(selection), _phoneLine);
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -12,11 +12,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Ui {
|
||||
class EmptyUserpic;
|
||||
class RippleAnimation;
|
||||
} // namespace Ui
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
class Contact : public Media {
|
||||
class Contact final : public Media {
|
||||
public:
|
||||
Contact(
|
||||
not_null<Element*> parent,
|
||||
|
@ -29,7 +30,8 @@ public:
|
|||
void draw(Painter &p, const PaintContext &context) const override;
|
||||
TextState textState(QPoint point, StateRequest request) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
bool toggleSelectionByHandlerClick(
|
||||
const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
}
|
||||
bool dragItemByHandler(const ClickHandlerPtr &p) const override {
|
||||
|
@ -43,16 +45,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
const QString &fname() const {
|
||||
return _fname;
|
||||
}
|
||||
const QString &lname() const {
|
||||
return _lname;
|
||||
}
|
||||
const QString &phone() const {
|
||||
return _phone;
|
||||
}
|
||||
|
||||
// Should be called only by Data::Session.
|
||||
void updateSharedContactUserId(UserId userId) override;
|
||||
|
||||
|
@ -62,18 +54,40 @@ public:
|
|||
private:
|
||||
QSize countOptimalSize() override;
|
||||
|
||||
void clickHandlerPressedChanged(
|
||||
const ClickHandlerPtr &p, bool pressed) override;
|
||||
|
||||
[[nodiscard]] QMargins inBubblePadding() const;
|
||||
[[nodiscard]] QMargins innerMargin() const;
|
||||
[[nodiscard]] int bottomInfoPadding() const;
|
||||
|
||||
[[nodiscard]] TextSelection toTitleSelection(
|
||||
TextSelection selection) const;
|
||||
[[nodiscard]] TextSelection toDescriptionSelection(
|
||||
TextSelection selection) const;
|
||||
|
||||
const style::QuoteStyle &_st;
|
||||
const int _pixh;
|
||||
|
||||
UserId _userId = 0;
|
||||
UserData *_contact = nullptr;
|
||||
|
||||
int _phonew = 0;
|
||||
QString _fname, _lname, _phone;
|
||||
Ui::Text::String _name;
|
||||
Ui::Text::String _nameLine;
|
||||
Ui::Text::String _phoneLine;
|
||||
Ui::Text::String _infoLine;
|
||||
|
||||
struct Button {
|
||||
QString text;
|
||||
int width = 0;
|
||||
ClickHandlerPtr link;
|
||||
mutable std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
};
|
||||
std::vector<Button> _buttons;
|
||||
Button _mainButton;
|
||||
|
||||
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
|
||||
mutable Ui::PeerUserpicView _userpic;
|
||||
|
||||
ClickHandlerPtr _linkl;
|
||||
int _linkw = 0;
|
||||
QString _link;
|
||||
mutable QPoint _lastPoint;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue