diff --git a/fonts/fc-custom.conf b/fonts/fc-custom.conf
deleted file mode 100644
index ab5c183..0000000
--- a/fonts/fc-custom.conf
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
- /usr/share/fonts
- /usr/local/share/fonts
- ~/.fonts
- ~/.local/share/fonts
- /usr/X11R6/lib/X11/fonts
- fonts
-
-
- mono
-
-
- monospace
-
-
-
-
- sans serif
-
-
- sans-serif
-
-
-
-
- sans
-
-
- sans-serif
-
-
- /var/cache/fontconfig_11
- fontconfig_11
- ~/.fontconfig_11
-
-
- true
-
-
- false
-
-
- true
-
-
- hintslight
-
-
- lcddefault
-
-
- rgb
-
-
-
diff --git a/fonts/fonts.qrc b/fonts/fonts.qrc
index 64c7085..22a4a29 100644
--- a/fonts/fonts.qrc
+++ b/fonts/fonts.qrc
@@ -10,7 +10,4 @@
DAVazirMediumAsBold.ttf
DAVazirMedium.ttf
-
- fc-custom.conf
-
diff --git a/ui/basic_click_handlers.cpp b/ui/basic_click_handlers.cpp
index ca59447..c1e9d54 100644
--- a/ui/basic_click_handlers.cpp
+++ b/ui/basic_click_handlers.cpp
@@ -41,13 +41,16 @@ QString UrlClickHandler::copyToClipboardContextItemText() const {
: Ui::Integration::Instance().phraseContextCopyLink();
}
-QString UrlClickHandler::url() const {
- if (isEmail()) {
- return _originalUrl;
+QString UrlClickHandler::EncodeForOpening(const QString &originalUrl) {
+ if (IsEmail(originalUrl)) {
+ return originalUrl;
}
- QUrl u(_originalUrl), good(u.isValid() ? u.toEncoded() : QString());
- QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _originalUrl);
+ const auto u = QUrl(originalUrl);
+ const auto good = QUrl(u.isValid() ? u.toEncoded() : QString());
+ const auto result = good.isValid()
+ ? QString::fromUtf8(good.toEncoded())
+ : originalUrl;
if (!result.isEmpty()
&& !QRegularExpression(
diff --git a/ui/basic_click_handlers.h b/ui/basic_click_handlers.h
index 53969c6..ac8c7e3 100644
--- a/ui/basic_click_handlers.h
+++ b/ui/basic_click_handlers.h
@@ -59,11 +59,17 @@ public:
const auto at = url.indexOf('@'), slash = url.indexOf('/');
return ((at > 0) && (slash < 0 || slash > at));
}
+ [[nodiscard]] static QString EncodeForOpening(const QString &originalUrl);
[[nodiscard]] static bool IsSuspicious(const QString &url);
[[nodiscard]] static QString ShowEncoded(const QString &url);
protected:
- QString url() const override;
+ [[nodiscard]] QString originalUrl() const {
+ return _originalUrl;
+ }
+ QString url() const override {
+ return EncodeForOpening(_originalUrl);
+ }
QString readable() const override {
return _readable;
}
diff --git a/ui/image/image_prepare.cpp b/ui/image/image_prepare.cpp
index d372b22..3e48444 100644
--- a/ui/image/image_prepare.cpp
+++ b/ui/image/image_prepare.cpp
@@ -97,6 +97,20 @@ std::array PrepareCorners(
return result;
}
+std::array CornersMask(int radius) {
+ return PrepareCornersMask(radius);
+}
+
+std::array PrepareCorners(
+ int radius,
+ const style::color &color) {
+ auto result = CornersMask(radius);
+ for (auto &image : result) {
+ style::colorizeImage(image, color->c, &image);
+ }
+ return result;
+}
+
QImage prepareBlur(QImage img) {
if (img.isNull()) {
return img;
diff --git a/ui/image/image_prepare.h b/ui/image/image_prepare.h
index ddfe40a..60261b7 100644
--- a/ui/image/image_prepare.h
+++ b/ui/image/image_prepare.h
@@ -27,12 +27,18 @@ namespace Images {
[[nodiscard]] QPixmap PixmapFast(QImage &&image);
[[nodiscard]] QImage BlurLargeImage(QImage image, int radius);
+
[[nodiscard]] const std::array &CornersMask(
ImageRoundRadius radius);
[[nodiscard]] std::array PrepareCorners(
ImageRoundRadius radius,
const style::color &color);
+[[nodiscard]] std::array CornersMask(int radius);
+[[nodiscard]] std::array PrepareCorners(
+ int radius,
+ const style::color &color);
+
QImage prepareBlur(QImage image);
void prepareRound(
QImage &image,
diff --git a/ui/platform/win/ui_utility_win.cpp b/ui/platform/win/ui_utility_win.cpp
index 392a65d..6af98ea 100644
--- a/ui/platform/win/ui_utility_win.cpp
+++ b/ui/platform/win/ui_utility_win.cpp
@@ -37,7 +37,7 @@ void IgnoreAllActivation(not_null widget) {
ShowWindow(handle, SW_HIDE);
const auto style = GetWindowLongPtr(handle, GWL_EXSTYLE);
- SetWindowLong(
+ SetWindowLongPtr(
handle,
GWL_EXSTYLE,
style | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
diff --git a/ui/platform/win/ui_window_shadow_win.cpp b/ui/platform/win/ui_window_shadow_win.cpp
index 644749b..2463aa9 100644
--- a/ui/platform/win/ui_window_shadow_win.cpp
+++ b/ui/platform/win/ui_window_shadow_win.cpp
@@ -213,7 +213,7 @@ void WindowShadow::init(QColor color) {
return;
}
ShadowByHandle.emplace(_handles[i], this);
- SetWindowLongPtr(_handles[i], GWLP_HWNDPARENT, (LONG)_handle);
+ SetWindowLongPtr(_handles[i], GWLP_HWNDPARENT, (LONG_PTR)_handle);
_contexts[i] = CreateCompatibleDC(_screenContext);
if (!_contexts[i]) {
diff --git a/ui/round_rect.cpp b/ui/round_rect.cpp
index 0af480b..eb42a51 100644
--- a/ui/round_rect.cpp
+++ b/ui/round_rect.cpp
@@ -74,6 +74,17 @@ RoundRect::RoundRect(
}, _lifetime);
}
+RoundRect::RoundRect(
+ int radius,
+ const style::color &color)
+: _color(color)
+, _corners(Images::PrepareCorners(radius, color)) {
+ style::PaletteChanged(
+ ) | rpl::start_with_next([=] {
+ _corners = Images::PrepareCorners(radius, _color);
+ }, _lifetime);
+}
+
const style::color &RoundRect::color() const {
return _color;
}
diff --git a/ui/round_rect.h b/ui/round_rect.h
index 4d65f4a..920c3dd 100644
--- a/ui/round_rect.h
+++ b/ui/round_rect.h
@@ -24,6 +24,7 @@ void DrawRoundedRect(
class RoundRect final {
public:
RoundRect(ImageRoundRadius radius, const style::color &color);
+ RoundRect(int radius, const style::color &color);
[[nodiscard]] const style::color &color() const;
void paint(
diff --git a/ui/text/text.cpp b/ui/text/text.cpp
index 3f224c3..59a1108 100644
--- a/ui/text/text.cpp
+++ b/ui/text/text.cpp
@@ -535,6 +535,20 @@ bool Parser::checkEntities() {
const auto entityLength = _waitingEntity->length();
const auto entityBegin = _start + _waitingEntity->offset();
const auto entityEnd = entityBegin + entityLength;
+ const auto pushSimpleUrl = [&](EntityType type) {
+ link.type = type;
+ link.data = QString(entityBegin, entityLength);
+ if (type == EntityType::Url) {
+ computeLinkText(link.data, &link.text, &link.shown);
+ } else {
+ link.text = link.data;
+ }
+ };
+ const auto pushComplexUrl = [&] {
+ link.type = entityType;
+ link.data = _waitingEntity->data();
+ link.text = QString(entityBegin, entityLength);
+ };
if (entityType == EntityType::Bold) {
flags = TextBlockFBold;
} else if (entityType == EntityType::Semibold) {
@@ -559,18 +573,17 @@ bool Parser::checkEntities() {
|| entityType == EntityType::Hashtag
|| entityType == EntityType::Cashtag
|| entityType == EntityType::BotCommand) {
- link.type = entityType;
- link.data = QString(entityBegin, entityLength);
- if (link.type == EntityType::Url) {
- computeLinkText(link.data, &link.text, &link.shown);
+ pushSimpleUrl(entityType);
+ } else if (entityType == EntityType::CustomUrl) {
+ const auto url = _waitingEntity->data();
+ const auto text = QString(entityBegin, entityLength);
+ if (url == text) {
+ pushSimpleUrl(EntityType::Url);
} else {
- link.text = link.data;
+ pushComplexUrl();
}
- } else if (entityType == EntityType::CustomUrl
- || entityType == EntityType::MentionName) {
- link.type = entityType;
- link.data = _waitingEntity->data();
- link.text = QString(_start + _waitingEntity->offset(), _waitingEntity->length());
+ } else if (entityType == EntityType::MentionName) {
+ pushComplexUrl();
}
if (link.type != EntityType::Invalid) {
@@ -3271,16 +3284,20 @@ TextForMimeData String::toText(
if (!composeExpanded && !composeEntities) {
return;
}
- const auto skipLink = (entity.type == EntityType::CustomUrl)
- && (entity.data.startsWith(qstr("internal:")));
+ const auto customTextLink = (entity.type == EntityType::CustomUrl);
+ const auto internalLink = customTextLink
+ && entity.data.startsWith(qstr("internal:"));
if (composeExpanded) {
result.expanded.append(full);
- if (entity.type == EntityType::CustomUrl && !skipLink) {
+ const auto sameAsTextLink = customTextLink
+ && (entity.data
+ == UrlClickHandler::EncodeForOpening(full.toString()));
+ if (customTextLink && !internalLink && !sameAsTextLink) {
const auto &url = entity.data;
result.expanded.append(qstr(" (")).append(url).append(')');
}
}
- if (composeEntities && !skipLink) {
+ if (composeEntities && !internalLink) {
insertEntity({
entity.type,
linkStart,
diff --git a/ui/text/text_entity.cpp b/ui/text/text_entity.cpp
index 087fa77..4d6de85 100644
--- a/ui/text/text_entity.cpp
+++ b/ui/text/text_entity.cpp
@@ -1587,7 +1587,8 @@ void ParseEntities(TextWithEntities &result, int32 flags, bool rich) {
int32 len = result.text.size(), commandOffset = rich ? 0 : len;
bool inLink = false, commandIsLink = false;
- const QChar *start = result.text.constData(), *end = start + result.text.size();
+ const auto start = result.text.constData();
+ const auto end = start + result.text.size();
for (int32 offset = 0, matchOffset = offset, mentionSkip = 0; offset < len;) {
if (commandOffset <= offset) {
for (commandOffset = offset; commandOffset < len; ++commandOffset) {
@@ -1642,6 +1643,10 @@ void ParseEntities(TextWithEntities &result, int32 flags, bool rich) {
}
if (!(start + mentionStart + 1)->isLetter() || !(start + mentionEnd - 1)->isLetterOrNumber()) {
mentionSkip = mentionEnd;
+ if (mentionSkip < len
+ && (start + mentionSkip)->isLowSurrogate()) {
+ ++mentionSkip;
+ }
mMention = RegExpMention().match(result.text, qMax(mentionSkip, matchOffset));
if (mMention.hasMatch()) {
mentionStart = mMention.capturedStart();
diff --git a/ui/ui_utility.h b/ui/ui_utility.h
index 4a1ce5e..a174909 100644
--- a/ui/ui_utility.h
+++ b/ui/ui_utility.h
@@ -24,23 +24,11 @@ class object_ptr;
namespace Ui {
namespace details {
-struct ForwardTag {
-};
-
-struct InPlaceTag {
-};
-
template
class AttachmentOwner : public QObject {
public:
- template
- AttachmentOwner(QObject *parent, const ForwardTag&, OtherValue &&value)
- : QObject(parent)
- , _value(std::forward(value)) {
- }
-
template
- AttachmentOwner(QObject *parent, const InPlaceTag&, Args &&...args)
+ AttachmentOwner(QObject *parent, Args &&...args)
: QObject(parent)
, _value(std::forward(args)...) {
}
@@ -74,11 +62,19 @@ inline Value *CreateChild(
} else {
return CreateChild>(
parent,
- details::InPlaceTag{},
std::forward(args)...)->value();
}
}
+template
+inline not_null>*> WrapAsQObject(
+ not_null parent,
+ Value &&value) {
+ return CreateChild>>(
+ parent.get(),
+ std::forward(value));
+}
+
inline void DestroyChild(QWidget *child) {
delete child;
}
@@ -92,10 +88,7 @@ template
inline not_null*> AttachAsChild(
not_null parent,
Value &&value) {
- return CreateChild>>(
- parent.get(),
- details::ForwardTag{},
- std::forward(value))->value();
+ return WrapAsQObject(parent, std::forward(value))->value();
}
[[nodiscard]] bool AppInFocus();