Compare commits

..

54 Commits

Author SHA1 Message Date
Sprite
bf0ad9e7ca Explicitly specify signed modifier for char type 2022-06-25 07:13:57 +04:00
John Preston
fc7dcd0360 Version 4.0.2: Remove Saved Messages premium badge. 2022-06-25 00:06:13 +04:00
Ilya Fedin
14416a68db Fix openal pipewire version check in snap 2022-06-24 21:11:12 +04:00
John Preston
ee1a80abd7 Version 4.0.2.
- Fix window title on Windows 7. (again)
- Fix file chooser and global menu on macOS.
- Crash fix and OpenAL check for PipeWire fix on Linux.
2022-06-24 21:00:52 +04:00
John Preston
d392d9cb1f Fix a crash in window handling on Linux. 2022-06-24 20:59:55 +04:00
John Preston
65c7a9a554 Fix title on Win7 and macOS file chooser. 2022-06-24 20:45:14 +04:00
Ilya Fedin
1c98399c6f Fix pipewire version check in openal 2022-06-24 19:52:55 +04:00
John Preston
263ac2eb71 Version 4.0.1.
- Fix window title on Windows 7.
- Bug fixes and other minor improvements.
2022-06-24 13:07:47 +04:00
23rd
75d8e8ba7d Fixed opening of non-primary windows while recording voice message. 2022-06-24 04:07:16 +03:00
23rd
0fbd7d1a3b Fixed playback of recorded but not sent voice messages. 2022-06-24 04:07:16 +03:00
John Preston
8f0ba749d1 Fix history visibility edit button.
Regression was introduced in c3386fba52.

Fixes #24691.
2022-06-24 00:25:23 +04:00
John Preston
fc8ea688a3 Update profile badges order. 2022-06-23 17:53:36 +04:00
John Preston
2d651050ad Show premium badge in peer lists.
Fixes #24687.
2022-06-23 14:00:59 +04:00
John Preston
a94c42411b Show verified badge in chat top bar. 2022-06-23 11:35:44 +04:00
23rd
57f769f358 Returned lost method that checks tray existence. 2022-06-23 09:38:21 +03:00
John Preston
ce39eb2da9 Don't watch theme file while using theme editor. 2022-06-23 10:35:52 +04:00
Ilya Fedin
f7bc84fdd6 Automatically reload theme on file change 2022-06-23 10:09:59 +04:00
Ilya Fedin
28f75525b2 Update openal to 1.22.1
Downgrade pipewire headers as openal won't work with pipewire version less than headers it builds with now
2022-06-23 09:48:27 +04:00
John Preston
03c1f15961 Fix MentionClickHandler in non-context handler activations. 2022-06-23 09:47:54 +04:00
John Preston
2f92830f6a Use correct title in premium sticker toast. 2022-06-23 09:31:32 +04:00
John Preston
73af96e9c3 Hide reply keyboard if started typing. 2022-06-22 20:15:50 +04:00
John Preston
1e63a6a1a7 Fix possible crash in Windows Toast Notifications. 2022-06-22 20:07:17 +04:00
John Preston
0df699a054 Allow drag-n-drop-ing files up to 4 GB.
Fixes #24657.
2022-06-22 18:56:01 +04:00
John Preston
0e771312f4 Edit Chat Theme / Auto Delete on service message click. 2022-06-22 18:48:57 +04:00
John Preston
db15a58dde Fix separate windows with audio player.
Fixes https://bugs.telegram.org/c/18154
2022-06-22 16:42:46 +04:00
John Preston
d81c40f4c8 Fix new window crash for unavailable channels. 2022-06-22 15:30:56 +04:00
John Preston
e2624416af Allow base::WinRT::TryCreateInstance on Win7.
Fixes #24666.
2022-06-22 12:38:32 +04:00
John Preston
e72b4c6192 Allow complex forwarding from Saved to Saved. 2022-06-22 12:21:44 +04:00
John Preston
654fefaa72 Fix custom rank display in profile members dropdown. 2022-06-22 12:07:39 +04:00
John Preston
7f6c163449 Fix crash in video userpics.
Fixes #24665.
2022-06-22 12:03:47 +04:00
John Preston
5738998310 Fix window frame. 2022-06-22 12:03:37 +04:00
Ilya Fedin
45d2baa2c4 Restore missed QWindow::setScreen 2022-06-21 22:19:32 +04:00
John Preston
9033d49d76 Version 4.0.
- Premium: Send media and files each up to 4 GB in size.
- Premium: Download media and files at the fastest possible speed,
with no limits.
- Premium: Double most of the limits in the app.
- Premium: Get a new button next to any voice message
to generate a transcript of its audio.
- Premium: React with even more emoji,
including :clown: and 😍.
- Premium: Send unique stickers with additional effects,
updated monthly.
- Premium: Set a default chat folder
or enable tools to auto-archive and hide new chats.
- Premium: Subscribers have a badge next to their name,
showing they help support Telegram.
- Premium: Show off your profile video
that will be animated for everyone in chats and the chat list.
- Premium: Sponsored Messages that are sometimes shown
in public channels will no longer appear.
- Enable join requests for your public groups,
no invite links required.
- Users who open the group will see an Apply to Join Group button.
- Once approved by an admin,
users will be able to participate in the chat.
- Bots that are integrated into the attachment menu
can be programmed to work in groups and channels.
2022-06-21 02:04:35 +04:00
23rd
1b754d14ae Improved display some api errors in non-primary windows. 2022-06-20 23:08:37 +03:00
John Preston
d1c1b687c7 Update lib_ui submodule. 2022-06-21 00:05:45 +04:00
John Preston
8b44dcf8d0 Update cmake_helpers submodule. 2022-06-21 00:03:58 +04:00
Ilya Fedin
984094a7ff Partially revert "Use QWidget::screen/QWidget::mask instead of QWindow ones"
This partially reverts commit e5d8a1aa3c to use QWindow::setScreen.
2022-06-21 00:03:21 +04:00
John Preston
55285f327a Fix possible stack overflow crash. 2022-06-20 23:44:52 +04:00
John Preston
b85ad05f8a Fix possible crash in cached stickers playback. 2022-06-20 21:28:11 +04:00
John Preston
3c1663adeb Fix couple of possible crashes.
Fixes #24613.
2022-06-20 20:31:54 +04:00
John Preston
66e9c5ef16 Allow HiddenUrlClickHandler to work in a payment form. 2022-06-20 17:14:14 +04:00
John Preston
7027c0db0b Fix build with Qt >= 6.0 < 6.2 2022-06-20 15:09:51 +04:00
John Preston
6812f1e5ec Fix build with DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION. 2022-06-20 13:00:05 +04:00
John Preston
b963a68dd6 Fix windows taskbar notifications counter with multi-windows. 2022-06-20 12:56:50 +04:00
John Preston
1c720af9bc Clear history allowed when delete channel allowed. 2022-06-20 12:04:56 +04:00
John Preston
69f469a0f9 Fix bio limits in premium info page. 2022-06-20 11:57:31 +04:00
John Preston
fbc284af49 Fix auto-download limit.
Fixes #24642.
2022-06-20 11:48:19 +04:00
John Preston
ff51bf81f3 Allow clearing history in megagroups. 2022-06-20 11:30:43 +04:00
John Preston
29c61635de Revert some window title improvements.
Fixes #24617.
2022-06-20 11:13:49 +04:00
John Preston
1b9232e28d Always show premium badge in support mode. 2022-06-20 11:13:39 +04:00
John Preston
b84c876ba2 Fix opening links from bot inline reply markup. 2022-06-18 00:02:27 +04:00
John Preston
5fe1988d0a Suggest bot commands only in the start of the field. 2022-06-18 00:01:47 +04:00
John Preston
77330aa6a7 Fix a crash in adding a contact. 2022-06-18 00:01:30 +04:00
John Preston
03e60ed329 Fix uploading files > 500 Mb. 2022-06-18 00:00:56 +04:00
80 changed files with 611 additions and 218 deletions

View File

@@ -230,7 +230,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_limits_increase" = "Increase Limit";
"lng_sticker_premium_title" = "With Effects";
"lng_sticker_premium_text" = "This pack contains premium stickers like this one.";
"lng_sticker_premium_view" = "View";
"lng_reaction_premium_info" = "Click on the reaction to preview the animation.";

View File

