Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
7afb927acf
17 changed files with 101 additions and 113 deletions
|
|
@ -158,8 +158,10 @@ void ActivateClickHandler(
|
|||
not_null<QWidget*> guard,
|
||||
ClickHandlerPtr handler,
|
||||
ClickContext context) {
|
||||
crl::on_main(guard, [=] {
|
||||
handler->onClick(context);
|
||||
crl::on_main(guard, [=, weak = std::weak_ptr<ClickHandler>(handler)] {
|
||||
if (const auto strong = weak.lock()) {
|
||||
strong->onClick(context);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
enum class EntityType;
|
||||
enum class EntityType : uchar;
|
||||
class ClickHandler {
|
||||
public:
|
||||
virtual ~ClickHandler() {
|
||||
|
|
|
|||
|
|
@ -43,14 +43,19 @@ void Integration::startFontsEnd() {
|
|||
}
|
||||
|
||||
std::shared_ptr<ClickHandler> Integration::createLinkHandler(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
const TextParseOptions &options) {
|
||||
switch (type) {
|
||||
const EntityLinkData &data,
|
||||
const std::any &context) {
|
||||
switch (data.type) {
|
||||
case EntityType::CustomUrl:
|
||||
return !data.isEmpty()
|
||||
? std::make_shared<UrlClickHandler>(data, false)
|
||||
return !data.data.isEmpty()
|
||||
? std::make_shared<UrlClickHandler>(data.data, false)
|
||||
: nullptr;
|
||||
case EntityType::Email:
|
||||
case EntityType::Url:
|
||||
return !data.data.isEmpty()
|
||||
? std::make_shared<UrlClickHandler>(
|
||||
data.data,
|
||||
data.shown == EntityLinkShown::Full)
|
||||
: nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "base/basic_types.h"
|
||||
|
||||
#include <any>
|
||||
|
||||
// Methods that must be implemented outside lib_ui.
|
||||
|
||||
class QString;
|
||||
|
|
@ -16,7 +18,7 @@ class QVariant;
|
|||
|
||||
struct TextParseOptions;
|
||||
class ClickHandler;
|
||||
enum class EntityType;
|
||||
struct EntityLinkData;
|
||||
|
||||
namespace Ui {
|
||||
namespace Emoji {
|
||||
|
|
@ -43,10 +45,8 @@ public:
|
|||
virtual void startFontsEnd();
|
||||
|
||||
[[nodiscard]] virtual std::shared_ptr<ClickHandler> createLinkHandler(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
const TextParseOptions &options);
|
||||
const EntityLinkData &data,
|
||||
const std::any &context);
|
||||
[[nodiscard]] virtual bool handleUrlClick(
|
||||
const QString &url,
|
||||
const QVariant &context);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ void BoxContent::onScrollToY(int top, int bottom) {
|
|||
}
|
||||
}
|
||||
|
||||
void BoxContent::onDraggingScrollDelta(int delta) {
|
||||
void BoxContent::scrollByDraggingDelta(int delta) {
|
||||
_draggingScrollDelta = _scroll ? delta : 0;
|
||||
if (_draggingScrollDelta) {
|
||||
if (!_draggingScrollTimer) {
|
||||
|
|
|
|||
|
|
@ -192,11 +192,11 @@ public:
|
|||
getDelegate()->setNoContentMargin(noContentMargin);
|
||||
}
|
||||
|
||||
void scrollByDraggingDelta(int delta);
|
||||
|
||||
public slots:
|
||||
void onScrollToY(int top, int bottom = -1);
|
||||
|
||||
void onDraggingScrollDelta(int delta);
|
||||
|
||||
protected:
|
||||
virtual void prepare() = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ void LayerStackWidget::closeLayer(not_null<LayerWidget*> layer) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (layer == _specialLayer) {
|
||||
if (layer == _specialLayer || layer == _mainMenu) {
|
||||
hideAll(anim::type::normal);
|
||||
} else if (layer == currentLayer()) {
|
||||
if (_layers.size() == 1) {
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.
|
|||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "ui/platform/mac/ui_utility_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "ui/platform/linux/ui_utility_linux.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "ui/platform/win/ui_utility_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ void style_InitFontsResource() {
|
|||
Q_INIT_RESOURCE(win);
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
Q_INIT_RESOURCE(mac);
|
||||
#elif defined Q_OS_LINUX && !defined DESKTOP_APP_USE_PACKAGED // Q_OS_WIN || Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX && !defined DESKTOP_APP_USE_PACKAGED // Q_OS_WIN || Q_OS_MAC
|
||||
Q_INIT_RESOURCE(linux);
|
||||
#endif // Q_OS_WIN || Q_OS_MAC || (Q_OS_LINUX && !DESKTOP_APP_USE_PACKAGED)
|
||||
#endif // Q_OS_WIN || Q_OS_MAC || (Q_OS_UNIX && !DESKTOP_APP_USE_PACKAGED)
|
||||
}
|
||||
|
||||
namespace style {
|
||||
|
|
|
|||
105
ui/text/text.cpp
105
ui/text/text.cpp
|
|
@ -263,33 +263,18 @@ public:
|
|||
Parser(
|
||||
not_null<String*> string,
|
||||
const QString &text,
|
||||
const TextParseOptions &options);
|
||||
const TextParseOptions &options,
|
||||
const std::any &context);
|
||||
Parser(
|
||||
not_null<String*> string,
|
||||
const TextWithEntities &textWithEntities,
|
||||
const TextParseOptions &options);
|
||||
const TextParseOptions &options,
|
||||
const std::any &context);
|
||||
|
||||
private:
|
||||
struct ReadyToken {
|
||||
};
|
||||
|
||||
enum LinkDisplayStatus {
|
||||
LinkDisplayedFull,
|
||||
LinkDisplayedElided,
|
||||
};
|
||||
|
||||
struct TextLinkData {
|
||||
TextLinkData() = default;
|
||||
TextLinkData(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
LinkDisplayStatus displayStatus);
|
||||
EntityType type = EntityType::Invalid;
|
||||
QString text, data;
|
||||
LinkDisplayStatus displayStatus = LinkDisplayedFull;
|
||||
};
|
||||
|
||||
class StartedEntity {
|
||||
public:
|
||||
explicit StartedEntity(TextBlockFlags flags);
|
||||
|
|
@ -307,6 +292,7 @@ private:
|
|||
not_null<String*> string,
|
||||
TextWithEntities &&source,
|
||||
const TextParseOptions &options,
|
||||
const std::any &context,
|
||||
ReadyToken);
|
||||
|
||||
void trimSourceRange();
|
||||
|
|
@ -336,14 +322,11 @@ private:
|
|||
void computeLinkText(
|
||||
const QString &linkData,
|
||||
QString *outLinkText,
|
||||
LinkDisplayStatus *outDisplayStatus);
|
||||
|
||||
static ClickHandlerPtr CreateHandlerForLink(
|
||||
const TextLinkData &link,
|
||||
const TextParseOptions &options);
|
||||
EntityLinkShown *outShown);
|
||||
|
||||
const not_null<String*> _t;
|
||||
const TextWithEntities _source;
|
||||
const std::any &_context;
|
||||
const QChar * const _start = nullptr;
|
||||
const QChar *_end = nullptr; // mutable, because we trim by decrementing.
|
||||
const QChar *_ptr = nullptr;
|
||||
|
|
@ -355,7 +338,7 @@ private:
|
|||
const QFixed _stopAfterWidth; // summary width of all added words
|
||||
const bool _checkTilde = false; // do we need a special text block for tilde symbol
|
||||
|
||||
std::vector<TextLinkData> _links;
|
||||
std::vector<EntityLinkData> _links;
|
||||
base::flat_map<
|
||||
const QChar*,
|
||||
std::vector<StartedEntity>> _startedEntities;
|
||||
|
|
@ -379,17 +362,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
Parser::TextLinkData::TextLinkData(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
LinkDisplayStatus displayStatus)
|
||||
: type(type)
|
||||
, text(text)
|
||||
, data(data)
|
||||
, displayStatus(displayStatus) {
|
||||
}
|
||||
|
||||
Parser::StartedEntity::StartedEntity(TextBlockFlags flags) : _value(flags) {
|
||||
Expects(_value >= 0 && _value < int(kStringLinkIndexShift));
|
||||
}
|
||||
|
|
@ -415,22 +387,26 @@ std::optional<uint16> Parser::StartedEntity::lnkIndex() const {
|
|||
Parser::Parser(
|
||||
not_null<String*> string,
|
||||
const QString &text,
|
||||
const TextParseOptions &options)
|
||||
const TextParseOptions &options,
|
||||
const std::any &context)
|
||||
: Parser(
|
||||
string,
|
||||
PrepareRichFromPlain(text, options),
|
||||
options,
|
||||
context,
|
||||
ReadyToken()) {
|
||||
}
|
||||
|
||||
Parser::Parser(
|
||||
not_null<String*> string,
|
||||
const TextWithEntities &textWithEntities,
|
||||
const TextParseOptions &options)
|
||||
const TextParseOptions &options,
|
||||
const std::any &context)
|
||||
: Parser(
|
||||
string,
|
||||
PrepareRichFromRich(textWithEntities, options),
|
||||
options,
|
||||
context,
|
||||
ReadyToken()) {
|
||||
}
|
||||
|
||||
|
|
@ -438,9 +414,11 @@ Parser::Parser(
|
|||
not_null<String*> string,
|
||||
TextWithEntities &&source,
|
||||
const TextParseOptions &options,
|
||||
const std::any &context,
|
||||
ReadyToken)
|
||||
: _t(string)
|
||||
, _source(std::move(source))
|
||||
, _context(context)
|
||||
, _start(_source.text.constData())
|
||||
, _end(_start + _source.text.size())
|
||||
, _ptr(_start)
|
||||
|
|
@ -552,7 +530,7 @@ bool Parser::checkEntities() {
|
|||
}
|
||||
|
||||
auto flags = TextBlockFlags();
|
||||
auto link = TextLinkData();
|
||||
auto link = EntityLinkData();
|
||||
const auto entityType = _waitingEntity->type();
|
||||
const auto entityLength = _waitingEntity->length();
|
||||
const auto entityBegin = _start + _waitingEntity->offset();
|
||||
|
|
@ -584,7 +562,7 @@ bool Parser::checkEntities() {
|
|||
link.type = entityType;
|
||||
link.data = QString(entityBegin, entityLength);
|
||||
if (link.type == EntityType::Url) {
|
||||
computeLinkText(link.data, &link.text, &link.displayStatus);
|
||||
computeLinkText(link.data, &link.text, &link.shown);
|
||||
} else {
|
||||
link.text = link.data;
|
||||
}
|
||||
|
|
@ -745,7 +723,10 @@ bool Parser::readCommand() {
|
|||
case TextCommandLinkText: {
|
||||
createBlock();
|
||||
int32 len = _ptr->unicode();
|
||||
_links.emplace_back(EntityType::CustomUrl, QString(), QString(++_ptr, len), LinkDisplayedFull);
|
||||
_links.push_back(EntityLinkData{
|
||||
.data = QString(++_ptr, len),
|
||||
.type = EntityType::CustomUrl
|
||||
});
|
||||
_lnkIndex = kStringLinkIndexShift + _links.size();
|
||||
} break;
|
||||
|
||||
|
|
@ -942,9 +923,9 @@ void Parser::finalize(const TextParseOptions &options) {
|
|||
}
|
||||
|
||||
_t->_links.resize(index);
|
||||
const auto handler = CreateHandlerForLink(
|
||||
const auto handler = Integration::Instance().createLinkHandler(
|
||||
_links[realIndex - 1],
|
||||
options);
|
||||
_context);
|
||||
if (handler) {
|
||||
_t->setLink(index, handler);
|
||||
}
|
||||
|
|
@ -954,7 +935,10 @@ void Parser::finalize(const TextParseOptions &options) {
|
|||
_t->_text.squeeze();
|
||||
}
|
||||
|
||||
void Parser::computeLinkText(const QString &linkData, QString *outLinkText, LinkDisplayStatus *outDisplayStatus) {
|
||||
void Parser::computeLinkText(
|
||||
const QString &linkData,
|
||||
QString *outLinkText,
|
||||
EntityLinkShown *outShown) {
|
||||
auto url = QUrl(linkData);
|
||||
auto good = QUrl(url.isValid()
|
||||
? url.toEncoded()
|
||||
|
|
@ -963,28 +947,9 @@ void Parser::computeLinkText(const QString &linkData, QString *outLinkText, Link
|
|||
? good.toDisplayString()
|
||||
: linkData;
|
||||
*outLinkText = _t->_st->font->elided(readable, st::linkCropLimit);
|
||||
*outDisplayStatus = (*outLinkText == readable) ? LinkDisplayedFull : LinkDisplayedElided;
|
||||
}
|
||||
|
||||
ClickHandlerPtr Parser::CreateHandlerForLink(
|
||||
const TextLinkData &link,
|
||||
const TextParseOptions &options) {
|
||||
const auto result = Integration::Instance().createLinkHandler(
|
||||
link.type,
|
||||
link.text,
|
||||
link.data,
|
||||
options);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
switch (link.type) {
|
||||
case EntityType::Email:
|
||||
case EntityType::Url:
|
||||
return std::make_shared<UrlClickHandler>(
|
||||
link.data,
|
||||
link.displayStatus == LinkDisplayedFull);
|
||||
}
|
||||
return nullptr;
|
||||
*outShown = (*outLinkText == readable)
|
||||
? EntityLinkShown::Full
|
||||
: EntityLinkShown::Partial;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
@ -2707,7 +2672,7 @@ void String::setText(const style::TextStyle &st, const QString &text, const Text
|
|||
_st = &st;
|
||||
clear();
|
||||
{
|
||||
Parser parser(this, text, options);
|
||||
Parser parser(this, text, options, {});
|
||||
}
|
||||
recountNaturalSize(true, options.dir);
|
||||
}
|
||||
|
|
@ -2842,7 +2807,7 @@ int String::countMaxMonospaceWidth() const {
|
|||
return result.ceil().toInt();
|
||||
}
|
||||
|
||||
void String::setMarkedText(const style::TextStyle &st, const TextWithEntities &textWithEntities, const TextParseOptions &options) {
|
||||
void String::setMarkedText(const style::TextStyle &st, const TextWithEntities &textWithEntities, const TextParseOptions &options, const std::any &context) {
|
||||
_st = &st;
|
||||
clear();
|
||||
{
|
||||
|
|
@ -2870,9 +2835,9 @@ void String::setMarkedText(const style::TextStyle &st, const TextWithEntities &t
|
|||
// }
|
||||
// }
|
||||
// newText.append("},\n\n").append(text);
|
||||
// Parser parser(this, { newText, EntitiesInText() }, options);
|
||||
// Parser parser(this, { newText, EntitiesInText() }, options, context);
|
||||
|
||||
Parser parser(this, textWithEntities, options);
|
||||
Parser parser(this, textWithEntities, options, context);
|
||||
}
|
||||
recountNaturalSize(true, options.dir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "base/flags.h"
|
||||
|
||||
#include <private/qfixed_p.h>
|
||||
#include <any>
|
||||
|
||||
static const QChar TextCommand(0x0010);
|
||||
enum TextCommands {
|
||||
|
|
@ -126,7 +127,7 @@ public:
|
|||
void countLineWidths(int width, QVector<int> *lineWidths, bool breakEverywhere = false) const;
|
||||
void setText(const style::TextStyle &st, const QString &text, const TextParseOptions &options = _defaultOptions);
|
||||
void setRichText(const style::TextStyle &st, const QString &text, TextParseOptions options = _defaultOptions);
|
||||
void setMarkedText(const style::TextStyle &st, const TextWithEntities &textWithEntities, const TextParseOptions &options = _defaultOptions);
|
||||
void setMarkedText(const style::TextStyle &st, const TextWithEntities &textWithEntities, const TextParseOptions &options = _defaultOptions, const std::any &context = {});
|
||||
|
||||
void setLink(uint16 lnkIndex, const ClickHandlerPtr &lnk);
|
||||
bool hasLinks() const;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include <QtCore/QVector>
|
||||
#include <QtGui/QClipboard>
|
||||
|
||||
enum class EntityType {
|
||||
enum class EntityType : uchar {
|
||||
Invalid = 0,
|
||||
|
||||
Url,
|
||||
|
|
@ -33,6 +33,18 @@ enum class EntityType {
|
|||
Pre, // block
|
||||
};
|
||||
|
||||
enum class EntityLinkShown : uchar {
|
||||
Full,
|
||||
Partial,
|
||||
};
|
||||
|
||||
struct EntityLinkData {
|
||||
QString text;
|
||||
QString data;
|
||||
EntityType type = EntityType::Invalid;
|
||||
EntityLinkShown shown = EntityLinkShown::Full;
|
||||
};
|
||||
|
||||
class EntityInText;
|
||||
using EntitiesInText = QList<EntityInText>;
|
||||
|
||||
|
|
@ -226,11 +238,6 @@ enum {
|
|||
TextParseHashtags = 0x010,
|
||||
TextParseBotCommands = 0x020,
|
||||
TextParseMarkdown = 0x040,
|
||||
|
||||
TextTwitterMentions = 0x100,
|
||||
TextTwitterHashtags = 0x200,
|
||||
TextInstagramMentions = 0x400,
|
||||
TextInstagramHashtags = 0x800,
|
||||
};
|
||||
|
||||
struct TextWithTags {
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ public:
|
|||
|
||||
void clearState() override;
|
||||
|
||||
void paintRipple(QPainter &p, int x, int y, const QColor *colorOverride = nullptr);
|
||||
|
||||
~RippleButton();
|
||||
|
||||
protected:
|
||||
void paintRipple(QPainter &p, int x, int y, const QColor *colorOverride = nullptr);
|
||||
|
||||
void onStateChanged(State was, StateChangeSource source) override;
|
||||
|
||||
virtual QImage prepareRippleMask() const;
|
||||
|
|
|
|||
|
|
@ -247,15 +247,16 @@ void InnerDropdown::hideFinished() {
|
|||
void InnerDropdown::prepareCache() {
|
||||
if (_a_opacity.animating()) return;
|
||||
|
||||
const auto animating = _a_show.animating();
|
||||
auto showAnimation = base::take(_a_show);
|
||||
auto showAnimationData = base::take(_showAnimation);
|
||||
showChildren();
|
||||
_cache = GrabWidget(this);
|
||||
_showAnimation = base::take(showAnimationData);
|
||||
_a_show = base::take(showAnimation);
|
||||
if (_a_show.animating()) {
|
||||
if (animating) {
|
||||
hideChildren();
|
||||
}
|
||||
_showAnimation = base::take(showAnimationData);
|
||||
_a_show = base::take(showAnimation);
|
||||
}
|
||||
|
||||
void InnerDropdown::startOpacityAnimation(bool hiding) {
|
||||
|
|
|
|||
|
|
@ -2930,10 +2930,15 @@ void InputField::inputMethodEventInner(QInputMethodEvent *e) {
|
|||
startPlaceholderAnimation();
|
||||
}
|
||||
_inputMethodCommit = e->commitString();
|
||||
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
_inner->QTextEdit::inputMethodEvent(e);
|
||||
const auto text = *base::take(_inputMethodCommit);
|
||||
if (!processMarkdownReplaces(text)) {
|
||||
processInstantReplaces(text);
|
||||
|
||||
if (weak) {
|
||||
const auto text = *base::take(_inputMethodCommit);
|
||||
if (!processMarkdownReplaces(text)) {
|
||||
processInstantReplaces(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -454,13 +454,13 @@ Text::StateResult FlatLabel::dragActionFinish(const QPoint &p, Qt::MouseButton b
|
|||
}
|
||||
}
|
||||
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
if (!_selection.empty()) {
|
||||
TextUtilities::SetClipboardText(
|
||||
_text.toTextForMimeData(_selection),
|
||||
QClipboard::Selection);
|
||||
}
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ const style::icon &SideBarButton::computeIcon() const {
|
|||
|
||||
void SideBarButton::validateIconCache() {
|
||||
Expects(_st.iconPosition.x() < 0);
|
||||
Expects(_st.iconPosition.y() >= 0);
|
||||
|
||||
if (!(_active ? _iconCacheActive : _iconCache).isNull()) {
|
||||
return;
|
||||
|
|
@ -172,7 +171,10 @@ void SideBarButton::validateIconCache() {
|
|||
- st::defaultScrollArea.width
|
||||
- (width() / 2)
|
||||
+ (icon.width() / 2)));
|
||||
const auto y = _st.badgePosition.y() - _st.iconPosition.y();
|
||||
const auto top = (_st.iconPosition.y() >= 0)
|
||||
? _st.iconPosition.y()
|
||||
: (height() - icon.height()) / 2;
|
||||
const auto y = _st.badgePosition.y() - top;
|
||||
const auto r = _st.badgeHeight / 2.;
|
||||
p.drawRoundedRect(x, y, _iconCacheBadgeWidth, _st.badgeHeight, r, r);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue