Compare commits

..

41 Commits

Author SHA1 Message Date
John Preston
4247fd0c0f Version 4.6.3.
- Optimize chats list initial loading.
- Various crash fixes.
2023-02-16 07:03:13 +04:00
John Preston
50f2e93623 Replace "Your Report Tag" with "Crash ID". 2023-02-15 22:32:11 +04:00
Vitaly Zaitsev
fbfa6966f4 Updated internal submodules. 2023-02-15 21:17:16 +04:00
Vitaly Zaitsev
42eb452de8 Updated GSL submodule to version 4.0.0. 2023-02-15 21:17:16 +04:00
Vitaly Zaitsev
9b3692ca22 Removed deprecated GSL headers usage. 2023-02-15 21:17:16 +04:00
Daniel Novomeský
7463aad755 Upgrade libde265, libheif, libjxl in Windows build 2023-02-15 20:19:13 +04:00
Daniel Novomeský
9cf419999d Update kimageformats submodule
Contains fix in HEIF Qt plug-in
2023-02-15 20:19:13 +04:00
John Preston
7557a20679 Close PiP when a passcode lock is enabled. 2023-02-15 10:47:10 +04:00
John Preston
91e6c42fcf Fix channel creation flow. 2023-02-15 10:14:50 +04:00
John Preston
3573b84e8b Fix drag area in comments appearance. 2023-02-15 10:02:14 +04:00
John Preston
bb900c195c Fix possible crash in top bar back button.
Fixes #25882.
2023-02-15 09:43:42 +04:00
John Preston
e61c058eb5 Fix account activation from main menu. 2023-02-15 08:44:24 +04:00
Vitaly Zaitsev
b48dee0af7 Fixed build with GCC 13.
Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
2023-02-14 21:00:37 +04:00
Ilya Fedin
6b6afd38ac Update submodules 2023-02-14 18:37:01 +04:00
Ilya Fedin
98e8a20f5f Fix missing include in settings_main 2023-02-14 18:37:01 +04:00
Ilya Fedin
aeeb9fe761 Fix macOS GH action 2023-02-14 18:37:01 +04:00
Ilya Fedin
c65b45460b Fix range-v3 deprecation warnings 2023-02-14 18:37:01 +04:00
Ilya Fedin
1940edd6ee Fix deprecated declarations warnings on macOS 2023-02-14 18:37:01 +04:00
Ilya Fedin
96ef82272b Use QT_DEPRECATED_WARNINGS_SINCE 2023-02-14 18:37:01 +04:00
John Preston
29d93d348c Fix possible crash in migration tracking. 2023-02-14 10:00:10 +04:00
Ilya Fedin
879df6e6a3 Present window's devicePixelRatio in the UI
It's a more valid value when Qt's rater downscaling is in effect

Also round it
2023-02-13 11:48:51 +04:00
John Preston
9d3715a36a Fix possible crash in members invite.
In some cases Info::Controller (public Window::SessionNavigation)
can be destroyed without the box being destroyed, for example when
group topics are turned on and off.
2023-02-13 06:09:55 +04:00
John Preston
1cb0d7c2dc Fix crash in emoji panel search mode toggle. 2023-02-12 15:04:57 +04:00
John Preston
1da635a5dd Fix crash in cloud lang manager destructor. 2023-02-12 15:01:50 +04:00
John Preston
d0c2bec925 Fix crash clearing chats list before histories. 2023-02-12 14:39:06 +04:00
Ilya Fedin
13a9920c11 Set QT_DPI_ADJUSTMENT_POLICY for older Qt to the new default value 2023-02-11 15:40:00 +04:00
Ilya Fedin
0b100884fc Round system scale in step of 5 points, just like in settings 2023-02-11 15:40:00 +04:00
Ilya Fedin
6e89d41d58 Use variables from style namespace instead of hardcoded scale limits 2023-02-11 15:40:00 +04:00
John Preston
20f946f657 Add empty emoji search icon. 2023-02-10 20:12:28 +04:00
John Preston
9e49e32702 Fix system buttons padding on Windows. 2023-02-10 20:12:17 +04:00
John Preston
6834cdb969 Check restrictions in attach menu bots. 2023-02-09 13:15:45 +04:00
John Preston
36bf54b0d1 Fix layout in blocked users list. 2023-02-09 13:05:21 +04:00
John Preston
8f908ab9c0 Show empty search results in emoji panel. 2023-02-09 12:55:44 +04:00
John Preston
cbd9dd0c2c Allow either category or set being selected. 2023-02-09 12:17:16 +04:00
Joe Kappus
a8decf154f Fix build with GCC12 2023-02-09 11:18:02 +04:00
John Preston
f2ed77649e Preload complex last message on demand. 2023-02-09 09:56:54 +04:00
John Preston
369862a3a7 Always use 64 bit build of dump_syms. 2023-02-09 09:56:54 +04:00
23rd
e6b24a49f6 Moved sticker randomization to class in menu item of userpic builder. 2023-02-09 08:36:59 +03:00
23rd
08644a9c31 Fixed search categories in list of stickers from userpic emoji builder. 2023-02-09 08:36:59 +03:00
23rd
9090b8ce6b Fixed color buttons in userpic emoji builder with different scales. 2023-02-09 08:36:59 +03:00
John Preston
646bb2ff71 Upload sources-full first in release script. 2023-02-09 08:12:38 +04:00
85 changed files with 623 additions and 304 deletions

View File

@@ -64,7 +64,7 @@ jobs:
- name: First set up.
run: |
sudo chown -R `whoami`:admin /usr/local/share
brew install automake
brew install automake ninja
# Disable spotlight.
sudo mdutil -a -i off
@@ -113,13 +113,14 @@ jobs:
./configure.sh \
-D CMAKE_C_FLAGS="-Werror" \
-D CMAKE_CXX_FLAGS="-Werror" \
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO \
-D TDESKTOP_API_TEST=ON \
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
$DEFINE
cd ../out
xcoderun='xcodebuild build -project Telegram.xcodeproj -scheme Telegram -destination "platform=macOS,arch=x86_64" -configuration Debug CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO'
xcoderun='xcodebuild build -project Telegram.xcodeproj -scheme Telegram -destination "platform=macOS,arch=x86_64" -configuration Debug'
bash -c "$xcoderun" || bash -c "$xcoderun" || bash -c "$xcoderun"
- name: Move artifact.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -1877,6 +1877,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_masks_archive_pack" = "Archive Masks";
"lng_masks_has_been_archived" = "Mask pack has been archived.";
"lng_masks_installed" = "Mask pack has been installed.";
"lng_emoji_nothing_found" = "No emoji found";
"lng_in_dlg_photo" = "Photo";
"lng_in_dlg_album" = "Album";

View File

@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.6.2.0" />
Version="4.6.3.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,6,2,0
PRODUCTVERSION 4,6,2,0
FILEVERSION 4,6,3,0
PRODUCTVERSION 4,6,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "4.6.2.0"
VALUE "FileVersion", "4.6.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.6.2.0"
VALUE "ProductVersion", "4.6.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,6,2,0
PRODUCTVERSION 4,6,2,0
FILEVERSION 4,6,3,0
PRODUCTVERSION 4,6,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "4.6.2.0"
VALUE "FileVersion", "4.6.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.6.2.0"
VALUE "ProductVersion", "4.6.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -26,7 +26,9 @@ void openLog() {
return;
}
NSDateFormatter *fmt = [[NSDateFormatter alloc] initWithDateFormat:@"DebugLogs/%Y%m%d_%H%M%S_upd.txt" allowNaturalLanguage:NO];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
[fmt setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
[fmt setDateFormat:@"'DebugLogs/'yyyyMMdd'_'HHmmss'_update.txt'"];
NSString *logPath = [workDir stringByAppendingString:[fmt stringFromDate:[NSDate date]]];
[[NSFileManager defaultManager] createFileAtPath:logPath contents:nil attributes:nil];
_logFile = [NSFileHandle fileHandleForWritingAtPath:logPath];

View File

@@ -140,6 +140,19 @@ void MustBePublicFailed(
MustBePublicDestroy(channel);
}
[[nodiscard]] Fn<void(not_null<PeerData*>)> WrapPeerDoneFromChannelDone(
Fn<void(not_null<ChannelData*>)> channelDone) {
if (!channelDone) {
return nullptr;
}
return [=](not_null<PeerData*> peer) {
if (const auto channel = peer->asChannel()) {
const auto onstack = channelDone;
onstack(channel);
}
};
}
} // namespace
TextWithEntities PeerFloodErrorText(
@@ -482,13 +495,7 @@ GroupInfoBox::GroupInfoBox(
, _api(&_navigation->session().mtp())
, _type(type)
, _initialTitle(title)
, _done([channelDone = std::move(channelDone)](not_null<PeerData*> peer) {
if (const auto channel = peer->asChannel()) {
if (const auto onstack = channelDone) {
onstack(channel);
}
}
}) {
, _done(WrapPeerDoneFromChannelDone(std::move(channelDone))) {
}
GroupInfoBox::GroupInfoBox(

View File

@@ -572,9 +572,6 @@ changePhoneError: FlatLabel(changePhoneLabel) {
textFg: boxTextFgError;
}
blockedUsersListSubtitleAddPadding: margins(0px, 1px, 0px, -14px);
blockedUsersListIconPadding: margins(0px, 34px, 0px, 5px);
adminLogFilterUserpicLeft: 15px;
adminLogFilterLittleSkip: 16px;
adminLogFilterCheckbox: Checkbox(defaultBoxCheckbox) {

View File

@@ -295,10 +295,11 @@ void AddParticipantsBoxController::Start(
not_null<ChatData*> chat) {
auto controller = std::make_unique<AddParticipantsBoxController>(chat);
const auto weak = controller.get();
const auto parent = navigation->parentController();
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_participant_invite(), [=] {
weak->inviteSelectedUsers(box, [=] {
navigation->parentController()->showPeerHistory(
parent->showPeerHistory(
chat,
Window::SectionShow::Way::ClearStack,
ShowAtTheEndMsgId);
@@ -320,11 +321,12 @@ void AddParticipantsBoxController::Start(
channel,
std::move(alreadyIn));
const auto weak = controller.get();
const auto parent = navigation->parentController();
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(tr::lng_participant_invite(), [=] {
weak->inviteSelectedUsers(box, [=] {
if (channel->isMegagroup()) {
navigation->parentController()->showPeerHistory(
parent->showPeerHistory(
channel,
Window::SectionShow::Way::ClearStack,
ShowAtTheEndMsgId);
@@ -337,13 +339,16 @@ void AddParticipantsBoxController::Start(
justCreated ? tr::lng_create_group_skip() : tr::lng_cancel(),
[=] { box->closeBox(); });
if (justCreated) {
const auto weak = base::make_weak(parent);
box->boxClosing() | rpl::start_with_next([=] {
auto params = Window::SectionShow();
params.activation = anim::activation::background;
navigation->parentController()->showPeerHistory(
channel,
params,
ShowAtTheEndMsgId);
if (const auto strong = weak.get()) {
strong->showPeerHistory(
channel,
params,
ShowAtTheEndMsgId);
}
}, box->lifetime());
}
};

View File

@@ -79,7 +79,7 @@ struct NestedRestrictionLabels {
second.erase(
ranges::remove(
second,
Flag::CreateTopics,
Flag::CreateTopics | Flag(),
&RestrictionLabel::flags),
end(second));
}
@@ -1002,7 +1002,7 @@ std::vector<AdminRightLabel> AdminRightLabels(
result.erase(
ranges::remove(
result,
Flag::ManageTopics,
Flag::ManageTopics | Flag(),
&AdminRightLabel::flags),
end(result));
}

View File

@@ -854,7 +854,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
if (((*i)->index() * _rowHeight) >= yTo) {
break;
}
(*i)->entry()->loadUserpic();
(*i)->entry()->chatListPreloadData();
}
}
} else if (!_filtered.empty()) {
@@ -865,7 +865,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
if (to > _filtered.size()) to = _filtered.size();
for (; from < to; ++from) {
_filtered[from]->entry()->loadUserpic();
_filtered[from]->entry()->chatListPreloadData();
}
}
}

View File

@@ -335,6 +335,7 @@ stickersToast: Toast(defaultToast) {
}
stickersEmpty: icon {{ "stickers_empty", windowSubTextFg }};
emojiEmpty: icon {{ "emoji_empty", windowSubTextFg }};
inlineBotsScroll: ScrollArea(defaultSolidScroll) {
deltat: stickerPanPadding;
@@ -396,7 +397,7 @@ reactStripBubble: icon{
{ "chat/reactions_bubble", windowBg },
};
reactStripBubbleRight: 20px;
reactPanelEmojiPan: EmojiPan(statusEmojiPan) {
userpicBuilderEmojiPan: EmojiPan(statusEmojiPan) {
margin: margins(reactStripSkip, 0px, reactStripSkip, 0px);
padding: margins(reactStripSkip, 0px, reactStripSkip, reactStripSkip);
desiredSize: reactStripSize;
@@ -405,6 +406,8 @@ reactPanelEmojiPan: EmojiPan(statusEmojiPan) {
search: TabbedSearch(defaultTabbedSearch) {
defaultFieldWidth: 88px;
}
}
reactPanelEmojiPan: EmojiPan(userpicBuilderEmojiPan) {
searchMargin: margins(1px, 10px, 2px, 6px);
}
emojiScroll: ScrollArea(defaultSolidScroll) {

View File

@@ -485,14 +485,21 @@ void EmojiListWidget::applyNextSearchQuery() {
if (!_searchMode && !searching) {
return;
}
_searchMode = searching;
const auto modeChanged = (_searchMode != searching);
clearSelection();
if (modeChanged) {
_searchMode = searching;
}
if (!searching) {
_searchResults.clear();
_searchCustomIds.clear();
}
clearSelection();
resizeToWidth(width());
update();
if (modeChanged) {
visibleTopBottomUpdated(getVisibleTop(), getVisibleBottom());
}
updateSelected();
};
if (_searchQuery.empty()) {
finish(false);
@@ -615,7 +622,7 @@ void EmojiListWidget::prepareExpanding() {
}
void EmojiListWidget::paintExpanding(
QPainter &p,
Painter &p,
QRect clip,
int finalBottom,
float64 progress,
@@ -968,7 +975,7 @@ base::unique_qptr<Ui::PopupMenu> EmojiListWidget::fillContextMenu(
}
void EmojiListWidget::paintEvent(QPaintEvent *e) {
auto p = QPainter(this);
auto p = Painter(this);
const auto clip = e ? e->rect() : rect();
@@ -1012,7 +1019,7 @@ void EmojiListWidget::validateEmojiPaintContext(
}
void EmojiListWidget::paint(
QPainter &p,
Painter &p,
ExpandingContext context,
QRect clip) {
validateEmojiPaintContext(context);
@@ -1036,6 +1043,9 @@ void EmojiListWidget::paint(
auto selectedButton = std::get_if<OverButton>(!v::is_null(_pressed)
? &_pressed
: &_selected);
if (_searchResults.empty() && _searchMode) {
paintEmptySearchResults(p);
}
enumerateSections([&](const SectionInfo &info) {
if (clip.top() >= info.rowsBottom) {
return true;
@@ -2001,6 +2011,13 @@ int EmojiListWidget::paintButtonGetWidth(
return emojiRight() - rect.x();
}
void EmojiListWidget::paintEmptySearchResults(Painter &p) {
Inner::paintEmptySearchResults(
p,
st::emojiEmpty,
tr::lng_emoji_nothing_found(tr::now));
}
bool EmojiListWidget::eventHook(QEvent *e) {
if (e->type() == QEvent::ParentChange) {
if (_picker->parentWidget() != parentWidget()) {
@@ -2190,10 +2207,13 @@ void EmojiListWidget::showSet(uint64 setId) {
}
uint64 EmojiListWidget::sectionSetId(int section) const {
Expects(section < _staticCount
Expects(_searchMode
|| section < _staticCount
|| (section - _staticCount) < _custom.size());
return (section < _staticCount)
return _searchMode
? SearchEmojiSectionSetId()
: (section < _staticCount)
? EmojiSectionSetId(static_cast<Section>(section))
: _custom[section - _staticCount].id;
}

View File

@@ -125,7 +125,7 @@ public:
void prepareExpanding();
void paintExpanding(
QPainter &p,
Painter &p,
QRect clip,
int finalBottom,
float64 progress,
@@ -271,7 +271,7 @@ private:
Api::SendOptions options = Api::SendOptions());
void selectEmoji(EmojiChosen data);
void selectCustom(FileChosen data);
void paint(QPainter &p, ExpandingContext context, QRect clip);
void paint(Painter &p, ExpandingContext context, QRect clip);
void drawCollapsedBadge(QPainter &p, QPoint position, int count);
void drawRecent(
QPainter &p,
@@ -313,6 +313,7 @@ private:
const SectionInfo &info,
bool selected,
QRect clip) const;
void paintEmptySearchResults(Painter &p);
void displaySet(uint64 setId);
void removeSet(uint64 setId);

View File

@@ -161,6 +161,7 @@ object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
.st = &st(),
});
_footer = result;
_chosenSetId = Data::Stickers::RecentSetId;
GifSectionsValue(
&session()
@@ -171,6 +172,9 @@ object_ptr<TabbedSelector::InnerFooter> GifsListWidget::createFooter() {
_footer->setChosen(
) | rpl::start_with_next([=](uint64 setId) {
if (_search) {
_search->cancel();
}
_chosenSetId = setId;
refreshIcons();
const auto i = ranges::find(_sections, setId, [](GifSection value) {
@@ -791,13 +795,16 @@ bool GifsListWidget::refreshInlineRows(int32 *added) {
void GifsListWidget::setupSearch() {
const auto session = &_controller->session();
_search = MakeSearch(this, st(), [=](std::vector<QString> &&query) {
_chosenSetId = Data::Stickers::RecentSetId;
refreshIcons();
searchForGifs(ranges::accumulate(query, QString(), [](
const auto accumulated = ranges::accumulate(query, QString(), [](
QString a,
QString b) {
return a.isEmpty() ? b : (a + ' ' + b);
}));
});
_chosenSetId = accumulated.isEmpty()
? Data::Stickers::RecentSetId
: SearchEmojiSectionSetId();
refreshIcons();
searchForGifs(accumulated);
}, session);
}

View File

@@ -417,6 +417,16 @@ void StickersListFooter::enumerateSubicons(
}
auto StickersListFooter::iconInfo(int index) const -> IconInfo {
if (index < 0) {
const auto iconsX = int(base::SafeRound(_iconState.x.current()));
return {
.index = -1,
.left = -_singleWidth - _iconsLeft,
.adjustedLeft = -_singleWidth - _iconsLeft - iconsX,
.width = _singleWidth,
.visible = false,
};
}
auto result = IconInfo();
enumerateIcons([&](const IconInfo &info) {
if (info.index == index) {
@@ -473,7 +483,8 @@ void StickersListFooter::validateSelectedIcon(
&& setId == Data::Stickers::RecentSetId)) {
newSelected = i;
break;
} else if (_icons[i].setId == Data::Stickers::FavedSetId) {
} else if (_icons[i].setId == Data::Stickers::FavedSetId
&& setId != SearchEmojiSectionSetId()) {
favedIconIndex = i;
} else if (isEmojiSection && _icons[i].setId == allEmojiSetId) {
newSelected = i;
@@ -483,7 +494,9 @@ void StickersListFooter::validateSelectedIcon(
setSelectedIcon(
(newSelected >= 0
? newSelected
: (favedIconIndex >= 0) ? favedIconIndex : 0),
: (favedIconIndex >= 0)
? favedIconIndex
: -1),
animations);
setSelectedSubicon(
(newSubSelected >= 0 ? newSubSelected : 0),
@@ -522,6 +535,9 @@ void StickersListFooter::setSelectedIcon(
if (_iconState.selected == newSelected) {
return;
}
if ((_iconState.selected < 0) != (newSelected < 0)) {
animations = ValidateIconAnimations::None;
}
_iconState.selected = newSelected;
updateEmojiSectionWidth();
const auto info = iconInfo(_iconState.selected);
@@ -1113,7 +1129,7 @@ void StickersListFooter::refreshIconsGeometry(
(st().footer - st().iconArea) / 2);
refreshScrollableDimensions();
refreshSubiconsGeometry();
_iconState.selected = _subiconState.selected = -1;
_iconState.selected = _subiconState.selected = -2;
validateSelectedIcon(activeSetId, animations);
update();
}

View File

@@ -165,17 +165,18 @@ StickersListWidget::StickersListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level,
bool masks)
Mode mode)
: Inner(
parent,
st::defaultEmojiPan,
&controller->session(),
Window::PausedIn(controller, level))
, _mode(mode)
, _controller(controller)
, _api(&session().mtp())
, _localSetsManager(std::make_unique<LocalStickersManager>(&session()))
, _section(Section::Stickers)
, _isMasks(masks)
, _isMasks(mode == Mode::Masks)
, _updateItemsTimer([=] { updateItems(); })
, _updateSetsTimer([=] { updateSets(); })
, _trendingAddBgOver(
@@ -1079,20 +1080,10 @@ void StickersListWidget::pauseInvisibleLottieIn(const SectionInfo &info) {
}
void StickersListWidget::paintEmptySearchResults(Painter &p) {
const auto iconLeft = (width() - st::stickersEmpty.width()) / 2;
const auto iconTop = (height() / 3) - (st::stickersEmpty.height() / 2);
st::stickersEmpty.paint(p, iconLeft, iconTop, width());
const auto text = tr::lng_stickers_nothing_found(tr::now);
const auto textWidth = st::normalFont->width(text);
p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);
p.drawTextLeft(
(width() - textWidth) / 2,
iconTop + st::stickersEmpty.height() - st::normalFont->height,
width(),
text,
textWidth);
Inner::paintEmptySearchResults(
p,
st::stickersEmpty,
tr::lng_stickers_nothing_found(tr::now));
}
int StickersListWidget::megagroupSetInfoLeft() const {
@@ -2462,7 +2453,18 @@ auto StickersListWidget::getLottieRenderer()
}
void StickersListWidget::showStickerSet(uint64 setId) {
if (_showingSetById) {
return;
}
_showingSetById = true;
const auto guard = gsl::finally([&] { _showingSetById = false; });
clearSelection();
if (_search
&& (!_searchQuery.isEmpty() || !_searchNextQuery.isEmpty())) {
_search->cancel();
cancelSetsSearch();
}
if (setId == Data::Stickers::FeaturedSetId) {
if (_section != Section::Featured) {
@@ -2565,7 +2567,7 @@ void StickersListWidget::setupSearch() {
return a.isEmpty() ? b : (a + ' ' + b);
});
searchForSets(std::move(text), SearchEmoji(query, set));
}, session);
}, session, false, (_mode == Mode::UserpicBuilder));
}
void StickersListWidget::displaySet(uint64 setId) {

View File

@@ -59,13 +59,21 @@ enum class ValidateIconAnimations;
class StickersListFooter;
class LocalStickersManager;
enum class StickersListMode {
Full,
Masks,
UserpicBuilder,
};
class StickersListWidget final : public TabbedSelector::Inner {
public:
using Mode = StickersListMode;
StickersListWidget(
QWidget *parent,
not_null<Window::SessionController*> controller,
Window::GifPauseReason level,
bool masks = false);
Mode mode = Mode::Full);
rpl::producer<FileChosen> chosen() const;
rpl::producer<> scrollUpdated() const;
@@ -331,6 +339,8 @@ private:
int index,
not_null<DocumentData*> document);
const Mode _mode;
not_null<Window::SessionController*> _controller;
std::unique_ptr<Ui::TabbedSearch> _search;
MTP::Sender _api;
@@ -345,6 +355,7 @@ private:
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
bool _showingSetById = false;
crl::time _lastScrolledAt = 0;
crl::time _lastFullUpdatedAt = 0;

View File

@@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/box_content.h"
#include "ui/image/image_prepare.h"
#include "ui/cached_round_corners.h"
#include "ui/painter.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
@@ -500,7 +501,7 @@ TabbedSelector::Tab TabbedSelector::createTab(SelectorTab type, int index) {
this,
_controller,
_level,
true);
StickersListWidget::Mode::Masks);
}
Unexpected("Type in TabbedSelector::createTab.");
};
@@ -1283,6 +1284,30 @@ void TabbedSelector::Inner::checkHideWithBox(QPointer<Ui::BoxContent> box) {
});
}
void TabbedSelector::Inner::paintEmptySearchResults(
Painter &p,
const style::icon &icon,
const QString &text) const {
const auto iconLeft = (width() - icon.width()) / 2;
const auto iconTop = std::max(
(height() / 3) - (icon.height() / 2),
st::normalFont->height);
icon.paint(p, iconLeft, iconTop, width());
const auto textWidth = st::normalFont->width(text);
const auto textTop = std::min(
iconTop + icon.height() - st::normalFont->height,
height() - 2 * st::normalFont->height);
p.setFont(st::normalFont);
p.setPen(st::windowSubTextFg);
p.drawTextLeft(
(width() - textWidth) / 2,
textTop,
width(),
text,
textWidth);
}
void TabbedSelector::Inner::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {

View File

@@ -376,6 +376,11 @@ protected:
void checkHideWithBox(QPointer<Ui::BoxContent> box);
void paintEmptySearchResults(
Painter &p,
const style::icon &icon,
const QString &text) const;
private:
const style::EmojiPan &_st;
const not_null<Main::Session*> _session;

View File

@@ -1118,10 +1118,11 @@ void Application::updateWindowTitles() {
}
void Application::lockByPasscode() {
_passcodeLock = true;
enumerateWindows([&](not_null<Window::Controller*> w) {
_passcodeLock = true;
w->setupPasscodeLock();
});
hideMediaView();
}
void Application::maybeLockByPasscode() {

View File

@@ -426,7 +426,7 @@ LastCrashedWindow::LastCrashedWindow(
}
_pleaseSendReport.setText(u"Please send us a crash report."_q);
_yourReportName.setText(u"Your Report Tag: %1\nYour User Tag: %2"_q.arg(QString(_minidumpName).replace(".dmp", "")).arg(launcher->installationTag(), 0, 16));
_yourReportName.setText(u"Crash ID: %1"_q.arg(QString(_minidumpName).replace(".dmp", "")));
_yourReportName.setCursor(style::cur_text);
_yourReportName.setTextInteractionFlags(Qt::TextSelectableByMouse);

View File

@@ -190,9 +190,6 @@ void WriteReportInfo(int signum, const char *name) {
} else {
dump() << "Caught signal " << signum << " in thread " << uint64(thread) << "\n";
}
dump() << "\nBacktrace omitted.\n";
dump() << "\n";
}
const int HandledSignals[] = {

View File

@@ -320,7 +320,14 @@ void Launcher::init() {
}
void Launcher::initHighDpi() {
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
qputenv("QT_DPI_ADJUSTMENT_POLICY", "AdjustDpi");
#endif // Qt < 6.2.0
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
#endif // Qt < 6.0.0
if (OptionFractionalScalingEnabled.value()) {
QApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);

View File

@@ -239,17 +239,17 @@ void Sandbox::setupScreenScale() {
const auto basePair = screen->handle()->logicalBaseDpi();
const auto base = (basePair.first + basePair.second) * 0.5;
const auto screenScaleExact = dpi / base;
const auto screenScale = int(base::SafeRound(screenScaleExact * 4)) * 25;
const auto screenScale = int(base::SafeRound(screenScaleExact * 20)) * 5;
LOG(("Primary screen DPI: %1, Base: %2.").arg(dpi).arg(base));
LOG(("Computed screen scale: %1").arg(screenScale));
if (Platform::IsMac()) {
// 110% for Retina screens by default.
cSetScreenScale((useRatio == 2) ? 110 : 100);
cSetScreenScale((useRatio == 2) ? 110 : style::kScaleDefault);
} else {
const auto clamped = std::clamp(
screenScale * useRatio,
50 * useRatio,
300);
style::kScaleMin * useRatio,
style::kScaleMax);
cSetScreenScale(int(base::SafeRound(clamped * 1. / useRatio)));
}
LOG(("DevicePixelRatio: %1").arg(useRatio));

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 4006002;
constexpr auto AppVersionStr = "4.6.2";
constexpr auto AppVersion = 4006003;
constexpr auto AppVersionStr = "4.6.3";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -148,18 +148,19 @@ auto ProcessAlternativeName(Info &&info) {
Manager::Manager(not_null<Main::Domain*> domain)
: _path(cWorkingDir() + "tdata/countries") {
read();
const auto mtpLifetime = _lifetime.make_state<rpl::lifetime>();
domain->activeValue(
) | rpl::map([=](Main::Account *account) {
if (!account) {
_api.reset();
}
return account
? account->mtpMainSessionValue()
: rpl::never<not_null<MTP::Instance*>>();
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
_api.emplace(instance);
request();
) | rpl::filter([=](Main::Account *account) {
return (account != nullptr);
}) | rpl::start_with_next_done([=](Main::Account *account) {
*mtpLifetime = account->mtpMainSessionValue(
) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
_api.emplace(instance);
request();
});
}, [=] {
_api.reset();
}, _lifetime);
}

View File

@@ -172,7 +172,7 @@ void EmojiStatuses::requestProfilePhotoGroups() {
const auto &data = group.data();
auto emoticons = ranges::views::all(
data.vemoticons().v
) | ranges::view::transform([](const MTPstring &emoticon) {
) | ranges::views::transform([](const MTPstring &emoticon) {
return qs(emoticon);
}) | ranges::to_vector;
result.push_back({

View File

@@ -211,7 +211,7 @@ not_null<Dialogs::MainList*> Folder::chatsList() {
return &_chatsList;
}
void Folder::loadUserpic() {
void Folder::chatListPreloadData() {
}
void Folder::paintUserpic(

View File

@@ -54,7 +54,7 @@ public:
const base::flat_set<QString> &chatListNameWords() const override;
const base::flat_set<QChar> &chatListFirstLetters() const override;
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,

View File

@@ -471,17 +471,7 @@ void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
const auto itemId = FullMsgId(channel()->id, topMessageId);
if (const auto item = owner().message(itemId)) {
setLastServerMessage(item);
// If we set a single album part, request the full album.
if (item->groupId() != MessageGroupId()) {
if (owner().groups().isGroupOfOne(item)
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()
&& _requestedGroups.emplace(item->fullId()).second) {
owner().histories().requestGroupAround(item);
}
}
resolveChatListMessageGroup();
} else {
setLastServerMessage(nullptr);
}
@@ -490,6 +480,23 @@ void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
}
}
void ForumTopic::resolveChatListMessageGroup() {
if (!(_flags & Flag::ResolveChatListMessage)) {
return;
}
// If we set a single album part, request the full album.
const auto item = _lastServerMessage.value_or(nullptr);
if (item && item->groupId() != MessageGroupId()) {
if (owner().groups().isGroupOfOne(item)
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()
&& _requestedGroups.emplace(item->fullId()).second) {
owner().histories().requestGroupAround(item);
}
}
}
void ForumTopic::growLastKnownServerMessageId(MsgId id) {
_lastKnownServerMessageId = std::max(_lastKnownServerMessageId, id);
}
@@ -548,10 +555,11 @@ void ForumTopic::setChatListMessage(HistoryItem *item) {
_forum->listMessageChanged(was, item);
}
void ForumTopic::loadUserpic() {
void ForumTopic::chatListPreloadData() {
if (_icon) {
[[maybe_unused]] const auto preload = _icon->ready();
}
allowChatListMessageResolve();
}
void ForumTopic::paintUserpic(
@@ -840,6 +848,14 @@ Dialogs::UnreadState ForumTopic::unreadStateFor(
return result;
}
void ForumTopic::allowChatListMessageResolve() {
if (_flags & Flag::ResolveChatListMessage) {
return;
}
_flags |= Flag::ResolveChatListMessage;
resolveChatListMessageGroup();
}
HistoryItem *ForumTopic::chatListMessage() const {
return _lastMessage.value_or(nullptr);
}

View File

@@ -146,7 +146,7 @@ public:
return _notify;
}
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,
@@ -169,6 +169,7 @@ private:
HasPinnedMessages = (1 << 3),
GeneralIconActive = (1 << 4),
GeneralIconSelected = (1 << 5),
ResolveChatListMessage = (1 << 6),
};
friend inline constexpr bool is_flag_type(Flag) { return true; }
using Flags = base::flags<Flag>;
@@ -183,6 +184,8 @@ private:
void setLastMessage(HistoryItem *item);
void setLastServerMessage(HistoryItem *item);
void setChatListMessage(HistoryItem *item);
void allowChatListMessageResolve();
void resolveChatListMessageGroup();
int chatListNameVersion() const override;

View File

@@ -381,6 +381,9 @@ void Session::clear() {
cSetRecentInlineBots(RecentInlineBots());
cSetRecentStickers(RecentStickerPack());
HistoryView::Element::ClearGlobal();
_contactsNoChatsList.clear();
_contactsList.clear();
_chatsList.clear();
_histories->clearAll();
_webpages.clear();
_locations.clear();

View File

@@ -230,7 +230,7 @@ public:
return nullptr;
}
virtual void loadUserpic() = 0;
virtual void chatListPreloadData() = 0;
virtual void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,

View File

@@ -205,6 +205,7 @@ void IndexedList::remove(Key key, Row *replacedBy) {
}
void IndexedList::clear() {
_list.clear();
_index.clear();
}

View File

@@ -2506,7 +2506,7 @@ void InnerWidget::visibleTopBottomUpdated(
int visibleBottom) {
_visibleTop = visibleTop;
_visibleBottom = visibleBottom;
loadPeerPhotos();
preloadRowsData();
const auto loadTill = _visibleTop
+ PreloadHeightsCount * (_visibleBottom - _visibleTop);
if (_state == WidgetState::Filtered && loadTill >= peerSearchOffset()) {
@@ -2726,7 +2726,7 @@ void InnerWidget::refresh(bool toTop) {
if (toTop) {
stopReorderPinned();
_mustScrollTo.fire({ 0, 0 });
loadPeerPhotos();
preloadRowsData();
}
_controller->setDialogsListDisplayForced(
_searchInChat || !_filter.isEmpty());
@@ -3115,8 +3115,10 @@ void InnerWidget::scrollToDefaultSelected() {
}
}
void InnerWidget::loadPeerPhotos() {
if (!parentWidget()) return;
void InnerWidget::preloadRowsData() {
if (!parentWidget()) {
return;
}
auto yFrom = _visibleTop;
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
@@ -3129,7 +3131,7 @@ void InnerWidget::loadPeerPhotos() {
if (((*i)->index() * _st->height) >= yTo) {
break;
}
(*i)->entry()->loadUserpic();
(*i)->entry()->chatListPreloadData();
}
yFrom = 0;
} else {
@@ -3144,7 +3146,7 @@ void InnerWidget::loadPeerPhotos() {
if (to > _filterResults.size()) to = _filterResults.size();
for (; from < to; ++from) {
_filterResults[from].key().entry()->loadUserpic();
_filterResults[from].key().entry()->chatListPreloadData();
}
}

View File

@@ -243,7 +243,7 @@ private:
Qt::KeyboardModifiers modifiers);
void clearIrrelevantState();
void selectByMouse(QPoint globalPosition);
void loadPeerPhotos();
void preloadRowsData();
void scrollToItem(int top, int height);
void scrollToDefaultSelected();
void setCollapsedPressed(int pressed);

View File

@@ -23,6 +23,10 @@ public:
List &operator=(List &&other) = default;
~List() = default;
void clear() {
_rows.clear();
_rowByKey.clear();
}
[[nodiscard]] int size() const {
return _rows.size();
}

View File

@@ -81,6 +81,7 @@ void MainList::clear() {
recomputeFullListSize();
});
const auto notifier = unreadStateChangeNotifier(true);
_pinned.clear();
_all.clear();
_unreadState = UnreadState();
_cloudUnreadState = UnreadState();

View File

@@ -743,6 +743,7 @@ void RowPainter::Paint(
const auto thread = row->thread();
const auto peer = history ? history->peer.get() : nullptr;
const auto badgesState = entry->chatListBadgesState();
entry->chatListPreloadData(); // Allow chat list message resolve.
const auto item = entry->chatListMessage();
const auto cloudDraft = [&]() -> const Data::Draft*{
if (!thread) {

View File

@@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <gsl/gsl_util>
#include <gsl/util>
namespace Export {
namespace Output {

View File

@@ -607,16 +607,6 @@ not_null<HistoryItem*> History::addNewItem(
} else {
addNewToBack(item, unread);
checkForLoadedAtTop(item);
if (!unread) {
// When we add just one last item, like we do while loading dialogs,
// we want to remove a single added grouped media, otherwise it will
// jump once we open the message history (first we show only that
// media, then we load the rest of the group and show the group).
//
// That way when we open the message history we show nothing until a
// whole history part is loaded, it certainly will contain the group.
removeOrphanMediaGroupPart();
}
}
return item;
}
@@ -2241,6 +2231,44 @@ Dialogs::UnreadState History::computeUnreadState() const {
return result;
}
void History::allowChatListMessageResolve() {
if (_flags & Flag::ResolveChatListMessage) {
return;
}
_flags |= Flag::ResolveChatListMessage;
if (!chatListMessageKnown()) {
requestChatListMessage();
} else {
resolveChatListMessageGroup();
}
}
void History::resolveChatListMessageGroup() {
const auto item = _chatListMessage.value_or(nullptr);
if (!(_flags & Flag::ResolveChatListMessage)
|| !item
|| !hasOrphanMediaGroupPart()) {
return;
}
// If we set a single album part, request the full album.
const auto withImages = !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty();
if (withImages) {
owner().histories().requestGroupAround(item);
}
if (unreadCountKnown() && !unreadCount()) {
// When we add just one last item, like we do while loading dialogs,
// we want to remove a single added grouped media, otherwise it will
// jump once we open the message history (first we show only that
// media, then we load the rest of the group and show the group).
//
// That way when we open the message history we show nothing until a
// whole history part is loaded, it certainly will contain the group.
clear(ClearType::Unload);
}
}
HistoryItem *History::chatListMessage() const {
return _chatListMessage.value_or(nullptr);
}
@@ -2269,8 +2297,9 @@ const base::flat_set<QChar> &History::chatListFirstLetters() const {
return peer->nameFirstLetters();
}
void History::loadUserpic() {
void History::chatListPreloadData() {
peer->loadUserpic();
allowChatListMessageResolve();
}
void History::paintUserpic(
@@ -2452,14 +2481,7 @@ void History::setChatListMessage(HistoryItem *item) {
}
_chatListMessage = item;
setChatListTimeId(item->date());
// If we have a single message from a group, request the full album.
if (hasOrphanMediaGroupPart()
&& !item->toPreview({
.hideSender = true,
.hideCaption = true }).images.empty()) {
owner().histories().requestGroupAround(item);
}
resolveChatListMessageGroup();
} else if (!_chatListMessage || *_chatListMessage) {
_chatListMessage = nullptr;
updateChatListEntry();
@@ -2560,13 +2582,21 @@ void History::requestChatListMessage() {
}
void History::setFakeChatListMessage() {
if (const auto chat = peer->asChat()) {
if (!(_flags & Flag::ResolveChatListMessage)) {
if (!chatListTimeId()) {
if (const auto last = lastMessage()) {
setChatListTimeId(last->date());
}
}
return;
} else if (const auto chat = peer->asChat()) {
// In chats we try to take the item before the 'last', which
// is the empty-displayed migration message.
owner().histories().requestFakeChatListMessage(this);
} else if (const auto from = migrateFrom()) {
// In megagroups we just try to use
// the message from the original group.
from->allowChatListMessageResolve();
from->requestChatListMessage();
}
}
@@ -3309,14 +3339,6 @@ bool History::hasOrphanMediaGroupPart() const {
return last->groupId() != MessageGroupId();
}
bool History::removeOrphanMediaGroupPart() {
if (hasOrphanMediaGroupPart()) {
clear(ClearType::Unload);
return true;
}
return false;
}
std::vector<MsgId> History::collectMessagesFromParticipantToDelete(
not_null<PeerData*> participant) const {
auto result = std::vector<MsgId>();

View File

@@ -111,7 +111,6 @@ public:
Element *findLastNonEmpty() const;
Element *findLastDisplayed() const;
bool hasOrphanMediaGroupPart() const;
bool removeOrphanMediaGroupPart();
[[nodiscard]] std::vector<MsgId> collectMessagesFromParticipantToDelete(
not_null<PeerData*> participant) const;
@@ -387,7 +386,7 @@ public:
const QString &chatListNameSortKey() const override;
const base::flat_set<QString> &chatListNameWords() const override;
const base::flat_set<QChar> &chatListFirstLetters() const override;
void loadUserpic() override;
void chatListPreloadData() override;
void paintUserpic(
Painter &p,
Ui::PeerUserpicView &view,
@@ -467,6 +466,7 @@ private:
IsForum = (1 << 3),
FakeUnreadWhileOpened = (1 << 4),
HasPinnedMessages = (1 << 5),
ResolveChatListMessage = (1 << 6),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) {
@@ -553,6 +553,8 @@ private:
void setChatListMessageFromLast();
void setChatListMessageUnknown();
void setFakeChatListMessage();
void allowChatListMessageResolve();
void resolveChatListMessageGroup();
// Add all items to the unread mentions if we were not loaded at bottom and now are.
void checkAddAllToUnreadMentions();

View File

@@ -3946,8 +3946,17 @@ void HistoryInner::notifyIsBotChanged() {
}
void HistoryInner::notifyMigrateUpdated() {
_migrated = _history->migrateFrom();
_migrated->translateTo(_history->translatedTo());
const auto migrated = _history->migrateFrom();
if (_migrated != migrated) {
if (_migrated) {
_migrated->delegateMixin()->setCurrent(nullptr);
}
_migrated = migrated;
if (_migrated) {
_migrated->delegateMixin()->setCurrent(this);
_migrated->translateTo(_history->translatedTo());
}
}
}
void HistoryInner::applyDragSelection() {

View File

@@ -491,7 +491,13 @@ HistoryWidget::HistoryWidget(
_botCommandStart->hide();
session().attachWebView().requestBots();
session().attachWebView().attachBotsUpdates(
rpl::merge(
session().attachWebView().attachBotsUpdates(),
session().changes().peerUpdates(
Data::PeerUpdate::Flag::Rights
) | rpl::filter([=](const Data::PeerUpdate &update) {
return update.peer == _peer;
}) | rpl::to_empty
) | rpl::start_with_next([=] {
refreshAttachBotsMenu();
}, lifetime());
@@ -505,7 +511,16 @@ HistoryWidget::HistoryWidget(
_attachDragAreas = DragArea::SetupDragAreaToContainer(
this,
crl::guard(this, [=](not_null<const QMimeData*> d) {
return _history && _canSendMessages && !isRecording();
if (!_peer || isRecording()) {
return false;
}
const auto replyTo = (_replyToId && !_editMsgId)
? _replyEditMsg
: 0;
const auto topic = replyTo ? replyTo->topic() : nullptr;
return topic
? Data::CanSendAnyOf(topic, Data::FilesSendRestrictions())
: Data::CanSendAnyOf(_peer, Data::FilesSendRestrictions());
}),
crl::guard(this, [=](bool f) { _field->setAcceptDrops(f); }),
crl::guard(this, [=] { updateControlsGeometry(); }));

View File

@@ -523,9 +523,9 @@ void BottomInfo::layoutReactionsText() {
_reactions.clear();
return;
}
auto sorted = ranges::view::all(
auto sorted = ranges::views::all(
_data.reactions
) | ranges::view::transform([](const MessageReaction &reaction) {
) | ranges::views::transform([](const MessageReaction &reaction) {
return not_null{ &reaction };
}) | ranges::to_vector;
ranges::sort(

View File

@@ -355,6 +355,11 @@ protected:
int resizeGetHeight(int newWidth) override;
private:
using ScrollTopState = ListMemento::ScrollTopState;
using PointState = HistoryView::PointState;
using CursorState = HistoryView::CursorState;
using ChosenReaction = HistoryView::Reactions::ChosenReaction;
struct MouseState {
MouseState();
MouseState(
@@ -405,10 +410,6 @@ private:
Selecting,
Deselecting,
};
using ScrollTopState = ListMemento::ScrollTopState;
using PointState = HistoryView::PointState;
using CursorState = HistoryView::CursorState;
using ChosenReaction = HistoryView::Reactions::ChosenReaction;
void onTouchSelect();
void onTouchScrollTimer();

View File

@@ -2616,9 +2616,18 @@ void RepliesWidget::clearSelected() {
}
void RepliesWidget::setupDragArea() {
const auto filter = [=](const auto &d) {
if (!_history || _composeControls->isRecording()) {
return false;
}
const auto peer = _history->peer;
return _topic
? Data::CanSendAnyOf(_topic, Data::FilesSendRestrictions())
: Data::CanSendAnyOf(peer, Data::FilesSendRestrictions());
};
const auto areas = DragArea::SetupDragAreaToContainer(
this,
[=](auto d) { return _history && !_composeControls->isRecording(); },
filter,
nullptr,
[=] { updateControlsGeometry(); });

View File

@@ -124,7 +124,9 @@ TopBarWidget::TopBarWidget(
_groupCall->setClickedCallback([=] { groupCall(); });
_menuToggle->setClickedCallback([=] { showPeerMenu(); });
_infoToggle->setClickedCallback([=] { toggleInfoSection(); });
_back->addClickHandler([=] { backClicked(); });
_back->setClickedCallback([=] {
InvokeQueued(_back.data(), [=] { backClicked(); });
});
_cancelChoose->setClickedCallback(
[=] { _cancelChooseForReport.fire({}); });

View File

@@ -111,9 +111,9 @@ void InlineList::layoutButtons() {
_buttons.clear();
return;
}
auto sorted = ranges::view::all(
auto sorted = ranges::views::all(
_data.reactions
) | ranges::view::transform([](const MessageReaction &reaction) {
) | ranges::views::transform([](const MessageReaction &reaction) {
return not_null{ &reaction };
}) | ranges::to_vector;
const auto &list = _owner->list(::Data::Reactions::Type::All);
@@ -643,7 +643,7 @@ InlineListData InlineListDataFromMessage(not_null<Message*> message) {
result.recent.reserve(recent.size());
for (const auto &[id, list] : recent) {
result.recent.emplace(id).first->second = list
| ranges::view::transform(&Data::RecentReaction::peer)
| ranges::views::transform(&Data::RecentReaction::peer)
| ranges::to_vector;
}
}

View File

@@ -220,9 +220,9 @@ void Controller::showReaction(const ReactionId &reaction) {
appendRow(peer, reaction);
}
} else {
_filtered = _all | ranges::view::filter([&](const AllEntry &entry) {
_filtered = _all | ranges::views::filter([&](const AllEntry &entry) {
return (entry.second == reaction);
}) | ranges::view::transform(
}) | ranges::views::transform(
&AllEntry::first
) | ranges::to_vector;
for (const auto peer : _filtered) {

View File

@@ -18,7 +18,7 @@ userpicBuilderEmojiSubtitle: FlatLabel(defaultFlatLabel) {
textFg: windowSubTextFg;
}
userpicBuilderEmojiSubtitlePadding: margins(0px, 9px, 0px, 2px);
userpicBuilderEmojiBubblePaletteSize: size(356px, 56px);
userpicBuilderEmojiBubblePaletteWidth: 356px;
userpicBuilderEmojiBubblePalettePadding: margins(12px, 8px, 12px, 8px);
userpicBuilderEmojiSelectorLeft: 5px;

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/random.h"
#include "base/timer.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h"
#include "data/stickers/data_custom_emoji.h"
#include "info/userpic/info_userpic_emoji_builder.h"
@@ -27,6 +28,128 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <random>
namespace UserpicBuilder {
namespace {
constexpr auto kTimeout = crl::time(1500);
class StickerProvider final {
public:
StickerProvider(not_null<Data::Session*> owner);
void setDocuments(std::vector<DocumentId> documents);
[[nodiscard]] DocumentId documentId() const;
[[nodiscard]] auto documentChanged() const
-> rpl::producer<not_null<DocumentData*>>;
private:
void processDocumentIndex(int documentIndex);
[[nodiscard]] DocumentData *lookupAndRememberSticker(int documentIndex);
[[nodiscard]] std::pair<DocumentData*, int> lookupSticker(
int documentIndex) const;
const not_null<Data::Session*> _owner;
int _documentIndex = 0;
std::vector<DocumentId> _shuffledDocuments;
base::Timer _timer;
rpl::event_stream<not_null<DocumentData*>> _documentChanged;
rpl::lifetime _resolvingLifetime;
rpl::lifetime _downloadFinishedLifetime;
};
StickerProvider::StickerProvider(not_null<Data::Session*> owner)
: _owner(owner) {
_timer.setCallback([=] {
_documentIndex++;
if (_documentIndex >= _shuffledDocuments.size()) {
_documentIndex = 0;
}
processDocumentIndex(_documentIndex);
});
}
DocumentId StickerProvider::documentId() const {
const auto &[document, index] = lookupSticker(_documentIndex);
return document ? document->id : DocumentId(0);
}
void StickerProvider::setDocuments(std::vector<DocumentId> documents) {
if (documents.empty()) {
return;
}
auto rd = std::random_device();
ranges::shuffle(documents, std::mt19937(rd()));
_shuffledDocuments = std::move(documents);
_documentIndex = 0;
processDocumentIndex(_documentIndex);
}
auto StickerProvider::documentChanged() const
-> rpl::producer<not_null<DocumentData*>> {
return _documentChanged.events();
}
void StickerProvider::processDocumentIndex(int documentIndex) {
if (const auto document = lookupAndRememberSticker(documentIndex)) {
_resolvingLifetime.destroy();
_owner->customEmojiManager().resolve(
document->id
) | rpl::start_with_next([=](not_null<DocumentData*> d) {
_resolvingLifetime.destroy();
_downloadFinishedLifetime.destroy();
const auto mediaView = d->createMediaView();
_downloadFinishedLifetime.add([=] {
[[maybe_unused]] const auto copy = mediaView;
});
mediaView->checkStickerLarge();
mediaView->goodThumbnailWanted();
rpl::single(
rpl::empty_value()
) | rpl::then(
_owner->session().downloaderTaskFinished()
) | rpl::start_with_next([=] {
if (mediaView->loaded()) {
_timer.callOnce(kTimeout);
_documentChanged.fire_copy(mediaView->owner());
_downloadFinishedLifetime.destroy();
}
}, _downloadFinishedLifetime);
}, _resolvingLifetime);
} else if (!_resolvingLifetime) {
_timer.callOnce(kTimeout);
}
}
DocumentData *StickerProvider::lookupAndRememberSticker(int documentIndex) {
const auto &[document, index] = lookupSticker(documentIndex);
if (document) {
_documentIndex = index;
}
return document;
}
std::pair<DocumentData*, int> StickerProvider::lookupSticker(
int documentIndex) const {
const auto size = _shuffledDocuments.size();
for (auto i = 0; i < size; i++) {
const auto unrestrictedIndex = documentIndex + i;
const auto index = (unrestrictedIndex >= size)
? (unrestrictedIndex - size)
: unrestrictedIndex;
const auto id = _shuffledDocuments[index];
const auto document = _owner->document(id);
if (document->sticker()) {
return { document, index };
}
}
return { nullptr, 0 };
}
} // namespace
void AddEmojiBuilderAction(
not_null<Window::SessionController*> controller,
@@ -34,35 +157,23 @@ void AddEmojiBuilderAction(
rpl::producer<std::vector<DocumentId>> documents,
Fn<void(UserpicBuilder::Result)> &&done,
bool isForum) {
constexpr auto kTimeout = crl::time(1500);
struct State final {
State() {
colorIndex = base::RandomIndex(std::numeric_limits<int>::max());
}
void next() {
auto nextIndex = documentIndex.current() + 1;
if (nextIndex >= shuffledDocuments.size()) {
nextIndex = 0;
}
documentIndex = nextIndex;
}
void documentShown() {
if (!firstDocumentShown) {
firstDocumentShown = true;
} else {
colorIndex = base::RandomIndex(
std::numeric_limits<int>::max());
}
timer.callOnce(kTimeout);
}
rpl::variable<int> documentIndex;
rpl::variable<int> colorIndex;
std::vector<DocumentId> shuffledDocuments;
bool firstDocumentShown = false;
base::Timer timer;
struct State final {
State(not_null<Window::SessionController*> controller)
: manager(&controller->session().data())
, colorIndex(rpl::single(
rpl::empty_value()
) | rpl::then(
manager.documentChanged() | rpl::skip(1) | rpl::to_empty
) | rpl::map([] {
return base::RandomIndex(std::numeric_limits<int>::max());
})) {
}
StickerProvider manager;
rpl::variable<int> colorIndex;
};
const auto state = menu->lifetime().make_state<State>();
const auto state = menu->lifetime().make_state<State>(controller);
auto item = base::make_unique_q<Ui::Menu::Action>(
menu.get(),
menu->st().menu,
@@ -70,10 +181,7 @@ void AddEmojiBuilderAction(
menu.get(),
tr::lng_attach_profile_emoji(tr::now),
[=, done = std::move(done), docs = rpl::duplicate(documents)] {
const auto index = state->documentIndex.current();
const auto id = index < state->shuffledDocuments.size()
? state->shuffledDocuments[index]
: 0;
const auto id = state->manager.documentId();
UserpicBuilder::ShowLayer(
controller,
{ id, state->colorIndex.current(), docs, {}, isForum },
@@ -81,29 +189,10 @@ void AddEmojiBuilderAction(
}),
nullptr,
nullptr);
state->timer.setCallback([=] { state->next(); });
const auto icon = UserpicBuilder::CreateEmojiUserpic(
item.get(),
st::restoreUserpicIcon.size,
state->documentIndex.value(
) | rpl::filter([=](int index) {
if (index >= state->shuffledDocuments.size()) {
state->next();
return false;
}
const auto id = state->shuffledDocuments[index];
if (!controller->session().data().document(id)->sticker()) {
state->next();
return false;
}
return true;
}) | rpl::map([=](int index) {
return controller->session().data().customEmojiManager().resolve(
state->shuffledDocuments[index]);
}) | rpl::flatten_latest() | rpl::map([=](not_null<DocumentData*> d) {
state->documentShown();
return d;
}),
state->manager.documentChanged(),
state->colorIndex.value(),
isForum);
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
@@ -115,13 +204,7 @@ void AddEmojiBuilderAction(
rpl::duplicate(
documents
) | rpl::start_with_next([=](std::vector<DocumentId> documents) {
if (documents.empty()) {
return;
}
auto rd = std::random_device();
ranges::shuffle(documents, std::mt19937(rd()));
state->shuffledDocuments = std::move(documents);
state->documentIndex.force_assign(0);
state->manager.setDocuments(std::move(documents));
}, item->lifetime());
menu->addAction(std::move(item));

View File

@@ -250,7 +250,7 @@ EmojiSelector::Selector EmojiSelector::createEmojiList(
.customRecentFactory = [=](DocumentId id, Fn<void()> repaint) {
return manager->create(id, std::move(repaint), tag);
},
.st = &st::reactPanelEmojiPan,
.st = &st::userpicBuilderEmojiPan,
};
const auto list = scroll->setOwnedWidget(
object_ptr<ChatHelpers::EmojiListWidget>(scroll, std::move(args)));
@@ -274,7 +274,8 @@ EmojiSelector::Selector EmojiSelector::createStickersList(
object_ptr<ChatHelpers::StickersListWidget>(
scroll,
_controller,
Window::GifPauseReason::Any));
Window::GifPauseReason::Any,
ChatHelpers::StickersListMode::UserpicBuilder));
const auto footer = list->createFooter().data();
list->refreshRecent();
list->chosen(
@@ -418,7 +419,8 @@ not_null<Ui::VerticalLayout*> CreateUserpicBuilder(
data.isForum)),
st::userpicBuilderEmojiPreviewPadding)->entity();
if (const auto id = data.documentId) {
if (const auto document = controller->session().data().document(id)) {
const auto document = controller->session().data().document(id);
if (document && document->sticker()) {
preview->setDocument(document);
}
}
@@ -434,8 +436,13 @@ not_null<Ui::VerticalLayout*> CreateUserpicBuilder(
const auto paletteBg = Ui::AddBubbleWrap(
container,
st::userpicBuilderEmojiBubblePaletteSize);
const auto palette = Ui::CreateChild<Ui::RpWidget>(paletteBg.get());
QSize(
st::userpicBuilderEmojiBubblePaletteWidth,
std::abs(Ui::BubbleWrapInnerRect(QRect(0, 0, 0, 0)).height())
+ st::userpicBuilderEmojiAccentColorSize
+ rect::m::sum::v(
st::userpicBuilderEmojiBubblePalettePadding)));
const auto palette = Ui::CreateChild<Ui::VerticalLayout>(paletteBg.get());
{
constexpr auto kColorsCount = int(7);
const auto checkIsSpecial = [=](int i) {
@@ -522,7 +529,7 @@ not_null<Ui::VerticalLayout*> CreateUserpicBuilder(
const auto selectorBg = Ui::AddBubbleWrap(
container,
QSize(
st::userpicBuilderEmojiBubblePaletteSize.width(),
st::userpicBuilderEmojiBubblePaletteWidth,
st::userpicBuilderEmojiSelectorMinHeight));
const auto selector = Ui::CreateChild<EmojiSelector>(
selectorBg.get(),

View File

@@ -1044,17 +1044,32 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
not_null<PeerData*> peer,
Fn<Api::SendAction()> actionFactory,
Fn<void(bool)> attach) {
if (!Data::CanSend(peer, ChatRestriction::SendInline)) {
return nullptr;
}
auto result = std::make_unique<Ui::DropdownMenu>(
parent,
st::dropdownMenuWithIcons);
const auto bots = &peer->session().attachWebView();
const auto raw = result.get();
raw->addAction(tr::lng_attach_photo_or_video(tr::now), [=] {
attach(true);
}, &st::menuIconPhoto);
raw->addAction(tr::lng_attach_document(tr::now), [=] {
attach(false);
}, &st::menuIconFile);
auto minimal = 0;
if (Data::CanSend(peer, ChatRestriction::SendPhotos, false)) {
++minimal;
raw->addAction(tr::lng_attach_photo_or_video(tr::now), [=] {
attach(true);
}, &st::menuIconPhoto);
}
const auto fileTypes = ChatRestriction::SendVideos
| ChatRestriction::SendGifs
| ChatRestriction::SendStickers
| ChatRestriction::SendMusic
| ChatRestriction::SendFiles;
if (Data::CanSendAnyOf(peer, fileTypes)) {
++minimal;
raw->addAction(tr::lng_attach_document(tr::now), [=] {
attach(false);
}, &st::menuIconFile);
}
for (const auto &bot : bots->attachBots()) {
if (!PeerMatchesTypes(peer, bot.user, bot.types)) {
continue;
@@ -1082,7 +1097,7 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
}, action->lifetime());
raw->addAction(std::move(action));
}
if (raw->actions().size() < 3) {
if (raw->actions().size() <= minimal) {
return nullptr;
}
return result;

View File

@@ -158,18 +158,18 @@ Language ParseLanguage(const MTPLangPackLanguage &data) {
CloudManager::CloudManager(Instance &langpack)
: _langpack(langpack) {
const auto mtpLifetime = _lifetime.make_state<rpl::lifetime>();
Core::App().domain().activeValue(
) | rpl::map([=](Main::Account *account) {
if (!account) {
_api.reset();
}
return account
? account->mtpMainSessionValue()
: rpl::never<not_null<MTP::Instance*>>();
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
_api.emplace(instance);
resendRequests();
) | rpl::filter([=](Main::Account *account) {
return (account != nullptr);
}) | rpl::start_with_next_done([=](Main::Account *account) {
*mtpLifetime = account->mtpMainSessionValue(
) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
_api.emplace(instance);
resendRequests();
});
}, [=] {
_api.reset();
}, _lifetime);
}

View File

@@ -202,8 +202,6 @@ Account &Domain::active() const {
return *_active.current();
}
rpl::producer<not_null<Account*>> Domain::activeChanges() const {
return _active.changes() | rpl::map([](Account *value) {
return not_null{ value };

View File

@@ -79,6 +79,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/download_path_box.h"
#include "boxes/connection_box.h"
#include "storage/storage_account.h"
#include "main/main_domain.h"
#include "media/audio/media_audio.h"
#include "media/player/media_player_panel.h"
#include "media/player/media_player_widget.h"
@@ -1265,6 +1266,8 @@ bool MainWidget::showHistoryInDifferentWindow(
const SectionShow &params,
MsgId showAtMsgId) {
const auto peer = session().data().peer(peerId);
const auto account = &session().account();
auto primary = Core::App().separateWindowForAccount(account);
if (const auto separate = Core::App().separateWindowForPeer(peer)) {
if (separate == &_controller->window()) {
return false;
@@ -1276,8 +1279,6 @@ bool MainWidget::showHistoryInDifferentWindow(
separate->activate();
return true;
} else if (isPrimary()) {
const auto primary = Core::App().separateWindowForAccount(
&peer->account());
if (primary && primary != &_controller->window()) {
primary->sessionController()->showPeerHistory(
peerId,
@@ -1291,18 +1292,17 @@ bool MainWidget::showHistoryInDifferentWindow(
return true;
} else if (singlePeer()->id == peerId) {
return false;
} else if (!primary) {
Core::App().domain().activate(account);
primary = Core::App().separateWindowForAccount(account);
}
const auto primary = Core::App().activePrimaryWindow();
if (&primary->account() != &session().account()) {
primary->showAccount(&session().account());
}
if (&primary->account() == &session().account()) {
if (primary && &primary->account() == account) {
primary->sessionController()->showPeerHistory(
peerId,
params,
showAtMsgId);
primary->activate();
}
primary->activate();
return true;
}

View File

@@ -194,7 +194,6 @@ void MainWindow::setupPasscodeLock() {
_passcodeLock.create(bodyWidget(), &controller());
updateControlsGeometry();
Core::App().hideMediaView();
ui_hideSettingsAndLayer(anim::type::instant);
if (_main) {
_main->hide();

View File

@@ -3380,6 +3380,13 @@ void OverlayWidget::switchToPip() {
}) | rpl::start_with_next([=] {
_pip = nullptr;
}, _pip->lifetime);
Core::App().passcodeLockChanges(
) | rpl::filter(
rpl::mappers::_1
) | rpl::start_with_next([=] {
_pip = nullptr;
}, _pip->lifetime);
}
if (isHidden()) {

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "stripe/stripe_card.h"
#include <vector>
#include <optional>
class QDate;

View File

@@ -17,7 +17,6 @@ public:
private:
void initHook() override;
void initHighDpi() override;
bool launchUpdater(UpdaterLaunch action) override;

View File

@@ -27,11 +27,6 @@ void Launcher::initHook() {
base::RegisterBundledResources(u"Telegram.rcc"_q);
}
void Launcher::initHighDpi() {
// macOS Retina display support is working fine.
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
}
bool Launcher::launchUpdater(UpdaterLaunch action) {
if (cExeName().isEmpty()) {
return false;

View File

@@ -226,7 +226,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
void MainWindow::closeWithoutDestroy() {
NSWindow *nsWindow = [reinterpret_cast<NSView*>(winId()) window];
auto isFullScreen = (([nsWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask);
auto isFullScreen = (([nsWindow styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen);
if (isFullScreen) {
_hideAfterFullScreenTimer.callOnce(kHideAfterFullscreenTimeoutMs);
[nsWindow toggleFullScreen:nsWindow];
@@ -266,7 +266,7 @@ bool MainWindow::preventsQuit(Core::QuitReason reason) {
// chromium.org/developers/design-documents/confirm-to-quit-experiment
return (reason == Core::QuitReason::QtQuitEvent)
&& Core::App().settings().macWarnBeforeQuit()
&& ([[NSApp currentEvent] type] == NSKeyDown)
&& ([[NSApp currentEvent] type] == NSEventTypeKeyDown)
&& !Platform::ConfirmQuit::RunModal(
tr::lng_mac_hold_to_quit(
tr::now,

View File

@@ -266,7 +266,10 @@ void SetApplicationIcon(const QIcon &icon) {
void objc_debugShowAlert(const QString &str) {
@autoreleasepool {
[[NSAlert alertWithMessageText:@"Debug Message" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", Q2NSString(str)] runModal];
NSAlert *alert = [[NSAlert alloc] init];
alert.messageText = @"Debug Message";
alert.informativeText = Q2NSString(str);
[alert runModal];
}
}

View File

@@ -513,6 +513,12 @@ settingsPremiumUserAbout: FlatLabel(boxDividerLabel) {
settingsPremiumLock: icon{{ "emoji/premium_lock", windowActiveTextFg, point(0px, 1px) }};
settingsPremiumLockSkip: 3px;
settingsBlockedListSubtitleAddPadding: margins(0px, 1px, 0px, -4px);
settingsBlockedListIconPadding: margins(0px, 34px, 0px, 5px);
settingsBlockedList: PeerList(peerListBox) {
padding: margins(0px, 0px, 0px, membersMarginBottom);
}
requestPeerRestriction: FlatLabel(defaultFlatLabel) {
minWidth: 240px;
textFg: membersAboutLimitFg;

View File

@@ -98,7 +98,7 @@ QPointer<Ui::RpWidget> Blocked::createPinnedToTop(not_null<QWidget*> parent) {
AddSubsectionTitle(
subtitle->entity(),
rpl::duplicate(subtitleText),
st::blockedUsersListSubtitleAddPadding);
st::settingsBlockedListSubtitleAddPadding);
subtitle->toggleOn(
rpl::merge(
_emptinessChanges.events() | rpl::map(!rpl::mappers::_1),
@@ -134,6 +134,7 @@ void Blocked::setupContent() {
};
auto controller = std::make_unique<BlockedBoxController>(_controller);
controller->setStyleOverrides(&st::settingsBlockedList);
const auto content = listWrap->entity()->add(
object_ptr<PeerListContent>(this, controller.get()));
@@ -171,7 +172,7 @@ void Blocked::setupContent() {
st::changePhoneIconSize,
},
},
st::blockedUsersListIconPadding);
st::settingsBlockedListIconPadding);
content->add(std::move(icon.widget));
_showFinished.events(
@@ -197,7 +198,7 @@ void Blocked::setupContent() {
st::changePhoneDescription)),
st::changePhoneDescriptionPadding);
AddSkip(content, st::blockedUsersListIconPadding.top());
AddSkip(content, st::settingsBlockedListIconPadding.top());
}
Ui::ResizeFitChild(this, _container);

View File

@@ -689,7 +689,7 @@ void SetupAccountsWrap(
if (!locked) {
addAction(tr::lng_menu_activate(tr::now), [=] {
Core::App().domain().activate(&session->account());
callback({});
}, &st::menuIconProfile);
}

View File

@@ -65,6 +65,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
#include <QtGui/QWindow>
namespace Settings {
namespace {
@@ -474,8 +475,9 @@ void SetupInterfaceScale(
if constexpr (Platform::IsMac()) {
return QString::number(scale) + '%';
} else {
const auto ratio = window->widget()->devicePixelRatioF();
return QString::number(int(scale * ratio)) + '%';
const auto handle = window->widget()->windowHandle();
const auto ratio = handle->devicePixelRatio();
return QString::number(base::SafeRound(scale * ratio)) + '%';
}
};
label->setText(labelText(cEvalScale(scale)));

View File

@@ -1053,7 +1053,7 @@ void FileLoadTask::process(Args &&args) {
if (image->modifications.paint) {
const auto documents = ExtractStickersFromScene(image);
_result->attachedStickers = documents
| ranges::view::transform(&DocumentData::mtpInput)
| ranges::views::transform(&DocumentData::mtpInput)
| ranges::to_vector;
}
}

View File

@@ -95,12 +95,12 @@ if %Build64% neq 0 (
set "UpdateFile=tx64upd%AppVersion%"
set "SetupFile=tsetup-x64.%AppVersionStrFull%.exe"
set "PortableFile=tportable-x64.%AppVersionStrFull%.zip"
set "DumpSymsPath=%SolutionPath%\..\..\Libraries\win64\breakpad\src\out\Release_x64\dump_syms.exe"
set "DumpSymsPath=%SolutionPath%\..\..\Libraries\win64\breakpad\src\tools\windows\dump_syms\Release\dump_syms.exe"
) else (
set "UpdateFile=tupdate%AppVersion%"
set "SetupFile=tsetup.%AppVersionStrFull%.exe"
set "PortableFile=tportable.%AppVersionStrFull%.zip"
set "DumpSymsPath=%SolutionPath%\..\..\Libraries\breakpad\src\out\Release\dump_syms.exe"
set "DumpSymsPath=%SolutionPath%\..\..\Libraries\breakpad\src\tools\windows\dump_syms\Release\dump_syms.exe"
)
set "ReleasePath=%SolutionPath%\Release"
set "DeployPath=%ReleasePath%\deploy\%AppVersionStrMajor%\%AppVersionStrFull%"

View File

@@ -710,9 +710,8 @@ release:
stage('libde265', """
win:
git clone https://github.com/strukturag/libde265.git
git clone --depth 1 -b v1.0.11 https://github.com/strukturag/libde265.git
cd libde265
git checkout c96962cf6a0259f1678e9a0e1566eb9b5516093a
cmake . ^
-A %WIN32X64% ^
-DCMAKE_INSTALL_PREFIX=%LIBS_DIR%/local ^
@@ -735,7 +734,7 @@ release:
stage('libheif', """
win:
git clone --depth 1 -b v1.14.0 https://github.com/strukturag/libheif.git
git clone --depth 1 -b v1.14.2 https://github.com/strukturag/libheif.git
cd libheif
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/HAVE_VISIBILITY/LIBHEIF_STATIC_BUILD/g' libheif/CMakeLists.txt
@@ -761,7 +760,7 @@ release:
stage('libjxl', """
win:
git clone -b v0.7.0 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
git clone -b v0.8.1 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
cd libjxl
cmake . ^
-A %WIN32X64% ^
@@ -781,6 +780,7 @@ win:
-DJPEGXL_ENABLE_MANPAGES=OFF ^
-DJPEGXL_ENABLE_EXAMPLES=OFF ^
-DJPEGXL_ENABLE_JNI=OFF ^
-DJPEGXL_ENABLE_JPEGLI_LIBJPEG=OFF ^
-DJPEGXL_ENABLE_SJPEG=OFF ^
-DJPEGXL_ENABLE_OPENEXR=OFF ^
-DJPEGXL_ENABLE_SKCMS=ON ^
@@ -1105,9 +1105,8 @@ depends:python/Scripts/activate.bat
release:
ninja -C out/Release%FolderPostfix% common crash_generation_client exception_handler
cd tools\\windows\\dump_syms
gyp dump_syms.gyp --format=ninja
cd ..\\..\\..
ninja -C out/Release%FolderPostfix% dump_syms
gyp dump_syms.gyp --format=msvs
msbuild dump_syms.vcxproj /property:Configuration=Release /property:Platform="x64"
win:
deactivate
mac:

View File

@@ -163,6 +163,12 @@ if not os.path.isdir(local_folder):
local_folder = local_folder + '/'
files = []
files.append({
'local': 'sources',
'remote': 'tdesktop-' + version + '-full.tar.gz',
'mime': 'application/x-gzip',
'label': 'Source code (tar.gz, full)',
})
files.append({
'local': 'tsetup.' + version_full + '.exe',
'remote': 'tsetup.' + version_full + '.exe',
@@ -205,12 +211,6 @@ files.append({
'mime': 'application/octet-stream',
'label': 'Linux 64 bit: Binary',
})
files.append({
'local': 'sources',
'remote': 'tdesktop-' + version + '-full.tar.gz',
'mime': 'application/x-gzip',
'label': 'Source code (tar.gz, full)',
})
r = requests.get(url + 'repos/telegramdesktop/tdesktop/releases/tags/v' + version)
if r.status_code == 404:

View File

@@ -1,7 +1,7 @@
AppVersion 4006002
AppVersion 4006003
AppVersionStrMajor 4.6
AppVersionStrSmall 4.6.2
AppVersionStr 4.6.2
AppVersionStrSmall 4.6.3
AppVersionStr 4.6.3
BetaChannel 0
AlphaVersion 0
AppVersionOriginal 4.6.2
AppVersionOriginal 4.6.3

View File

@@ -241,13 +241,12 @@ elseif (APPLE)
)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(lib_tgcalls
PRIVATE
-Wno-deprecated-volatile
-Wno-ambiguous-reversed-operator
)
endif()
target_compile_options_if_exists(lib_tgcalls
PRIVATE
-Wno-deprecated-volatile
-Wno-ambiguous-reversed-operator
-Wno-deprecated-declarations
)
remove_target_sources(lib_tgcalls ${tgcalls_loc}
platform/android/AndroidContext.cpp

View File

@@ -1,3 +1,8 @@
4.6.3 (15.02.23)
- Optimize chats list initial loading.
- Various crash fixes.
4.6.2 (07.02.23)
- One more attempt to fix fonts on Windows.

2
cmake

Submodule cmake updated: 17951fb650...86270a961e