@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="3.7.6.0" />
Version="4.0.2.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 3,7,6,0
PRODUCTVERSION 3,7,6,0
FILEVERSION 4,0,2,0
PRODUCTVERSION 4,0,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "3.7.6.0"
VALUE "FileVersion", "4.0.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.7.6.0"
VALUE "ProductVersion", "4.0.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,7,6,0
PRODUCTVERSION 3,7,6,0
FILEVERSION 4,0,2,0
PRODUCTVERSION 4,0,2,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", "3.7.6.0"
VALUE "FileVersion", "4.0.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.7.6.0"
VALUE "ProductVersion", "4.0.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -74,6 +74,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/sticker_set_box.h"
#include "boxes/premium_limits_box.h"
#include "window/notifications_manager.h"
#include "window/window_controller.h"
#include "window/window_lock_widgets.h"
#include "window/window_session_controller.h"
#include "inline_bots/inline_bot_result.h"
@@ -117,6 +118,26 @@ using UpdatedFileReferences = Data::UpdatedFileReferences;
return TimeId(msgId >> 32);
}
[[nodiscard]] std::shared_ptr<Window::Show> ShowForPeer(
not_null<PeerData*> peer) {
const auto separate = Core::App().separateWindowForPeer(peer);
const auto window = separate ? separate : Core::App().primaryWindow();
return std::make_shared<Window::Show>(window);
}
void ShowChannelsLimitBox(not_null<PeerData*> peer) {
const auto primary = Core::App().primaryWindow();
if (!primary) {
return;
}
primary->invokeForSessionController(
&peer->session().account(),
peer,
[&](not_null<Window::SessionController*> controller) {
controller->show(Box(ChannelsLimitBox, &peer->session()));
});
}
} // namespace
ApiWrap::ApiWrap(not_null<Main::Session*> session)
@@ -417,19 +438,25 @@ void ApiWrap::sendMessageFail(
not_null<PeerData*> peer,
uint64 randomId,
FullMsgId itemId) {
const auto show = ShowForPeer(peer);
if (error.type() == qstr("PEER_FLOOD")) {
Ui::show(Ui::MakeInformBox(
PeerFloodErrorText(&session(), PeerFloodType::Send)));
show->showBox(
Ui::MakeInformBox(
PeerFloodErrorText(&session(), PeerFloodType::Send)),
Ui::LayerOption::CloseOther);
} else if (error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
const auto link = Ui::Text::Link(
tr::lng_cant_more_info(tr::now),
session().createInternalLinkFull(qsl("spambot")));
Ui::show(Ui::MakeInformBox(
tr::lng_error_public_groups_denied(
tr::now,
lt_more_info,
link,
Ui::Text::WithEntities)));
show->showBox(
Ui::MakeInformBox(
tr::lng_error_public_groups_denied(
tr::now,
lt_more_info,
link,
Ui::Text::WithEntities)),
Ui::LayerOption::CloseOther);
} else if (error.type().startsWith(qstr("SLOWMODE_WAIT_"))) {
const auto chop = qstr("SLOWMODE_WAIT_").size();
const auto left = base::StringViewMid(error.type(), chop).toInt();
@@ -447,13 +474,21 @@ void ApiWrap::sendMessageFail(
Assert(peer->isUser());
if (const auto item = scheduled.lookupItem(peer->id, itemId.msg)) {
scheduled.removeSending(item);
Ui::show(Ui::MakeInformBox(tr::lng_cant_do_this()));
show->showBox(
Ui::MakeInformBox(tr::lng_cant_do_this()),
Ui::LayerOption::CloseOther);
}
} else if (error.type() == qstr("CHAT_FORWARDS_RESTRICTED")) {
Ui::ShowMultilineToast({ .text = { peer->isBroadcast()
? tr::lng_error_noforwards_channel(tr::now)
: tr::lng_error_noforwards_group(tr::now)
}, .duration = kJoinErrorDuration });
if (show->valid()) {
Ui::ShowMultilineToast({
.parentOverride = show->toastParent(),
.text = { peer->isBroadcast()
? tr::lng_error_noforwards_channel(tr::now)
: tr::lng_error_noforwards_group(tr::now)
},
.duration = kJoinErrorDuration
});
}
} else if (error.type() == qstr("PREMIUM_ACCOUNT_REQUIRED")) {
Settings::ShowPremium(&session(), "premium_stickers");
}
@@ -1214,7 +1249,7 @@ void ApiWrap::migrateDone(
void ApiWrap::migrateFail(not_null<PeerData*> peer, const QString &error) {
if (error == u"CHANNELS_TOO_MUCH"_q) {
Ui::show(Box(ChannelsLimitBox, _session));
ShowChannelsLimitBox(peer);
}
if (auto handlers = _migrateCallbacks.take(peer)) {
for (auto &handler : *handlers) {
@@ -1635,37 +1670,40 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
channel,
Data::PeerUpdate::Flag::ChannelAmIn);
} else if (!_channelAmInRequests.contains(channel)) {
auto requestId = request(MTPchannels_JoinChannel(
const auto requestId = request(MTPchannels_JoinChannel(
channel->inputChannel
)).done([=](const MTPUpdates &result) {
_channelAmInRequests.remove(channel);
applyUpdates(result);
}).fail([=](const MTP::Error &error) {
const auto &type = error.type();
if (type == qstr("CHANNEL_PRIVATE")
const auto show = ShowForPeer(channel);
if (type == u"CHANNEL_PRIVATE"_q
&& channel->invitePeekExpires()) {
channel->privateErrorReceived();
} else if (type == qstr("CHANNELS_TOO_MUCH")) {
Ui::show(Box(ChannelsLimitBox, _session));
} else if (type == u"CHANNELS_TOO_MUCH"_q) {
ShowChannelsLimitBox(channel);
} else {
const auto text = [&] {
if (type == qstr("INVITE_REQUEST_SENT")) {
if (type == u"INVITE_REQUEST_SENT"_q) {
return channel->isMegagroup()
? tr::lng_group_request_sent(tr::now)
: tr::lng_group_request_sent_channel(tr::now);
} else if (type == qstr("CHANNEL_PRIVATE")
|| type == qstr("CHANNEL_PUBLIC_GROUP_NA")
|| type == qstr("USER_BANNED_IN_CHANNEL")) {
} else if (type == u"CHANNEL_PRIVATE"_q
|| type == u"CHANNEL_PUBLIC_GROUP_NA"_q
|| type == u"USER_BANNED_IN_CHANNEL"_q) {
return channel->isMegagroup()
? tr::lng_group_not_accessible(tr::now)
: tr::lng_channel_not_accessible(tr::now);
} else if (type == qstr("USERS_TOO_MUCH")) {
} else if (type == u"USERS_TOO_MUCH"_q) {
return tr::lng_group_full(tr::now);
}
return QString();
}();
if (!text.isEmpty()) {
if (!text.isEmpty() && show->valid()) {
Ui::ShowMultilineToast({
.parentOverride = show->toastParent(),
.text = { text },
.duration = kJoinErrorDuration,
});

View File

@@ -365,6 +365,8 @@ void AddContactBox::save() {
firstName = lastName;
lastName = QString();
}
const auto weak = Ui::MakeWeak(this);
const auto session = _session;
_sentName = firstName;
_contactId = base::RandomValue<uint64>();
_addRequest = _session->api().request(MTPcontacts_ImportContacts(
@@ -375,18 +377,20 @@ void AddContactBox::save() {
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName)))
)).done(crl::guard(this, [=](
)).done(crl::guard(weak, [=](
const MTPcontacts_ImportedContacts &result) {
const auto &data = result.match([](
const auto &data) -> const MTPDcontacts_importedContacts& {
return data;
});
_session->data().processUsers(data.vusers());
session->data().processUsers(data.vusers());
if (!weak) {
return;
}
const auto extractUser = [&](const MTPImportedContact &data) {
return data.match([&](const MTPDimportedContact &data) {
return (data.vclient_id().v == _contactId)
? _session->data().userLoaded(data.vuser_id())
? session->data().userLoaded(data.vuser_id())
: nullptr;
});
};
@@ -398,7 +402,9 @@ void AddContactBox::save() {
if (user->isContact() || user->session().supportMode()) {
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
}
getDelegate()->hideLayer();
if (weak) { // showPeerHistory could close the box.
getDelegate()->hideLayer();
}
} else if (isBoxShown()) {
hideChildren();
_retrying = true;

View File

@@ -38,7 +38,7 @@ not_null<int64*> AddSizeLimitSlider(
using namespace Settings;
using Pair = base::flat_map<Type, int64>::value_type;
const auto limits = Ui::CreateChild<rpl::event_stream<int>>(
const auto limits = Ui::CreateChild<rpl::event_stream<int64>>(
container.get());
const auto currentLimit = ranges::max_element(
values,
@@ -51,7 +51,7 @@ not_null<int64*> AddSizeLimitSlider(
tr::lng_media_size_limit(),
limits->events_starting_with_copy(
startLimit
) | rpl::map([](int value) {
) | rpl::map([](int64 value) {
return tr::lng_media_size_up_to(
tr::now,
lt_size,
@@ -67,7 +67,7 @@ not_null<int64*> AddSizeLimitSlider(
Export::View::kSizeValueCount,
Export::View::SizeLimitByIndex,
*result,
[=](int value) {
[=](int64 value) {
*result = value;
limits->fire_copy(value);
});

View File

@@ -337,8 +337,6 @@ auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
lt_user,
{ user->firstName },
Ui::Text::RichLangValue);
} else if (_wipeHistoryJustClear) {
return std::nullopt;
} else {
result.checkbox.text = tr::lng_delete_for_everyone_check(tr::now);
}

View File

@@ -654,9 +654,13 @@ void PeerListRow::invalidatePixmapsCache() {
}
int PeerListRow::nameIconWidth() const {
return (special() || !_peer->isVerified())
return special()
? 0
: st::dialogsVerifiedIcon.width();
: _peer->isVerified()
? st::dialogsVerifiedIcon.width()
: (_peer->isPremium() && !_peer->isSelf())
? st::dialogsPremiumIcon.width()
: 0;
}
void PeerListRow::paintNameIcon(
@@ -665,7 +669,11 @@ void PeerListRow::paintNameIcon(
int y,
int outerWidth,
bool selected) {
st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
if (_peer->isVerified()) {
st::dialogsVerifiedIcon.paint(p, x, y, outerWidth);
} else if (_peer->isPremium() && !_peer->isSelf()) {
st::dialogsPremiumIcon.paint(p, x, y, outerWidth);
}
}
void PeerListRow::paintStatusText(

View File

@@ -1941,7 +1941,7 @@ auto ParticipantsBoxController::computeType(
? Badge::Fake
: user->isVerified()
? Badge::Verified
: (user->isPremium() && participant->session().premiumPossible())
: (user->isPremium() && participant->session().premiumBadgesShown())
? Badge::Premium
: Badge::None;
return result;

View File

@@ -608,7 +608,7 @@ void Controller::refreshHistoryVisibility() {
const auto withUsername = _typeDataSavedValue
&& (_typeDataSavedValue->privacy == Privacy::HasUsername);
_controls.historyVisibilityWrap->toggle(
(withUsername
(!withUsername
&& !_channelHasLocationOriginalValue
&& (!_linkedChatSavedValue || !*_linkedChatSavedValue)),
anim::type::instant);

View File

@@ -1722,12 +1722,12 @@ void DoubledLimitsPreviewBox(
});
}
{
const auto premium = limits.captionLengthPremium();
const auto premium = limits.aboutLengthPremium();
entries.push_back(Ui::Premium::ListEntry{
tr::lng_premium_double_limits_subtitle_bio(),
tr::lng_premium_double_limits_about_bio(
Ui::Text::RichLangValue),
limits.captionLengthDefault(),
limits.aboutLengthDefault(),
premium,
});
}

View File

@@ -3482,6 +3482,7 @@ void GroupCall::destroyController() {
DEBUG_LOG(("Call Info: Destroying call controller.."));
invalidate_weak_ptrs(&_instanceGuard);
_instance->stop();
crl::async([
instance = base::take(_instance),
done = _delegate->groupCallAddAsyncWaiter()
@@ -3497,6 +3498,8 @@ void GroupCall::destroyScreencast() {
if (_screenInstance) {
DEBUG_LOG(("Call Info: Destroying call screen controller.."));
invalidate_weak_ptrs(&_screenInstanceGuard);
_screenInstance->stop();
crl::async([
instance = base::take(_screenInstance),
done = _delegate->groupCallAddAsyncWaiter()

View File

@@ -574,6 +574,7 @@ void ChooseSourceProcess::setupSourcesGeometry() {
void ChooseSourceProcess::setupGeometryWithParent(
not_null<QWidget*> parent) {
_window->createWinId();
const auto parentScreen = [&] {
if (!::Platform::IsWayland()) {
if (const auto screen = QGuiApplication::screenAt(
@@ -585,7 +586,7 @@ void ChooseSourceProcess::setupGeometryWithParent(
}();
const auto myScreen = _window->screen();
if (parentScreen && myScreen != parentScreen) {
_window->setScreen(parentScreen);
_window->windowHandle()->setScreen(parentScreen);
}
_window->move(
parent->x() + (parent->width() - _window->width()) / 2,

View File

@@ -470,7 +470,7 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery(
}
return result;
} else if (text[i - 1] == '/') {
if (i < 2) {
if (i < 2 && !fragmentPosition) {
result.fromStart = (i == 1) && (fragmentPosition == 0);
result.query = text.mid(i - 1, position - fragmentPosition - i + 1);
}

View File

@@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
namespace {
@@ -118,16 +119,21 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) {
? QString::fromUtf8(parsedUrl.toEncoded())
: ShowEncoded(displayed);
const auto my = context.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
controller->show(
Ui::MakeConfirmBox({
.text = (tr::lng_open_this_link(tr::now)
+ qsl("\n\n")
+ displayUrl),
.confirmed = [=](Fn<void()> hide) { hide(); open(); },
.confirmText = tr::lng_open_link(),
}),
Ui::LayerOption::KeepOther);
const auto controller = my.sessionWindow.get();
const auto use = controller
? &controller->window()
: Core::App().activeWindow();
auto box = Ui::MakeConfirmBox({
.text = (tr::lng_open_this_link(tr::now)
+ qsl("\n\n")
+ displayUrl),
.confirmed = [=](Fn<void()> hide) { hide(); open(); },
.confirmText = tr::lng_open_link(),
});
if (my.show) {
my.show->showBox(std::move(box));
} else if (use) {
use->show(std::move(box), Ui::LayerOption::KeepOther);
}
} else {
open();
@@ -182,9 +188,15 @@ void MentionClickHandler::onClick(ClickContext context) const {
const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
const auto controller = my.sessionWindow.get();
const auto use = controller
? controller
: Core::App().activeWindow()
? Core::App().activeWindow()->sessionController()
: nullptr;
if (use) {
using Info = Window::SessionNavigation::PeerByLinkInfo;
controller->showPeerByLink(Info{
use->showPeerByLink(Info{
.usernameOrId = _tag.mid(1),
.resolveType = Window::ResolveType::Mention,
});

View File

@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "ui/basic_click_handlers.h"
#include "data/data_msg_id.h"
constexpr auto kPeerLinkPeerIdProperty = 0x01;
constexpr auto kPhotoLinkMediaProperty = 0x02;
@@ -15,6 +16,10 @@ constexpr auto kDocumentLinkMediaProperty = 0x03;
constexpr auto kSendReactionEmojiProperty = 0x04;
constexpr auto kReactionsCountEmojiProperty = 0x05;
namespace Ui {
class Show;
} // namespace Ui
namespace Main {
class Session;
} // namespace Main
@@ -35,6 +40,7 @@ struct ClickHandlerContext {
// Is filled from sections.
Fn<HistoryView::ElementDelegate*()> elementDelegate;
base::weak_ptr<Window::SessionController> sessionWindow;
std::shared_ptr<Ui::Show> show;
bool skipBotAutoLogin = false;
bool botStartAutoSubmit = false;
// Is filled from peer info.

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 = 3007006;
constexpr auto AppVersionStr = "3.7.6";
constexpr auto AppBetaVersion = true;
constexpr auto AppVersion = 4000002;
constexpr auto AppVersionStr = "4.0.2";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -641,8 +641,9 @@ void Histories::deleteAllMessages(
// }
}).send();
} else if (channel) {
using Flag = MTPchannels_DeleteHistory::Flag;
return session().api().request(MTPchannels_DeleteHistory(
MTP_flags(0),
MTP_flags(revoke ? Flag::f_for_everyone : Flag(0)),
channel->inputChannel,
MTP_int(deleteTillId)
)).done(finish).fail(finish).send();

View File

@@ -148,7 +148,7 @@ enum LocationType {
SecureFileLocation = 0xcbc7ee28, // mtpc_inputSecureFileLocation
};
enum FileStatus : char {
enum FileStatus : signed char {
FileDownloadFailed = -2,
FileUploadFailed = -1,
FileReady = 1,

View File

@@ -263,17 +263,27 @@ Widget::Widget(
const auto showAtMsgId = controller->uniqueChatsInSearchResults()
? ShowAtUnreadMsgId
: row.message.fullId.msg;
if (row.newWindow) {
if (row.newWindow && controller->canShowSeparateWindow(peer)) {
const auto active = controller->activeChatCurrent();
if (const auto history = active.history()) {
if (history->peer == peer) {
const auto fromActive = active.history()
? (active.history()->peer == peer)
: false;
const auto toSeparate = [=] {
Core::App().ensureSeparateWindowForPeer(
peer,
showAtMsgId);
};
if (fromActive) {
controller->window().preventOrInvoke([=] {
controller->content()->ui_showPeerHistory(
0,
Window::SectionShow::Way::ClearStack,
0);
}
toSeparate();
});
} else {
toSeparate();
}
Core::App().ensureSeparateWindowForPeer(peer, showAtMsgId);
} else {
controller->content()->choosePeer(peer->id, showAtMsgId);
}

View File

@@ -34,7 +34,7 @@ namespace Export {
namespace View {
namespace {
constexpr auto kMegabyte = 1024 * 1024;
constexpr auto kMegabyte = int64(1024) * 1024;
[[nodiscard]] PeerId ReadPeerId(
not_null<Main::Session*> session,

View File

@@ -133,10 +133,13 @@ void activateBotCommand(
skipConfirmation = true;
}
}
const auto context = QVariant::fromValue(ClickHandlerContext{
.sessionWindow = sessionController.get(),
});
if (skipConfirmation) {
UrlClickHandler::Open(url);
UrlClickHandler::Open(url, context);
} else {
HiddenUrlClickHandler::Open(url);
HiddenUrlClickHandler::Open(url, context);
}
} break;

View File

@@ -1218,6 +1218,9 @@ HistoryInner::VideoUserpic *HistoryInner::validateVideoUserpic(
return i->second.get();
}
const auto repaint = [=] {
if (hasPendingResizedItems()) {
return;
}
enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
// stop the enumeration if the userpic is below the painted rect
if (userpicTop >= _visibleAreaBottom) {

View File

@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h"
#include "main/main_session.h"
#include "main/main_domain.h" // Core::App().domain().activate().
#include "menu/menu_ttl_validator.h"
#include "apiwrap.h"
#include "history/history.h"
#include "history/view/media/history_view_invoice.h"
@@ -1362,7 +1363,11 @@ void HistoryService::createFromMtp(const MTPDmessage &message) {
void HistoryService::createFromMtp(const MTPDmessageService &message) {
const auto type = message.vaction().type();
if (type == mtpc_messageActionGameScore) {
if (type == mtpc_messageActionSetChatTheme) {
setupChatThemeChange();
} else if (type == mtpc_messageActionSetMessagesTTL) {
setupTTLChange();
} else if (type == mtpc_messageActionGameScore) {
const auto &data = message.vaction().c_messageActionGameScore();
UpdateComponents(HistoryServiceGameScore::Bit());
Get<HistoryServiceGameScore>()->score = data.vscore().v;
@@ -1525,6 +1530,42 @@ void HistoryService::clearDependency() {
}
}
void HistoryService::setupChatThemeChange() {
if (const auto user = history()->peer->asUser()) {
auto link = std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
controller->toggleChooseChatTheme(user);
}
});
UpdateComponents(HistoryServiceChatThemeChange::Bit());
Get<HistoryServiceChatThemeChange>()->link = std::move(link);
} else {
RemoveComponents(HistoryServiceChatThemeChange::Bit());
}
}
void HistoryService::setupTTLChange() {
const auto peer = history()->peer;
auto link = std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
const auto validator = TTLMenu::TTLValidator(
std::make_shared<Window::Show>(controller),
peer);
if (validator.can()) {
validator.showBox();
}
}
});
UpdateComponents(HistoryServiceTTLChange::Bit());
Get<HistoryServiceTTLChange>()->link = std::move(link);
}
void HistoryService::dependencyItemRemoved(HistoryItem *dependency) {
clearDependency();
updateDependentText();

View File

@@ -59,6 +59,16 @@ struct HistoryServiceOngoingCall
rpl::lifetime lifetime;
};
struct HistoryServiceChatThemeChange
: public RuntimeComponent<HistoryServiceChatThemeChange, HistoryItem> {
ClickHandlerPtr link;
};
struct HistoryServiceTTLChange
: public RuntimeComponent<HistoryServiceTTLChange, HistoryItem> {
ClickHandlerPtr link;
};
namespace HistoryView {
class ServiceMessagePainter;
} // namespace HistoryView
@@ -155,6 +165,8 @@ private:
void updateDependentText();
void updateText(PreparedText &&text);
void clearDependency();
void setupChatThemeChange();
void setupTTLChange();
void createFromMtp(const MTPDmessage &message);
void createFromMtp(const MTPDmessageService &message);

View File

@@ -737,8 +737,10 @@ HistoryWidget::HistoryWidget(
if (flags & PeerUpdateFlag::UnavailableReason) {
const auto unavailable = _peer->computeUnavailableReason();
if (!unavailable.isEmpty()) {
controller->showBackFromStack();
controller->show(Ui::MakeInformBox(unavailable));
closeCurrent();
if (const auto primary = Core::App().primaryWindow()) {
primary->show(Ui::MakeInformBox(unavailable));
}
return;
}
}
@@ -1595,6 +1597,12 @@ void HistoryWidget::fieldChanged() {
updateSendButtonType();
if (!HasSendText(_field)) {
_previewState = Data::PreviewState::Allowed;
_fieldIsEmpty = true;
} else if (_fieldIsEmpty) {
_fieldIsEmpty = false;
if (_kbShown) {
toggleKeyboard();
}
}
if (updateCmdStartShown()) {
updateControlsVisibility();
@@ -2932,7 +2940,7 @@ void HistoryWidget::unreadCountUpdated() {
if (_history->chatListUnreadMark()) {
crl::on_main(this, [=, history = _history] {
if (history == _history) {
controller()->showBackFromStack();
closeCurrent();
_cancelRequests.fire({});
}
});
@@ -2942,6 +2950,14 @@ void HistoryWidget::unreadCountUpdated() {
}
}
void HistoryWidget::closeCurrent() {
if (controller()->isPrimary()) {
controller()->showBackFromStack();
} else {
controller()->window().close();
}
}
void HistoryWidget::messagesFailed(const MTP::Error &error, int requestId) {
if (error.type() == qstr("CHANNEL_PRIVATE")
&& _peer->isChannel()
@@ -2951,13 +2967,15 @@ void HistoryWidget::messagesFailed(const MTP::Error &error, int requestId) {
|| error.type() == qstr("CHANNEL_PUBLIC_GROUP_NA")
|| error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
auto was = _peer;
controller()->showBackFromStack();
Ui::ShowMultilineToast({
.parentOverride = Window::Show(controller()).toastParent(),
.text = { (was && was->isMegagroup())
? tr::lng_group_not_accessible(tr::now)
: tr::lng_channel_not_accessible(tr::now) },
});
closeCurrent();
if (const auto primary = Core::App().primaryWindow()) {
Ui::ShowMultilineToast({
.parentOverride = Window::Show(primary).toastParent(),
.text = { (was && was->isMegagroup())
? tr::lng_group_not_accessible(tr::now)
: tr::lng_channel_not_accessible(tr::now) },
});
}
return;
}
@@ -2972,7 +2990,7 @@ void HistoryWidget::messagesFailed(const MTP::Error &error, int requestId) {
_preloadDownRequest = 0;
} else if (_firstLoadRequest == requestId) {
_firstLoadRequest = 0;
controller()->showBackFromStack();
closeCurrent();
} else if (_delayedShowAtRequest == requestId) {
_delayedShowAtRequest = 0;
}

View File

@@ -390,6 +390,7 @@ private:
void handleHistoryChange(not_null<const History*> history);
void showAboutTopPromotion();
void unreadCountUpdated();
void closeCurrent();
[[nodiscard]] int computeMaxFieldHeight() const;
void toggleMuteUnmute();
@@ -742,6 +743,7 @@ private:
bool _inClickable = false;
bool _kbShown = false;
bool _fieldIsEmpty = true;
HistoryItem *_kbReplyTo = nullptr;
object_ptr<Ui::ScrollArea> _kbScroll;
const not_null<BotKeyboard*> _keyboard;

View File

@@ -408,6 +408,7 @@ void ListenWrap::initPlayButton() {
using State = TrackState;
_mediaView->setBytes(_data->bytes);
_document->size = _data->bytes.size();
_document->type = VoiceDocument;
const auto &play = _playPauseSt.playOuter;
@@ -1415,7 +1416,6 @@ void VoiceRecordBar::hideFast() {
hide();
_lock->hide();
_level->hide();
stopRecording(StopType::Cancel);
}
void VoiceRecordBar::stopRecording(StopType type) {
@@ -1542,7 +1542,10 @@ void VoiceRecordBar::hideAnimated() {
return;
}
_lockShowing = false;
visibilityAnimate(false, [=] { hideFast(); });
visibilityAnimate(false, [=] {
hideFast();
stopRecording(StopType::Cancel);
});
}
void VoiceRecordBar::finishAnimating() {
@@ -1676,6 +1679,7 @@ void VoiceRecordBar::showDiscardBox(
auto sure = [=, callback = std::move(callback)](Fn<void()> &&close) {
if (animated == anim::type::instant) {
hideFast();
stopRecording(StopType::Cancel);
} else {
hideAnimated();
}

View File

@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h"
#include "ui/ui_utility.h"
#include "mainwidget.h"
#include "menu/menu_ttl_validator.h"
#include "lang/lang_keys.h"
#include "styles/style_chat.h"
@@ -613,6 +614,12 @@ TextState Service::textState(QPoint point, StateRequest request) const {
if (PeerHasThisCall(peer, call->id).value_or(false)) {
result.link = call->link;
}
} else if (const auto theme = item->Get<HistoryServiceChatThemeChange>()) {
result.link = theme->link;
} else if (const auto ttl = item->Get<HistoryServiceTTLChange>()) {
if (TTLMenu::TTLValidator(nullptr, history()->peer).can()) {
result.link = ttl->link;
}
}
}
} else if (media) {

View File

@@ -12,12 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "lang/lang_keys.h"
#include "ui/text/text_utilities.h"
#include "boxes/sticker_set_box.h"
#include "lottie/lottie_single_player.h"
#include "window/window_session_controller.h"
#include "apiwrap.h"
#include "styles/style_chat.h"
namespace HistoryView {
@@ -36,7 +38,9 @@ StickerToast::StickerToast(
, _destroy(std::move(destroy)) {
}
StickerToast::~StickerToast() = default;
StickerToast::~StickerToast() {
cancelRequest();
}
void StickerToast::showFor(not_null<DocumentData*> document) {
const auto sticker = document->sticker();
@@ -49,11 +53,76 @@ void StickerToast::showFor(not_null<DocumentData*> document) {
return;
}
strong->hideAnimated();
} else if (_setRequestId) {
if (_for == document) {
return;
}
cancelRequest();
}
_for = document;
const auto title = lookupTitle();
if (!title.isEmpty()) {
showWithTitle(title);
} else {
requestSet();
}
}
QString StickerToast::lookupTitle() const {
Expects(_for != nullptr);
const auto sticker = _for->sticker();
if (!sticker) {
return {};
}
const auto id = sticker->set.id;
if (!id) {
return {};
}
const auto &sets = _for->owner().stickers().sets();
const auto i = sets.find(id);
if (i == end(sets)) {
return {};
}
return i->second->title;
}
void StickerToast::requestSet() {
Expects(_for != nullptr);
if (const auto sticker = _for->sticker()) {
const auto api = &_controller->session().api();
_setRequestId = api->request(MTPmessages_GetStickerSet(
Data::InputStickerSet(sticker->set),
MTP_int(0) // hash
)).done([=](const MTPmessages_StickerSet &result) {
_setRequestId = 0;
result.match([&](const MTPDmessages_stickerSet &data) {
data.vset().match([&](const MTPDstickerSet &data) {
const auto owner = &_controller->session().data();
showWithTitle(owner->stickers().getSetTitle(data));
});
}, [&](const MTPDmessages_stickerSetNotModified &) {
LOG(("API Error: Got messages.stickerSetNotModified."));
});
}).fail([=] {
_setRequestId = 0;
}).send();
}
}
void StickerToast::cancelRequest() {
_controller->session().api().request(base::take(_setRequestId)).cancel();
}
void StickerToast::showWithTitle(const QString &title) {
Expects(_for != nullptr);
const auto text = Ui::Text::Bold(
tr::lng_sticker_premium_title(tr::now)
title
).append('\n').append(
tr::lng_sticker_premium_text(tr::now)
);
@@ -98,8 +167,8 @@ void StickerToast::showFor(not_null<DocumentData*> document) {
preview->resize(size, size);
preview->show();
const auto bytes = document->createMediaView()->bytes();
const auto filepath = document->filepath();
const auto bytes = _for->createMediaView()->bytes();
const auto filepath = _for->filepath();
const auto player = preview->lifetime().make_state<Lottie::SinglePlayer>(
Lottie::ReadContent(bytes, filepath),
Lottie::FrameRequest{ QSize(size, size) },
@@ -122,7 +191,7 @@ void StickerToast::showFor(not_null<DocumentData*> document) {
button->setClickedCallback([=, weak = _weak] {
_controller->show(
Box<StickerSetBox>(_controller, document->sticker()->set),
Box<StickerSetBox>(_controller, _for->sticker()->set),
Ui::LayerOption::KeepOther);
if (const auto strong = weak.get()) {
strong->hideAnimated();

View File

@@ -34,6 +34,11 @@ public:
void showFor(not_null<DocumentData*> document);
private:
void requestSet();
void cancelRequest();
void showWithTitle(const QString &title);
[[nodiscard]] QString lookupTitle() const;
const not_null<Window::SessionController*> _controller;
const not_null<QWidget*> _parent;
style::Toast _st;
@@ -41,6 +46,8 @@ private:
DocumentData *_for = nullptr;
Fn<void()> _destroy;
mtpRequestId _setRequestId = 0;
};
} // namespace HistoryView

View File

@@ -513,9 +513,10 @@ void TopBarWidget::paintTopBar(Painter &p) {
const auto peer = history->peer;
const auto &text = peer->topBarNameText();
const auto badgeStyle = Ui::PeerBadgeStyle{
nullptr, // verified
&st::dialogsPremiumIcon, // premium
&st::attentionButtonFg };
&st::dialogsVerifiedIcon,
&st::dialogsPremiumIcon,
&st::attentionButtonFg,
};
const auto badgeWidth = Ui::DrawPeerBadgeGetWidth(
peer,
p,

View File

@@ -177,7 +177,8 @@ void Cover::initViewers(rpl::producer<QString> title) {
BadgeValue(
_peer
) | rpl::start_with_next([=](Badge badge) {
if (badge == Badge::Premium && !_peer->session().premiumPossible()) {
if (badge == Badge::Premium
&& !_peer->session().premiumBadgesShown()) {
badge = Badge::None;
}
setBadge(badge);

View File

@@ -479,14 +479,14 @@ rpl::producer<Badge> BadgeValueFromFlags(Peer peer) {
Flag::Verified | Flag::Scam | Flag::Fake),
Data::PeerPremiumValue(peer)
) | rpl::map([=](base::flags<Flag> value, bool premium) {
return (value & Flag::Verified)
? Badge::Verified
: premium
? Badge::Premium
: (value & Flag::Scam)
return (value & Flag::Scam)
? Badge::Scam
: (value & Flag::Fake)
? Badge::Fake
: (value & Flag::Verified)
? Badge::Verified
: premium
? Badge::Premium
: Badge::None;
});
}

View File

@@ -236,6 +236,10 @@ bool Session::premiumPossible() const {
return premium() || _premiumPossible.current();
}
bool Session::premiumBadgesShown() const {
return supportMode() || premiumPossible();
}
rpl::producer<bool> Session::premiumPossibleValue() const {
using namespace rpl::mappers;

View File

@@ -83,6 +83,7 @@ public:
[[nodiscard]] bool premium() const;
[[nodiscard]] bool premiumPossible() const;
[[nodiscard]] rpl::producer<bool> premiumPossibleValue() const;
[[nodiscard]] bool premiumBadgesShown() const;
[[nodiscard]] uint64 uniqueId() const; // userId() with TestDC shift.
[[nodiscard]] UserId userId() const;

View File

@@ -1314,6 +1314,7 @@ void MainWidget::ui_showPeerHistory(
}
const auto unavailable = peer->computeUnavailableReason();
if (!unavailable.isEmpty()) {
Assert(isPrimary());
if (params.activation != anim::activation::background) {
controller()->show(Ui::MakeInformBox(unavailable));
}

View File

@@ -280,6 +280,7 @@ void MainWindow::setupMain(MsgId singlePeerShowAtMsgId) {
clearWidgets();
_main = std::move(created);
if (const auto peer = singlePeer()) {
updateControlsGeometry();
_main->controller()->showPeerHistory(
peer,
Window::SectionShow::Way::ClearStack,

View File

@@ -501,7 +501,7 @@ void OverlayWidget::moveToScreen(bool inMove) {
DEBUG_LOG(("Viewer Pos: Currently on screen %1, moving to screen %2")
.arg(screenList.indexOf(myScreen))
.arg(screenList.indexOf(activeWindowScreen)));
_widget->setScreen(activeWindowScreen);
window()->setScreen(activeWindowScreen);
DEBUG_LOG(("Viewer Pos: New actual screen: %1")
.arg(screenList.indexOf(_widget->screen())));
}

View File

@@ -475,7 +475,7 @@ void PipPanel::setPositionDefault() {
const auto parentScreen = widgetScreen(_parent);
const auto myScreen = widgetScreen(widget());
if (parentScreen && myScreen && myScreen != parentScreen) {
widget()->setScreen(parentScreen);
widget()->windowHandle()->setScreen(parentScreen);
}
auto position = Position();
position.snapped = RectPart::Top | RectPart::Left;

View File

@@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/local_url_handlers.h" // TryConvertUrlToLocal.
#include "core/file_utilities.h" // File::OpenUrl.
#include "core/core_cloud_password.h" // Core::CloudPasswordState
#include "core/click_handler_types.h"
#include "lang/lang_keys.h"
#include "apiwrap.h"
#include "api/api_cloud_password.h"
@@ -808,6 +809,12 @@ void CheckoutProcess::panelShowBox(object_ptr<Ui::BoxContent> box) {
_panel->showBox(std::move(box));
}
QVariant CheckoutProcess::panelClickHandlerContext() {
return QVariant::fromValue(ClickHandlerContext{
.show = _panel->uiShow(),
});
}
void CheckoutProcess::performInitialSilentValidation() {
const auto &invoice = _form->invoice();
const auto &saved = _form->information();

View File

@@ -147,6 +147,7 @@ private:
Ui::UncheckedCardDetails data,
bool saveInformation) override;
void panelShowBox(object_ptr<Ui::BoxContent> box) override;
QVariant panelClickHandlerContext() override;
QString panelWebviewDataPath() override;

View File

@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/effects/radial_animation.h"
#include "ui/click_handler.h"
#include "lang/lang_keys.h"
#include "webview/webview_embed.h"
#include "webview/webview_interface.h"
@@ -679,6 +680,17 @@ void Panel::requestTermsAcceptance(
st::boxRowPadding.right(),
st::defaultBoxCheckbox.margin.bottom(),
});
row->setAllowTextLines(5);
row->setClickHandlerFilter([=](
const ClickHandlerPtr &link,
Qt::MouseButton button) {
ActivateClickHandler(_widget.get(), link, ClickContext{
.button = button,
.other = _delegate->panelClickHandlerContext(),
});
return false;
});
(*update) = [=] { row->update(); };
struct State {
@@ -830,6 +842,10 @@ void Panel::showCriticalError(const TextWithEntities &text) {
}
}
std::shared_ptr<Show> Panel::uiShow() {
return _widget->uiShow();
}
void Panel::showWebviewError(
const QString &text,
const Webview::Available &information) {

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/object_ptr.h"
namespace Ui {
class Show;
class RpWidget;
class SeparatePanel;
class BoxContent;
@@ -85,6 +86,7 @@ public:
void showBox(object_ptr<Ui::BoxContent> box);
void showToast(const TextWithEntities &text);
void showCriticalError(const TextWithEntities &text);
[[nodiscard]] std::shared_ptr<Show> uiShow();
[[nodiscard]] rpl::lifetime &lifetime();

View File

@@ -53,6 +53,7 @@ public:
Ui::UncheckedCardDetails data,
bool saveInformation) = 0;
virtual void panelShowBox(object_ptr<BoxContent> box) = 0;
virtual QVariant panelClickHandlerContext() = 0;
virtual QString panelWebviewDataPath() = 0;
};

View File

@@ -419,6 +419,10 @@ rpl::producer<> Tray::iconClicks() const {
return _iconClicks.events();
}
bool Tray::hasIcon() const {
return _icon;
}
rpl::lifetime &Tray::lifetime() {
return _lifetime;
}

View File

@@ -33,6 +33,8 @@ public:
[[nodiscard]] rpl::producer<> hideToTrayRequests() const;
[[nodiscard]] rpl::producer<> iconClicks() const;
[[nodiscard]] bool hasIcon() const;
void createIcon();
void destroyIcon();

View File

@@ -27,6 +27,8 @@ public:
[[nodiscard]] rpl::producer<> hideToTrayRequests() const;
[[nodiscard]] rpl::producer<> iconClicks() const;
[[nodiscard]] bool hasIcon() const;
void createIcon();
void destroyIcon();

View File

@@ -413,6 +413,10 @@ rpl::producer<> Tray::iconClicks() const {
return rpl::never<>();
}
bool Tray::hasIcon() const {
return _nativeIcon != nullptr;
}
rpl::lifetime &Tray::lifetime() {
return _lifetime;
}

View File

@@ -12,35 +12,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "core/sandbox.h"
#include "base/platform/win/base_windows_winrt.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QAbstractNativeEventFilter>
namespace Platform {
namespace {
class WindowsIntegration final
: public Integration
, public QAbstractNativeEventFilter {
public:
void init() override;
private:
bool nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) override;
bool processEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result);
};
void WindowsIntegration::init() {
QCoreApplication::instance()->installNativeEventFilter(this);
_taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
}
ITaskbarList3 *WindowsIntegration::taskbarList() const {
return _taskbarList.get();
}
WindowsIntegration &WindowsIntegration::Instance() {
return static_cast<WindowsIntegration&>(Integration::Instance());
}
bool WindowsIntegration::nativeEventFilter(
@@ -64,6 +53,12 @@ bool WindowsIntegration::processEvent(
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
if (msg && msg == _taskbarCreatedMsgId && !_taskbarList) {
_taskbarList = base::WinRT::TryCreateInstance<ITaskbarList3>(
CLSID_TaskbarList,
CLSCTX_ALL);
}
switch (msg) {
case WM_ENDSESSION:
Core::Quit();
@@ -90,8 +85,6 @@ bool WindowsIntegration::processEvent(
return false;
}
} // namespace
std::unique_ptr<Integration> CreateIntegration() {
return std::make_unique<WindowsIntegration>();
}

View File

@@ -7,9 +7,41 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "platform/platform_integration.h"
#include <QAbstractNativeEventFilter>
#include <winrt/base.h>
#include <ShlObj.h>
namespace Platform {
class Integration;
class WindowsIntegration final
: public Integration
, public QAbstractNativeEventFilter {
public:
void init() override;
[[nodiscard]] ITaskbarList3 *taskbarList() const;
[[nodiscard]] static WindowsIntegration &Instance();
private:
bool nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) override;
bool processEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result);
uint32 _taskbarCreatedMsgId = 0;
winrt::com_ptr<ITaskbarList3> _taskbarList;
};
[[nodiscard]] std::unique_ptr<Integration> CreateIntegration();

View File

@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_notifications_manager.h"
#include "platform/win/tray_win.h"
#include "platform/win/windows_dlls.h"
#include "platform/win/integration_win.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "mainwindow.h"
@@ -82,9 +83,7 @@ private:
using namespace Microsoft::WRL;
ComPtr<ITaskbarList3> taskbarList;
bool handleSessionNotification = false;
uint32 kTaskbarCreatedMsgId = 0;
[[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
if (!icon.isNull()) {
@@ -124,15 +123,6 @@ bool EventFilter::mainWindowEvent(
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
if (const auto tbCreatedMsgId = kTaskbarCreatedMsgId) {
if (msg == tbCreatedMsgId) {
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&taskbarList));
if (!SUCCEEDED(hr)) {
taskbarList.Reset();
}
}
}
switch (msg) {
case WM_DESTROY: {
@@ -179,9 +169,6 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
, _taskbarHiderWindow(std::make_unique<QWindow>()) {
qApp->installNativeEventFilter(&_private->filter);
if (!kTaskbarCreatedMsgId) {
kTaskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
}
setupNativeWindowFrame();
using namespace rpl::mappers;
@@ -356,7 +343,9 @@ void MainWindow::updateIconCounters() {
QIcon iconSmall, iconBig;
iconSmall.addPixmap(iconSmallPixmap16);
iconSmall.addPixmap(iconSmallPixmap32);
const auto bigCounter = taskbarList.Get() ? 0 : counter;
const auto integration = &Platform::WindowsIntegration::Instance();
const auto taskbarList = integration->taskbarList();
const auto bigCounter = taskbarList ? 0 : counter;
iconBig.addPixmap(Tray::IconWithCounter(
Tray::CounterLayerArgs(32, bigCounter, muted),
false,
@@ -528,9 +517,6 @@ void MainWindow::destroyCachedIcons() {
MainWindow::~MainWindow() {
WTSUnRegisterSessionNotification(_hWnd);
_private->viewSettings.Reset();
if (taskbarList) {
taskbarList.Reset();
}
destroyCachedIcons();
}

View File

@@ -440,6 +440,7 @@ private:
const QString &subtitle,
const QString &msg,
DisplayOptions options);
void tryHide(const ToastNotification &notification);
[[nodiscard]] std::wstring ensureSendButtonIcon();
Window::Notifications::CachedUserpics _cachedUserpics;
@@ -485,7 +486,7 @@ void Manager::Private::clearAll() {
for (const auto &[key, notifications] : base::take(_notifications)) {
for (const auto &[msgId, notification] : notifications) {
_notifier.Hide(notification);
tryHide(notification);
}
}
}
@@ -511,7 +512,7 @@ void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
if (i->second.empty()) {
_notifications.erase(i);
}
_notifier.Hide(taken);
tryHide(taken);
}
void Manager::Private::clearFromHistory(not_null<History*> history) {
@@ -528,7 +529,7 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
_notifications.erase(i);
for (const auto &[msgId, notification] : temp) {
_notifier.Hide(notification);
tryHide(notification);
}
}
}
@@ -548,7 +549,7 @@ void Manager::Private::clearFromSession(not_null<Main::Session*> session) {
_notifications.erase(i);
for (const auto &[msgId, notification] : temp) {
_notifier.Hide(notification);
tryHide(notification);
}
}
}
@@ -807,7 +808,7 @@ bool Manager::Private::showNotificationInTryCatch(
if (j != i->second.end()) {
const auto existing = j->second;
i->second.erase(j);
_notifier.Hide(existing);
tryHide(existing);
i = _notifications.find(key);
}
}
@@ -827,7 +828,14 @@ bool Manager::Private::showNotificationInTryCatch(
return true;
}
Manager::Manager(Window::Notifications::System *system) : NativeManager(system)
void Manager::Private::tryHide(const ToastNotification &notification) {
base::WinRT::Try([&] {
_notifier.Hide(notification);
});
}
Manager::Manager(Window::Notifications::System *system)
: NativeManager(system)
, _private(std::make_unique<Private>(this, Private::Type::Rounded)) {
}

View File

@@ -231,6 +231,10 @@ rpl::producer<> Tray::iconClicks() const {
return _iconClicks.events();
}
bool Tray::hasIcon() const {
return _icon;
}
rpl::lifetime &Tray::lifetime() {
return _lifetime;
}

View File

@@ -32,6 +32,8 @@ public:
[[nodiscard]] rpl::producer<> hideToTrayRequests() const;
[[nodiscard]] rpl::producer<> iconClicks() const;
[[nodiscard]] bool hasIcon() const;
void createIcon();
void destroyIcon();

View File

@@ -402,7 +402,7 @@ void GroupMembersWidget::setItemFlags(
const auto rankIt = megagroup->mgInfo->admins.find(peerToUser(user->id));
const auto adminCanEdit = isAdmin && adminIt->second.canEdit;
const auto rank = (amCreator || isCreator)
? (megagroup->mgInfo->creatorRank.isEmpty()
? (!megagroup->mgInfo->creatorRank.isEmpty()
? megagroup->mgInfo->creatorRank
: tr::lng_owner_badge(tr::now))
: (amAdmin || isAdmin)

View File

@@ -29,7 +29,7 @@ namespace {
// max 512kb uploaded at the same time in each session
constexpr auto kMaxUploadFileParallelSize = MTP::kUploadSessionsCount * 512 * 1024;
constexpr auto kDocumentMaxPartsCount = 8000;
constexpr auto kDocumentMaxPartsCountDefault = 4000;
// 32kb for tiny document ( < 1mb )
constexpr auto kDocumentUploadPartSize0 = 32 * 1024;
@@ -120,9 +120,7 @@ void Uploader::File::setDocSize(int64 size) {
if (docSize > limit1 || !setPartSize(kDocumentUploadPartSize1)) {
if (!setPartSize(kDocumentUploadPartSize2)) {
if (!setPartSize(kDocumentUploadPartSize3)) {
if (!setPartSize(kDocumentUploadPartSize4)) {
LOG(("Upload Error: bad doc size: %1").arg(docSize));
}
setPartSize(kDocumentUploadPartSize4);
}
}
}
@@ -133,7 +131,7 @@ bool Uploader::File::setPartSize(uint32 partSize) {
docPartSize = partSize;
docPartsCount = (docSize / docPartSize)
+ ((docSize % docPartSize) ? 1 : 0);
return (docPartsCount <= kDocumentMaxPartsCount);
return (docPartsCount <= kDocumentMaxPartsCountDefault);
}
uint64 Uploader::File::id() const {

View File

@@ -165,8 +165,8 @@ MimeDataState ComputeMimeDataState(const QMimeData *data) {
const auto filesize = info.size();
if (filesize > kFileSizePremiumLimit) {
return MimeDataState::None;
} else if (filesize > kFileSizeLimit) {
return MimeDataState::PremiumFile;
//} else if (filesize > kFileSizeLimit) {
// return MimeDataState::PremiumFile;
} else if (allAreSmallImages) {
if (filesize > Images::kReadBytesLimit) {
allAreSmallImages = false;

View File

@@ -23,7 +23,7 @@ enum class MimeDataState {
None,
Files,
PhotoFiles,
PremiumFile,
//PremiumFile,
Image,
};

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "platform/platform_specific.h"
#include <QtWidgets/QApplication>
@@ -19,17 +20,20 @@ Tray::Tray() {
void Tray::create() {
rebuildMenu();
if (Core::App().settings().workMode() != Settings::WorkMode::WindowOnly) {
using WorkMode = Settings::WorkMode;
if (Platform::TrayIconSupported()
&& (Core::App().settings().workMode() != WorkMode::WindowOnly)) {
_tray.createIcon();
}
Core::App().settings().workModeValue(
) | rpl::combine_previous(
) | rpl::start_with_next([=](
Settings::WorkMode previous,
Settings::WorkMode state) {
const auto wasHasIcon = (previous != Settings::WorkMode::WindowOnly);
const auto nowHasIcon = (state != Settings::WorkMode::WindowOnly);
) | rpl::start_with_next([=](WorkMode previous, WorkMode state) {
if (!Platform::TrayIconSupported()) {
return;
}
const auto wasHasIcon = (previous != WorkMode::WindowOnly);
const auto nowHasIcon = (state != WorkMode::WindowOnly);
if (wasHasIcon != nowHasIcon) {
if (nowHasIcon) {
_tray.createIcon();
@@ -177,4 +181,8 @@ void Tray::toggleSoundNotifications() {
}
}
bool Tray::has() const {
return _tray.hasIcon();
}
} // namespace Core

View File

@@ -23,6 +23,8 @@ public:
[[nodiscard]] rpl::producer<> showFromTrayRequests() const;
[[nodiscard]] rpl::producer<> hideToTrayRequests() const;
[[nodiscard]] bool has() const;
private:
void rebuildMenu();
void toggleSoundNotifications();

View File

@@ -110,25 +110,7 @@ int DrawPeerBadgeGetWidth(
int nameWidth,
int outerWidth,
const PeerBadgeStyle &st) {
if (peer->isVerified() && st.verified) {
const auto iconw = st.verified->width();
st.verified->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
} else if (peer->isPremium()
&& st.premium
&& peer->session().premiumPossible()) {
const auto iconw = st.premium->width();
st.premium->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
} else if ((peer->isScam() || peer->isFake()) && st.scam) {
if ((peer->isScam() || peer->isFake()) && st.scam) {
const auto phrase = peer->isScam()
? tr::lng_scam_badge(tr::now)
: tr::lng_fake_badge(tr::now);
@@ -149,6 +131,24 @@ int DrawPeerBadgeGetWidth(
height);
DrawScamFakeBadge(p, rect, outerWidth, *st.scam, phrase, phraseWidth);
return st::dialogsScamSkip + width;
} else if (peer->isVerified() && st.verified) {
const auto iconw = st.verified->width();
st.verified->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
} else if (peer->isPremium()
&& st.premium
&& peer->session().premiumBadgesShown()) {
const auto iconw = st.premium->width();
st.premium->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
}
return 0;
}

View File

@@ -903,7 +903,7 @@ Core::WindowPosition MainWindow::SecondaryInitPosition() {
}
bool MainWindow::minimizeToTray() {
if (Core::Quitting()/* || !hasTrayIcon()*/) {
if (Core::Quitting() || !Core::App().tray().has()) {
return false;
}

View File

@@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QBuffer>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QFileSystemWatcher>
namespace Window {
namespace Theme {
@@ -540,6 +541,8 @@ ChatBackground::ChatBackground() : _adjustableColors({
st::historyScrollBarBgOver }) {
}
ChatBackground::~ChatBackground() = default;
void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) {
_themeImage = PostprocessBackgroundImage(
std::move(themeImage),
@@ -566,6 +569,7 @@ void ChatBackground::start() {
_updates.events(
) | rpl::start_with_next([=](const BackgroundUpdate &update) {
refreshThemeWatcher();
if (update.paletteChanged()) {
style::NotifyPaletteChanged();
}
@@ -584,6 +588,25 @@ void ChatBackground::start() {
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
}
void ChatBackground::refreshThemeWatcher() {
const auto path = _themeObject.pathAbsolute;
if (path.isEmpty()
|| !QFileInfo(path).isNativePath()
|| editingTheme()) {
_themeWatcher = nullptr;
} else if (!_themeWatcher || !_themeWatcher->files().contains(path)) {
_themeWatcher = std::make_unique<QFileSystemWatcher>(
QStringList(path));
QObject::connect(
_themeWatcher.get(),
&QFileSystemWatcher::fileChanged,
[](const QString &path) {
Apply(path);
KeepApplied();
});
}
}
void ChatBackground::checkUploadWallPaper() {
if (!_session) {
_wallPaperUploadLifetime = rpl::lifetime();
@@ -807,6 +830,7 @@ std::optional<Data::CloudTheme> ChatBackground::editingTheme() const {
void ChatBackground::setEditingTheme(const Data::CloudTheme &editing) {
_editingTheme = editing;
refreshThemeWatcher();
}
void ChatBackground::clearEditingTheme(ClearEditing clear) {
@@ -822,6 +846,7 @@ void ChatBackground::clearEditingTheme(ClearEditing clear) {
reapplyWithNightMode(std::nullopt, _nightMode);
KeepApplied();
}
refreshThemeWatcher();
}
void ChatBackground::adjustPaletteUsingBackground(const QImage &image) {

View File

@@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_cloud_themes.h"
#include "ui/style/style_core_palette.h"
class QFileSystemWatcher;
namespace style {
struct colorizer;
} // namespace style
@@ -154,6 +156,7 @@ enum class ClearEditing {
class ChatBackground final {
public:
ChatBackground();
~ChatBackground();
[[nodiscard]] rpl::producer<BackgroundUpdate> updates() const {
return _updates.events();
@@ -240,6 +243,7 @@ private:
[[nodiscard]] bool isNonDefaultBackground();
void checkUploadWallPaper();
[[nodiscard]] QImage postprocessBackgroundImage(QImage image);
void refreshThemeWatcher();
friend bool IsNightMode();
friend void SetNightModeValue(bool nightMode);
@@ -276,6 +280,7 @@ private:
QImage _themeImage;
bool _themeTile = false;
std::optional<Data::CloudTheme> _editingTheme;
std::unique_ptr<QFileSystemWatcher> _themeWatcher;
Data::WallPaper _paperForRevert
= Data::details::UninitializedWallPaper();

View File

@@ -1201,7 +1201,9 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
navigation
](not_null<PeerData*> peer) mutable {
const auto content = navigation->parentController()->content();
if (peer->isSelf()) {
if (peer->isSelf()
&& !draft.ids.empty()
&& draft.ids.front().peer != peer->id) {
const auto history = peer->owner().history(peer);
auto resolved = history->resolveForwardDraft(draft);
if (!resolved.items.empty()) {

View File

@@ -1220,6 +1220,11 @@ void SessionController::closeThirdSection() {
}
}
bool SessionController::canShowSeparateWindow(
not_null<PeerData*> peer) const {
return peer->computeUnavailableReason().isEmpty();
}
void SessionController::showPeer(not_null<PeerData*> peer, MsgId msgId) {
const auto currentPeer = activeChatCurrent().peer();
if (peer && peer->isChannel() && currentPeer != peer) {
@@ -1926,8 +1931,8 @@ Show::Show(not_null<SessionNavigation*> navigation)
: Show(&navigation->parentController()->window()) {
}
Show::Show(not_null<Controller*> window)
: _window(base::make_weak(window.get())) {
Show::Show(Controller *window)
: _window(base::make_weak(window)) {
}
Show::~Show() = default;

View File

@@ -380,6 +380,7 @@ public:
void resizeForThirdSection();
void closeThirdSection();
[[nodiscard]] bool canShowSeparateWindow(not_null<PeerData*> peer) const;
void showPeer(not_null<PeerData*> peer, MsgId msgId = ShowAtUnreadMsgId);
void startOrJoinGroupCall(
@@ -609,7 +610,7 @@ void ActivateWindow(not_null<SessionController*> controller);
class Show : public Ui::Show {
public:
explicit Show(not_null<SessionNavigation*> navigation);
explicit Show(not_null<Controller*> window);
explicit Show(Controller *window);
~Show();
void showBox(
object_ptr<Ui::BoxContent> content,

View File

@@ -422,15 +422,13 @@ RUN git init ffmpeg \
&& rm -rf ffmpeg
FROM builder AS pipewire
RUN git clone -b 0.3.42 --depth=1 $GIT/PipeWire/pipewire.git \
RUN git clone -b 0.3.33 --depth=1 $GIT/PipeWire/pipewire.git \
&& cd pipewire \
&& meson build \
--buildtype=release \
-Dtests=disabled \
-Dexamples=disabled \
-Dpipewire-v4l2=disabled \
-Dspa-plugins=disabled \
-Dsession-managers=[] \
&& meson compile -C build \
&& DESTDIR="$LibrariesPath/pipewire-cache" meson install -C build \
&& cd .. \
@@ -439,15 +437,13 @@ RUN git clone -b 0.3.42 --depth=1 $GIT/PipeWire/pipewire.git \
FROM builder AS openal
COPY --from=pipewire ${LibrariesPath}/pipewire-cache /
RUN git clone -b 1.22.0 --depth=1 $GIT/kcat/openal-soft.git \
RUN git clone -b 1.22.1 --depth=1 $GIT/kcat/openal-soft.git \
&& cd openal-soft \
&& curl -sSL https://github.com/kcat/openal-soft/commit/2ea5bb91686ee1a7350672bf15b7b63649dbf111.patch \
| git apply \
&& sed -i 's@PW_CHECK_VERSION(major, minor, revision)@!PW_CHECK_VERSION(major, minor, revision + 1)@' alc/backends/pipewire.cpp \
&& CFLAGS="$HFLAGS" CXXFLAGS="$HFLAGS" cmake -GNinja -B build . \
-DCMAKE_BUILD_TYPE=Release \
-DLIBTYPE:STRING=STATIC \
-DALSOFT_EXAMPLES=OFF \
-DALSOFT_TESTS=OFF \
-DALSOFT_UTILS=OFF \
-DALSOFT_INSTALL_CONFIG=OFF \
&& cmake --build build --parallel \

View File

@@ -399,7 +399,7 @@ if customRunCommand:
stage('patches', """
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout e1383b0e8f
git checkout 38af8ef4c6
""")
stage('depot_tools', """
@@ -976,7 +976,7 @@ release:
mac:
git clone https://github.com/kcat/openal-soft.git
cd openal-soft
git checkout af8e756d
git checkout 1.22.1
CFLAGS=$UNGUARDED CPPFLAGS=$UNGUARDED cmake -B build . \\
-D CMAKE_INSTALL_PREFIX:PATH=$USED_PREFIX \\
-D ALSOFT_EXAMPLES=OFF \\

View File

@@ -1,7 +1,7 @@
AppVersion 3007006
AppVersionStrMajor 3.7
AppVersionStrSmall 3.7.6
AppVersionStr 3.7.6
BetaChannel 1
AppVersion 4000002
AppVersionStrMajor 4.0
AppVersionStrSmall 4.0.2
AppVersionStr 4.0.2
BetaChannel 0
AlphaVersion 0
AppVersionOriginal 3.7.6.beta
AppVersionOriginal 4.0.2

View File

@@ -1,3 +1,31 @@
4.0.2 (24.06.22)
- Fix window title on Windows 7. (again)
- Fix file chooser and global menu on macOS.
- Crash fix and OpenAL check for PipeWire fix on Linux.
4.0.1 (23.06.22)
- Fix window title on Windows 7.
- Bug fixes and other minor improvements.
4.0 (22.06.22)
- Premium: Send media and files each up to 4 GB in size.
- Premium: Download media and files at the fastest possible speed, with no limits.
- Premium: Double most of the limits in the app.
- Premium: Get a new button next to any voice message to generate a transcript of its audio.
- Premium: React with even more emoji, including :clown: and :heart_eyes:.
- Premium: Send unique stickers with additional effects, updated monthly.
- Premium: Set a default chat folder or enable tools to auto-archive and hide new chats.
- Premium: Subscribers have a badge next to their name, showing they help support Telegram.
- Premium: Show off your profile video that will be animated for everyone in chats and the chat list.
- Premium: Sponsored Messages that are sometimes shown in public channels will no longer appear.
- Enable join requests for your public groups no invite links required.
- Users who open the group will see an Apply to Join Group button.
- Once approved by an admin, users will be able to participate in the chat.
- Bots that are integrated into the attachment menu can be programmed to work in groups and channels.
3.7.6 beta (16.06.22)
- Settings > Advanced > Experimental adds an option to open chats in separate windows.

2
cmake

Submodule cmake updated: 06237779c2...d8442d4d96

View File

@@ -237,7 +237,7 @@ parts:
openal:
source: https://github.com/kcat/openal-soft.git
source-depth: 1
source-tag: 1.22.0
source-tag: 1.22.1
plugin: cmake
build-packages:
- libasound2-dev
@@ -254,9 +254,11 @@ parts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_INSTALL_PREFIX=/usr
- -DALSOFT_EXAMPLES=OFF
- -DALSOFT_TESTS=OFF
- -DALSOFT_UTILS=OFF
- -DALSOFT_INSTALL_CONFIG=OFF
override-pull: |
craftctl default
sed -i 's@PW_CHECK_VERSION(major, minor, revision)@!PW_CHECK_VERSION(major, minor, revision + 1)@' alc/backends/pipewire.cpp
prime:
- -./usr/include
- -./usr/lib/$CRAFT_ARCH_TRIPLET/cmake