Compare commits

..

51 Commits

Author SHA1 Message Date
John Preston
21b10cebe0 Beta version 3.1.3.
- Fix illegal instruction crash in opus encoder.
2021-09-27 10:28:29 +04:00
John Preston
50435f7783 Allow creating links with Ip addresses. 2021-09-27 10:28:29 +04:00
Ilya Fedin
1b789de4f4 Cherry-pick a opus fix for detecting CPU instructions on Windows 2021-09-27 08:50:51 +04:00
John Preston
a50310f0c1 Beta version 3.1.2 (Windows only).
- Control video in fullscreen mode using arrows and numbers.
- Open locations in browser if default Bing Maps is not installed.
- Reconnect without timeout when network availability changes.
- Crash fixes.
2021-09-26 17:24:09 +04:00
John Preston
eb02a7861a Add modern C++/WinRT headers path to Telegram project. 2021-09-26 17:20:22 +04:00
John Preston
8759ca4577 Rewrite bingmaps check to C++/WinRT. 2021-09-26 17:17:57 +04:00
Hermesis
d5c6d9a231 Open map in browser if default "bingmaps:" handler is not found 2021-09-26 17:16:38 +04:00
John Preston
63f179e93e Add Windows network reachability backend. 2021-09-26 14:31:54 +04:00
Hermesis
cfcc1b1ce7 Control video in fullscreen mode using arrows and numbers 2021-09-26 14:07:02 +04:00
John Preston
da1945d0ca Add some more information for an assertion violation. 2021-09-25 22:49:51 +04:00
John Preston
12252ef1aa One more attempt of OpenGL context loss crash fix. 2021-09-25 22:39:49 +04:00
John Preston
1eef94e8d9 Fix possible crash in delayed typing updates. 2021-09-25 22:39:11 +04:00
Ilya Fedin
0984e631fa Use opus built with cmake on Windows 2021-09-25 15:35:32 +04:00
John Preston
ec064a904d Version 3.1.1.
- Crash fixes.
2021-09-24 08:47:02 +04:00
John Preston
b47692e920 Update patches revision. 2021-09-24 08:46:52 +04:00
John Preston
132f127f3f Add some assertions to debug a crash. 2021-09-24 08:44:22 +04:00
John Preston
5c44b851fe One more attempt to fix crashes on context loss. 2021-09-23 17:39:39 +04:00
John Preston
2f5bed2899 Skip "contact joined" toast if disabled in Settings.
The chats still appear (they are server-side), but skip the toast.
2021-09-23 17:37:29 +04:00
John Preston
cf76933352 Fix saving tray "Toggle notifications" on relaunch.
Fixes https://bugs.telegram.org/c/9509
2021-09-22 14:03:41 +04:00
John Preston
eaa4c5e5b1 Fix caching by making a fake dir ThirdParty/gyp. 2021-09-22 12:42:59 +04:00
John Preston
a4b5b6e370 Fix crash in lottie destructor.
Fixes #16985.
2021-09-21 21:29:59 +04:00
John Preston
c1be1ca4ae Add ./build/prepare/linux.sh which builds docker. 2021-09-21 18:11:24 +04:00
Ilya Fedin
b2df781b76 Fix icon for Quit Telegram taskbar item in snap 2021-09-20 15:09:42 +03:00
Ilya Fedin
38815c1ca8 Backport fonts hook from snapcraft extensions 2021-09-20 11:40:03 +03:00
John Preston
2ec92f541c Version 3.1: Fix building Qt for Release. 2021-09-19 18:42:29 +03:00
John Preston
7ce8b42216 Version 3.1.
- Some animated emoji now have extra effects.
- Send 🎆 🎉, 🎈, :like:, 💩 or ❤️
to any private chat, then click on the animated emoji
to launch the effect.
- If your chat partner also has the chat open,
you will both see the effects.
- See the "Watching" status
when your chat partner is enjoying emoji effects with you.
- More interactive emoji coming soon.
- Right click one of your outgoing messages in small groups
to see who recently viewed it.
- To protect privacy, read receipts are only stored for 7 days
after the message was sent.
- Record video and audio from live broadcasts in your group or channel.
- Admins can start recording from the '...' menu.
- Choose between recording in portrait or landscape orientation.
- Finished recordings are sent to the admin's Saved Messages
and can be easily shared.
2021-09-19 18:21:31 +03:00
John Preston
17511749de Hold only last 5 custom themes in memory. 2021-09-19 18:15:46 +03:00
John Preston
4f6c7657bf Fix comments root pinned view disappearing. 2021-09-19 17:48:00 +03:00
John Preston
54085c70a4 Select light / dark custom theme based on dialogsBg value. 2021-09-19 17:39:29 +03:00
John Preston
e6c4b96c54 Just close SendFilesBox on last item remove.
Fixes https://bugs.telegram.org/c/2298
2021-09-19 17:36:31 +03:00
John Preston
b75221737a Make history-down button scale better. 2021-09-19 17:29:42 +03:00
John Preston
c336d725ea Fix media controls hiding workaround. 2021-09-19 16:55:55 +03:00
John Preston
d0fcc40d25 Don't play interactions in an inactive window. 2021-09-19 15:12:37 +03:00
John Preston
422bfd973b Don't play interactions without large emoji. 2021-09-19 15:12:20 +03:00
John Preston
d4db679ce8 Base custom chat themes on a separate light theme. 2021-09-19 14:43:09 +03:00
John Preston
2c7d8858c0 Base custom chat themes on a separate dark theme. 2021-09-19 14:43:09 +03:00
John Preston
155bbed3f4 Show correct video recording status. 2021-09-19 14:42:56 +03:00
John Preston
b1517c68fb Colorize outgoing selected state in light custom themes. 2021-09-19 14:42:51 +03:00
John Preston
d206ba7e1d Always underline links if color is the same as text. 2021-09-19 14:42:46 +03:00
John Preston
af100c2d13 Fix poll answer check in custom chat themes. 2021-09-19 14:40:43 +03:00
John Preston
1f25777929 Update watching emoji interaction phrase. 2021-09-19 14:40:43 +03:00
John Preston
a566405598 Show correct emoticon in interaction-seen status. 2021-09-19 14:40:43 +03:00
John Preston
b02967a44e Update tg_angle in prepare script. 2021-09-19 14:40:43 +03:00
John Preston
e0135e509d Allow exporting test chat themes. 2021-09-19 14:40:43 +03:00
John Preston
8274fddcbc Revert build-in Tinted theme.
Fixes #16969.
2021-09-19 14:40:43 +03:00
John Preston
82c45871c7 Fix build with Xcode. 2021-09-19 14:40:43 +03:00
23rd
2164caaab7 Fixed formatting of comments count. 2021-09-19 14:40:07 +03:00
Ilya Fedin
f4b162cbaf Update submodules 2021-09-19 13:22:38 +03:00
Ilya Fedin
4bc4584868 Build glibmm with LTO
In combination with https://github.com/desktop-app/cmake_helpers/pull/126 gets rid of unused glib symbols
2021-09-19 13:22:38 +03:00
John Preston
890a126423 Use shared provider for interaction animations. 2021-09-18 20:29:56 +03:00
John Preston
42cc24e167 Cache interactions in four cache keys. 2021-09-17 19:23:52 +03:00
67 changed files with 678 additions and 184 deletions

View File

@@ -259,12 +259,17 @@ jobs:
- name: Opus.
if: steps.cache-opus.outputs.cache-hit != 'true'
run: |
git clone %GIT%/telegramdesktop/opus.git
git clone -b v1.3.1 %GIT%/xiph/opus.git
cd opus
git checkout tdesktop
cd win32\VS2015
msbuild -m opus.sln /property:Configuration=Debug /property:Platform="Win32"
msbuild -m opus.sln /property:Configuration=Release /property:Platform="Win32"
git cherry-pick 927de8453c
cmake -B out . ^
-A Win32 ^
-DCMAKE_INSTALL_PREFIX=%LibrariesPath%/local/opus ^
-DCMAKE_C_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" ^
-DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG"
cmake --build out --config Debug
cmake --build out --config Release
cmake --install out --config Release
- name: Rnnoise.
run: |

View File

@@ -43,6 +43,8 @@ include(cmake/generate_appdata_changelog.cmake)
if (WIN32)
include(cmake/generate_midl.cmake)
generate_midl(Telegram ${src_loc}/platform/win/windows_quiethours.idl)
nuget_add_winrt(Telegram)
endif()
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1618,7 +1618,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_user_action_upload_file" = "{user} is sending a file";
"lng_send_action_choose_sticker" = "choosing a sticker";
"lng_user_action_choose_sticker" = "{user} is choosing a sticker";
"lng_user_action_watching_animations" = "watching {emoji} animations";
"lng_user_action_watching_animations" = "watching {emoji}";
"lng_unread_bar#one" = "{count} unread message";
"lng_unread_bar#other" = "{count} unread messages";
"lng_unread_bar_some" = "Unread messages";
@@ -2239,7 +2239,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_recording_start_checkbox" = "Also record video";
"lng_group_call_recording_start_audio_subtitle" = "This chat will be recorded into an audio file";
"lng_group_call_recording_start_video_subtitle" = "Choose video orientation";
"lng_group_call_is_recorded" = "Voice chat is being recorded.";
"lng_group_call_is_recorded" = "The audio stream is being recorded.";
"lng_group_call_is_recorded_video" = "The video stream is being recorded.";
"lng_group_call_is_recorded_channel" = "Live stream is being recorded.";
"lng_group_call_can_speak_here" = "You can now speak.";
"lng_group_call_can_speak" = "You can now speak in {chat}.";

Binary file not shown.

View File

@@ -60,6 +60,8 @@
<file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file>
<file alias="night.tdesktop-theme">../../night.tdesktop-theme</file>
<file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file>
<file alias="day-custom-base.tdesktop-theme">../../day-custom-base.tdesktop-theme</file>
<file alias="night-custom-base.tdesktop-theme">../../night-custom-base.tdesktop-theme</file>
<file alias="icons/calls/hands.lottie">../../icons/calls/hands.lottie</file>
<file alias="icons/calls/voice.lottie">../../icons/calls/voice.lottie</file>
<file alias="recording/info_audio.svg">../../art/recording/recording_info_audio.svg</file>

View File

@@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="3.0.5.0" />
Version="3.1.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 3,0,5,0
PRODUCTVERSION 3,0,5,0
FILEVERSION 3,1,3,0
PRODUCTVERSION 3,1,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", "3.0.5.0"
VALUE "FileVersion", "3.1.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.0.5.0"
VALUE "ProductVersion", "3.1.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,0,5,0
PRODUCTVERSION 3,0,5,0
FILEVERSION 3,1,3,0
PRODUCTVERSION 3,1,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", "3.0.5.0"
VALUE "FileVersion", "3.1.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.0.5.0"
VALUE "ProductVersion", "3.1.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -549,9 +549,6 @@ void SendFilesBox::pushBlock(int from, int till) {
block.takeWidget(),
QMargins(0, _inner->count() ? st::sendMediaRowSkip : 0, 0, 0));
const auto preventDelete =
widget->lifetime().make_state<rpl::event_stream<int>>();
block.itemDeleteRequest(
) | rpl::filter([=] {
return !_removingIndex;
@@ -562,9 +559,9 @@ void SendFilesBox::pushBlock(int from, int till) {
if (index < 0 || index >= _list.files.size()) {
return;
}
// Prevent item delete if it is the only one.
// Just close the box if it is the only one.
if (_list.files.size() == 1) {
preventDelete->fire_copy(0);
closeBox();
return;
}
_list.files.erase(_list.files.begin() + index);
@@ -572,9 +569,7 @@ void SendFilesBox::pushBlock(int from, int till) {
});
}, widget->lifetime());
rpl::merge(
block.itemReplaceRequest(),
preventDelete->events()
block.itemReplaceRequest(
) | rpl::start_with_next([=](int index) {
const auto replace = [=](Ui::PreparedList list) {
if (list.files.empty()) {

View File

@@ -1000,6 +1000,8 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
_recordingMark->setClickedCallback([=] {
showToast({ (livestream
? tr::lng_group_call_is_recorded_channel
: real->recordVideo()
? tr::lng_group_call_is_recorded_video
: tr::lng_group_call_is_recorded)(tr::now) });
});
const auto animate = [=] {

View File

@@ -117,7 +117,8 @@ void EmojiInteractions::startOutgoing(
if (!IsServerMsgId(item->id) || !item->history()->peer->isUser()) {
return;
}
const auto emoji = chooseInteractionEmoji(item);
const auto emoticon = item->originalText().text;
const auto emoji = chooseInteractionEmoji(emoticon);
if (!emoji) {
return;
}
@@ -145,6 +146,7 @@ void EmojiInteractions::startOutgoing(
media->checkStickerLarge();
const auto now = crl::now();
animations.push_back({
.emoticon = emoticon,
.emoji = emoji,
.document = document,
.media = media,
@@ -195,6 +197,7 @@ void EmojiInteractions::startIncoming(
const auto media = document->createMediaView();
media->checkStickerLarge();
animations.push_back({
.emoticon = emoticon,
.emoji = emoji,
.document = document,
.media = media,
@@ -219,7 +222,7 @@ void EmojiInteractions::seenOutgoing(
if (const auto j = i->second.find(emoji); j != end(i->second)) {
const auto last = j->second.lastDoneReceivedAt;
if (!last || last + kAcceptSeenSinceRequest > crl::now()) {
_seen.fire({ peer, emoji });
_seen.fire({ peer, emoticon });
}
}
}
@@ -263,7 +266,7 @@ auto EmojiInteractions::checkAnimations(
} else if (!lastStartedAt || lastStartedAt + kMinDelay <= now) {
animation.startedAt = now;
_playRequests.fire({
animation.emoji->text(),
animation.emoticon,
item,
animation.media,
animation.scheduledAt,
@@ -316,7 +319,7 @@ void EmojiInteractions::sendAccumulatedOutgoing(
peer->input,
MTPint(), // top_msg_id
MTP_sendMessageEmojiInteraction(
MTP_string(emoji->text()),
MTP_string(from->emoticon),
MTP_int(item->id),
MTP_dataJSON(MTP_bytes(ToJson(bunch))))
)).done([=](const MTPBool &result, mtpRequestId requestId) {

View File

@@ -28,7 +28,7 @@ class Element;
namespace ChatHelpers {
struct EmojiInteractionPlayRequest {
QString emoji;
QString emoticon;
not_null<HistoryItem*> item;
std::shared_ptr<Data::DocumentMedia> media;
crl::time shouldHaveStartedAt = 0;
@@ -45,7 +45,7 @@ struct EmojiInteractionsBunch {
struct EmojiInteractionSeen {
not_null<PeerData*> peer;
not_null<EmojiPtr> emoji;
QString emoticon;
};
class EmojiInteractions final {
@@ -78,6 +78,7 @@ public:
private:
struct Animation {
QString emoticon;
not_null<EmojiPtr> emoji;
not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> media;

View File

@@ -60,12 +60,11 @@ auto LottieFromDocument(
Method &&method,
not_null<Data::DocumentMedia*> media,
uint8 keyShift,
QSize box,
int cacheAreaLimit) {
QSize box) {
const auto document = media->owner();
const auto data = media->bytes();
const auto filepath = document->filepath();
if (box.width() * box.height() > cacheAreaLimit) {
if (box.width() * box.height() > kDontCacheLottieAfterArea) {
// Don't use frame caching for large stickers.
return method(
Lottie::ReadContent(data, filepath),
@@ -114,12 +113,9 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
replacements,
std::move(renderer));
};
const auto limit = (sizeTag == StickerLottieSize::EmojiInteraction)
? (3 * kDontCacheLottieAfterArea)
: kDontCacheLottieAfterArea;
const auto tag = replacements ? replacements->tag : uint8(0);
const auto keyShift = ((tag << 4) & 0xF0) | (uint8(sizeTag) & 0x0F);
return LottieFromDocument(method, media, uint8(keyShift), box, limit);
return LottieFromDocument(method, media, uint8(keyShift), box);
}
not_null<Lottie::Animation*> LottieAnimationFromDocument(
@@ -130,8 +126,7 @@ not_null<Lottie::Animation*> LottieAnimationFromDocument(
const auto method = [&](auto &&...args) {
return player->append(std::forward<decltype(args)>(args)...);
};
const auto limit = kDontCacheLottieAfterArea;
return LottieFromDocument(method, media, uint8(sizeTag), box, limit);
return LottieFromDocument(method, media, uint8(sizeTag), box);
}
bool HasLottieThumbnail(

View File

@@ -45,6 +45,9 @@ enum class StickerLottieSize : uchar {
SetsListThumbnail,
InlineResults,
EmojiInteraction,
EmojiInteractionReserved1,
EmojiInteractionReserved2,
EmojiInteractionReserved3,
};
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(

View File

@@ -58,6 +58,16 @@ std::map<int, const char*> BetaLogs() {
{
3000005,
"- Add support for Emoji 13.1."
},
{
3001002,
"- Control video in fullscreen mode using arrows and numbers.\n"
"- Open locations in browser if default Bing Maps is not installed.\n"
"- Reconnect without timeout when network availability changes.\n"
"- Crash fixes."
}
};
};

View File

@@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_instance.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "window/themes/window_theme_editor_box.h" // GenerateSlug.
#include "settings/settings_common.h"
#include "mainwidget.h"
#include "main/main_session.h"
@@ -469,6 +470,100 @@ bool ShowInviteLink(
return true;
}
void ExportTestChatTheme(
not_null<Main::Session*> session,
not_null<const Data::CloudTheme*> theme) {
if (!theme->paper
|| !theme->paper->isPattern()
|| theme->paper->backgroundColors().empty()
|| !theme->accentColor
|| !theme->paper->hasShareUrl()) {
Ui::Toast::Show("Something went wrong :(");
return;
}
const auto &bg = theme->paper->backgroundColors();
const auto url = theme->paper->shareUrl(session);
const auto from = url.indexOf("bg/");
const auto till = url.indexOf("?");
if (from < 0 || till <= from) {
Ui::Toast::Show("Bad WallPaper link: " + url);
return;
}
using Flag = MTPaccount_CreateTheme::Flag;
using Setting = MTPDinputThemeSettings::Flag;
using Paper = MTPDwallPaperSettings::Flag;
const auto color = [](const QColor &color) {
const auto red = color.red();
const auto green = color.green();
const auto blue = color.blue();
return int(((uint32(red) & 0xFFU) << 16)
| ((uint32(green) & 0xFFU) << 8)
| (uint32(blue) & 0xFFU));
};
const auto colors = [&](const std::vector<QColor> &colors) {
auto result = QVector<MTPint>();
result.reserve(colors.size());
for (const auto &single : colors) {
result.push_back(MTP_int(color(single)));
}
return result;
};
const auto slug = url.mid(from + 3, till - from - 3);
const auto flags = Flag::f_settings;
const auto settings = Setting::f_wallpaper
| Setting::f_wallpaper_settings
| (theme->outgoingAccentColor
? Setting::f_outbox_accent_color
: Setting(0))
| (!theme->outgoingMessagesColors.empty()
? Setting::f_message_colors
: Setting(0));
const auto papers = Paper::f_background_color
| Paper::f_intensity
| (bg.size() > 1
? Paper::f_second_background_color
: Paper(0))
| (bg.size() > 2
? Paper::f_third_background_color
: Paper(0))
| (bg.size() > 3
? Paper::f_fourth_background_color
: Paper(0));
session->api().request(MTPaccount_CreateTheme(
MTP_flags(flags),
MTP_string(Window::Theme::GenerateSlug()),
MTP_string(theme->title + " Desktop"),
MTPInputDocument(),
MTP_inputThemeSettings(
MTP_flags(settings),
(theme->basedOnDark
? MTP_baseThemeTinted()
: MTP_baseThemeClassic()),
MTP_int(color(theme->accentColor.value_or(Qt::black))),
MTP_int(color(theme->outgoingAccentColor.value_or(
Qt::black))),
MTP_vector<MTPint>(colors(
theme->outgoingMessagesColors)),
MTP_inputWallPaperSlug(MTP_string(slug)),
MTP_wallPaperSettings(
MTP_flags(papers),
MTP_int(color(bg[0])),
MTP_int(color(bg.size() > 1 ? bg[1] : Qt::black)),
MTP_int(color(bg.size() > 2 ? bg[2] : Qt::black)),
MTP_int(color(bg.size() > 3 ? bg[3] : Qt::black)),
MTP_int(theme->paper->patternIntensity()),
MTP_int(0)))
)).done([=](const MTPTheme &result) {
const auto slug = Data::CloudTheme::Parse(session, result, true).slug;
QGuiApplication::clipboard()->setText(
session->createInternalLinkFull("addtheme/" + slug));
Ui::Toast::Show(tr::lng_background_link_copied(tr::now));
}).fail([=](const MTP::Error &error) {
Ui::Toast::Show("Error: " + error.type());
}).send();
}
bool ResolveTestChatTheme(
Window::SessionController *controller,
const Match &match,
@@ -485,6 +580,9 @@ bool ResolveTestChatTheme(
history->peer->themeEmoji(),
params);
if (theme) {
if (!params["export"].isEmpty()) {
ExportTestChatTheme(&controller->session(), &*theme);
}
[[maybe_unused]] auto value = controller->cachedChatThemeValue(
*theme);
}

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 = 3000005;
constexpr auto AppVersionStr = "3.0.5";
constexpr auto AppVersion = 3001003;
constexpr auto AppVersionStr = "3.1.3";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -433,7 +433,7 @@ void CloudThemes::SetTestingColors(bool testing) {
IsTestingColors = testing;
}
QString CloudThemes::PrepareTestingLink(const CloudTheme &theme) {
QString CloudThemes::prepareTestingLink(const CloudTheme &theme) const {
const auto hex = [](int value) {
return QChar((value < 10) ? ('0' + value) : ('a' + (value - 10)));
};
@@ -460,6 +460,16 @@ QString CloudThemes::PrepareTestingLink(const CloudTheme &theme) {
if (theme.paper && !theme.paper->backgroundColors().empty()) {
arguments.push_back("bg=" + colors(theme.paper->backgroundColors()));
}
if (theme.paper/* && theme.paper->hasShareUrl()*/) {
arguments.push_back("intensity="
+ QString::number(theme.paper->patternIntensity()));
//const auto url = theme.paper->shareUrl(_session);
//const auto from = url.indexOf("bg/");
//const auto till = url.indexOf("?");
//if (from > 0 && till > from) {
// arguments.push_back("slug=" + url.mid(from + 3, till - from - 3));
//}
}
if (theme.outgoingAccentColor) {
arguments.push_back("out_accent" + color(*theme.outgoingAccentColor));
}
@@ -525,7 +535,11 @@ std::optional<CloudTheme> CloudThemes::updateThemeFromLink(
const auto bg = colors(params["bg"]);
applyTo.paper = (applyTo.paper && !bg.empty())
? std::make_optional(applyTo.paper->withBackgroundColors(bg))
: std::nullopt;
: applyTo.paper;
applyTo.paper = (applyTo.paper && params["intensity"].toInt())
? std::make_optional(
applyTo.paper->withPatternIntensity(params["intensity"].toInt()))
: applyTo.paper;
applyTo.outgoingAccentColor = color(params["out_accent"]);
applyTo.outgoingMessagesColors = colors(params["out_bg"]);
_chatThemesUpdates.fire({});

View File

@@ -77,7 +77,7 @@ public:
[[nodiscard]] static bool TestingColors();
static void SetTestingColors(bool testing);
[[nodiscard]] static QString PrepareTestingLink(const CloudTheme &theme);
[[nodiscard]] QString prepareTestingLink(const CloudTheme &theme) const;
[[nodiscard]] std::optional<CloudTheme> updateThemeFromLink(
const QString &emoji,
const QMap<QString, QString> &params);

View File

@@ -341,6 +341,9 @@ enum class MessageFlag : uint32 {
// Fake message for some UI element.
FakeHistoryItem = (1U << 27),
// Contact sign-up message, notification should be skipped for Silent.
IsContactSignUp = (1U << 28),
};
inline constexpr bool is_flag_type(MessageFlag) { return true; }
using MessageFlags = base::flags<MessageFlag>;

View File

@@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Editor {
QImage ImageModified(QImage image, const PhotoModifications &mods) {
Expects(!image.isNull());
if (!mods) {
return image;
}

View File

@@ -202,7 +202,8 @@ HistoryInner::HistoryInner(
using PlayRequest = ChatHelpers::EmojiInteractionPlayRequest;
_controller->emojiInteractions().playRequests(
) | rpl::filter([=](const PlayRequest &request) {
return (request.item->history() == _history);
return (request.item->history() == _history)
&& _controller->widget()->isActive();
}) | rpl::start_with_next([=](PlayRequest &&request) {
if (const auto view = request.item->mainView()) {
_emojiInteractions->play(std::move(request), view);

View File

@@ -459,6 +459,17 @@ bool HistoryItem::isScheduled() const {
&& (_flags & MessageFlag::IsOrWasScheduled);
}
bool HistoryItem::skipNotification() const {
if (isSilent() && (_flags & MessageFlag::IsContactSignUp)) {
return true;
} else if (const auto forwarded = Get<HistoryMessageForwarded>()) {
if (forwarded->imported) {
return true;
}
}
return false;
}
void HistoryItem::destroy() {
_history->destroyMessage(this);
}

View File

@@ -109,6 +109,7 @@ public:
[[nodiscard]] bool isAdminLogEntry() const;
[[nodiscard]] bool isFromScheduled() const;
[[nodiscard]] bool isScheduled() const;
[[nodiscard]] bool skipNotification() const;
void addLogEntryOriginal(
WebPageId localId,

View File

@@ -554,6 +554,8 @@ void HistoryService::applyAction(const MTPMessageAction &action) {
_flags |= MessageFlag::IsGroupEssential;
}, [&](const MTPDmessageActionChannelMigrateFrom &) {
_flags |= MessageFlag::IsGroupEssential;
}, [&](const MTPDmessageActionContactSignUp &) {
_flags |= MessageFlag::IsContactSignUp;
}, [](const auto &) {
});
}

View File

@@ -688,7 +688,8 @@ HistoryWidget::HistoryWidget(
auto text = QStringList();
const auto push = [&](QString label, const auto &theme) {
using namespace Data;
const auto l = CloudThemes::PrepareTestingLink(theme);
const auto &themes = _peer->owner().cloudThemes();
const auto l = themes.prepareTestingLink(theme);
if (!l.isEmpty()) {
text.push_back(label + ": " + l);
}
@@ -1410,15 +1411,16 @@ bool HistoryWidget::updateStickersByEmoji() {
}
void HistoryWidget::fieldChanged() {
const auto typing = (_history
&& !_inlineBot
&& !_editMsgId
&& (_textUpdateEvents & TextUpdateEvent::SendTyping));
const auto updateTyping = (_textUpdateEvents & TextUpdateEvent::SendTyping);
InvokeQueued(this, [=] {
updateInlineBotQuery();
const auto choosingSticker = updateStickersByEmoji();
if (!choosingSticker && typing) {
if (_history
&& !_inlineBot
&& !_editMsgId
&& !choosingSticker
&& updateTyping) {
session().sendProgressManager().update(
_history,
Api::SendProgressType::Typing);

View File

@@ -25,7 +25,7 @@ namespace HistoryView {
namespace {
constexpr auto kSizeMultiplier = 3;
constexpr auto kCachesCount = 4;
constexpr auto kMaxPlays = 5;
constexpr auto kMaxPlaysWithSmallDelay = 3;
constexpr auto kSmallDelay = crl::time(200);
@@ -59,16 +59,19 @@ EmojiInteractions::~EmojiInteractions() = default;
void EmojiInteractions::play(
ChatHelpers::EmojiInteractionPlayRequest request,
not_null<Element*> view) {
if (_plays.empty()) {
if (!view->media()) {
// Large emoji may be disabled.
return;
} else if (_plays.empty()) {
play(
std::move(request.emoji),
std::move(request.emoticon),
view,
std::move(request.media),
request.incoming);
} else {
const auto now = crl::now();
_delayed.push_back({
request.emoji,
request.emoticon,
view,
std::move(request.media),
now,
@@ -79,7 +82,7 @@ void EmojiInteractions::play(
}
void EmojiInteractions::play(
QString emoji,
QString emoticon,
not_null<Element*> view,
std::shared_ptr<Data::DocumentMedia> media,
bool incoming) {
@@ -90,12 +93,9 @@ void EmojiInteractions::play(
|| _visibleTop == _visibleBottom) {
return;
}
auto lottie = ChatHelpers::LottiePlayerFromDocument(
media.get(),
nullptr,
ChatHelpers::StickerLottieSize::EmojiInteraction,
_emojiSize * kSizeMultiplier * style::DevicePixelRatio(),
Lottie::Quality::High);
auto lottie = preparePlayer(media.get());
const auto shift = GenerateRandomShift(_emojiSize);
lottie->updates(
) | rpl::start_with_next([=](Lottie::Update update) {
@@ -114,13 +114,61 @@ void EmojiInteractions::play(
.shift = shift,
});
if (incoming) {
_playStarted.fire(std::move(emoji));
_playStarted.fire(std::move(emoticon));
}
if (const auto media = view->media()) {
media->stickerClearLoopPlayed();
}
}
std::unique_ptr<Lottie::SinglePlayer> EmojiInteractions::preparePlayer(
not_null<Data::DocumentMedia*> media) {
// Shortened copy from stickers_lottie module.
const auto document = media->owner();
const auto baseKey = document->bigFileBaseCacheKey();
const auto tag = uint8(0);
const auto keyShift = ((tag << 4) & 0xF0)
| (uint8(ChatHelpers::StickerLottieSize::EmojiInteraction) & 0x0F);
const auto key = Storage::Cache::Key{
baseKey.high,
baseKey.low + keyShift
};
const auto get = [=](int i, FnMut<void(QByteArray &&cached)> handler) {
document->owner().cacheBigFile().get(
{ key.high, key.low + i },
std::move(handler));
};
const auto weak = base::make_weak(&document->session());
const auto put = [=](int i, QByteArray &&cached) {
crl::on_main(weak, [=, data = std::move(cached)]() mutable {
weak->data().cacheBigFile().put(
{ key.high, key.low + i },
std::move(data));
});
};
const auto data = media->bytes();
const auto filepath = document->filepath();
const auto request = Lottie::FrameRequest{
_emojiSize * kSizeMultiplier * style::DevicePixelRatio(),
};
auto &weakProvider = _sharedProviders[document];
auto shared = [&] {
if (const auto result = weakProvider.lock()) {
return result;
}
const auto result = Lottie::SinglePlayer::SharedProvider(
kCachesCount,
get,
put,
Lottie::ReadContent(data, filepath),
request,
Lottie::Quality::High);
weakProvider = result;
return result;
}();
return std::make_unique<Lottie::SinglePlayer>(std::move(shared), request);
}
void EmojiInteractions::visibleAreaUpdated(
int visibleTop,
int visibleBottom) {
@@ -209,8 +257,11 @@ void EmojiInteractions::checkDelayed() {
}
auto good = std::move(*i);
_delayed.erase(begin(_delayed), i + 1);
const auto incoming = good.incoming;
play(std::move(good.emoji), good.view, std::move(good.media), incoming);
play(
std::move(good.emoticon),
good.view,
std::move(good.media),
good.incoming);
}
rpl::producer<QRect> EmojiInteractions::updateRequests() const {

View File

@@ -17,6 +17,7 @@ struct EmojiInteractionPlayRequest;
namespace Lottie {
class SinglePlayer;
class FrameProvider;
} // namespace Lottie
namespace Main {
@@ -52,7 +53,7 @@ private:
bool finished = false;
};
struct Delayed {
QString emoji;
QString emoticon;
not_null<Element*> view;
std::shared_ptr<Data::DocumentMedia> media;
crl::time shouldHaveStartedAt = 0;
@@ -62,12 +63,15 @@ private:
[[nodiscard]] QRect computeRect(not_null<Element*> view) const;
void play(
QString emoji,
QString emoticon,
not_null<Element*> view,
std::shared_ptr<Data::DocumentMedia> media,
bool incoming);
void checkDelayed();
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> preparePlayer(
not_null<Data::DocumentMedia*> media);
const not_null<Main::Session*> _session;
int _visibleTop = 0;
@@ -78,6 +82,9 @@ private:
std::vector<Delayed> _delayed;
rpl::event_stream<QRect> _updateRequests;
rpl::event_stream<QString> _playStarted;
base::flat_map<
not_null<DocumentData*>,
std::weak_ptr<Lottie::FrameProvider>> _sharedProviders;
rpl::lifetime _lifetime;

View File

@@ -1421,6 +1421,7 @@ QPixmap RepliesWidget::grabForShowAnimation(const Window::SectionSlideParams &pa
_composeControls->showForGrab();
auto result = Ui::GrabWidget(this);
if (params.withTopBarShadow) _topBarShadow->show();
_rootView->hide();
return result;
}
@@ -1537,7 +1538,7 @@ void RepliesWidget::restoreState(not_null<RepliesMemento*> memento) {
? (areComments
? tr::lng_comments_header
: tr::lng_replies_header)(
lt_count,
lt_count_decimal,
rpl::single(count) | tr::to_count())
: (areComments
? tr::lng_comments_header_none
@@ -1706,6 +1707,7 @@ void RepliesWidget::showAnimatedHook(
void RepliesWidget::showFinishedHook() {
_topBar->setAnimatingMode(false);
_composeControls->showFinished();
_rootView->show();
// We should setup the drag area only after
// the section animation is finished,

View File

@@ -667,7 +667,7 @@ void TopBarWidget::setActiveChat(
) | rpl::filter([=](const InteractionSeen &seen) {
return (seen.peer == history->peer);
}) | rpl::start_with_next([=](const InteractionSeen &seen) {
handleEmojiInteractionSeen(seen.emoji->text());
handleEmojiInteractionSeen(seen.emoticon);
}, lifetime());
}
}

View File

@@ -1207,31 +1207,67 @@ void Poll::paintFilling(
top += st::historyPollAnswerPadding.top();
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
const auto thickness = st::historyPollFillingHeight;
const auto max = awidth - st::historyPollFillingRight;
const auto size = anim::interpolate(st::historyPollFillingMin, max, filling);
const auto radius = st::historyPollFillingRadius;
const auto ftop = bottom - st::historyPollFillingBottom - thickness;
if (chosen && !correct) {
p.setBrush(st->boxTextFgError());
} else if (chosen && correct && _poll->quiz() && !context.outbg) {
p.setBrush(st->boxTextFgGood());
} else {
p.setBrush(stm->msgWaveformActive);
}
enum class Style {
Incorrect,
Correct,
Default,
};
const auto style = [&] {
if (chosen && !correct) {
return Style::Incorrect;
} else if (chosen && correct && _poll->quiz() && !context.outbg) {
return Style::Correct;
} else {
return Style::Default;
}
}();
auto barleft = aleft;
auto barwidth = size;
const auto &color = (style == Style::Incorrect)
? st->boxTextFgError()
: (style == Style::Correct)
? st->boxTextFgGood()
: stm->msgFileBg;
p.setPen(Qt::NoPen);
p.setBrush(color);
PainterHighQualityEnabler hq(p);
if (chosen || correct) {
const auto &icon = (chosen && !correct)
const auto &icon = (style == Style::Incorrect)
? st->historyPollChoiceWrong()
: st->historyPollChoiceRight();
: (style == Style::Correct)
? st->historyPollChoiceRight()
: stm->historyPollChoiceRight;
const auto cleft = aleft - st::historyPollPercentSkip - icon.width();
const auto ctop = ftop - (icon.height() - thickness) / 2;
p.drawEllipse(cleft, ctop, icon.width(), icon.height());
icon.paint(p, cleft, ctop, width);
const auto paintContent = [&](Painter &p) {
icon.paint(p, cleft, ctop, width);
};
if (style == Style::Default && usesBubblePattern(context)) {
const auto add = st::lineWidth * 2;
const auto target = QRect(
cleft,
ctop,
icon.width(),
icon.height()
).marginsAdded({ add, add, add, add });
Ui::PaintPatternBubblePart(
p,
context.viewport,
context.bubblesPattern->pixmap,
target,
paintContent,
_fillingIconCache);
} else {
paintContent(p);
}
//barleft += icon.width() - radius;
//barwidth -= icon.width() - radius;
}

View File

@@ -214,6 +214,7 @@ private:
Ui::Animations::Simple _wrongAnswerAnimation;
mutable QPoint _lastLinkPoint;
mutable QImage _userpicCircleCache;
mutable QImage _fillingIconCache;
mutable std::unique_ptr<CloseInformation> _close;

View File

@@ -779,7 +779,7 @@ void MainWindow::toggleDisplayNotifyFromTray() {
settings.setRememberedFlashBounceNotifyFromTray(false);
}
}
account().session().saveSettings();
Core::App().saveSettingsDelayed();
using Change = Window::Notifications::ChangeType;
auto &notifications = Core::App().notifications();
notifications.notifySettingsChanged(Change::DesktopEnabled);

View File

@@ -94,6 +94,7 @@ constexpr auto kPreloadCount = 3;
constexpr auto kMaxZoomLevel = 7; // x8
constexpr auto kZoomToScreenLevel = 1024;
constexpr auto kOverlayLoaderPriority = 2;
constexpr auto kSeekTimeMs = 5 * crl::time(1000);
// macOS OpenGL renderer fails to render larger texture
// even though it reports that max texture size is 16384.
@@ -3002,6 +3003,23 @@ void OverlayWidget::playbackPauseResume() {
}
}
void OverlayWidget::seekRelativeTime(crl::time time) {
Expects(_streamed != nullptr);
const auto newTime = std::clamp(
_streamed->instance.info().video.state.position + time,
crl::time(0),
_streamed->instance.info().video.state.duration);
restartAtSeekPosition(newTime);
}
void OverlayWidget::restartAtProgress(float64 progress) {
Expects(_streamed != nullptr);
restartAtSeekPosition(_streamed->instance.info().video.state.duration
* std::clamp(progress, 0., 1.));
}
void OverlayWidget::restartAtSeekPosition(crl::time position) {
Expects(_streamed != nullptr);
@@ -3737,7 +3755,21 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
} else if (_fullScreenVideo) {
if (key == Qt::Key_Escape) {
playbackToggleFullScreen();
} else if (key == Qt::Key_0) {
activateControls();
restartAtSeekPosition(0);
} else if (key >= Qt::Key_1 && key <= Qt::Key_9) {
activateControls();
const auto index = int(key - Qt::Key_0);
restartAtProgress(index / 10.0);
} else if (key == Qt::Key_Left) {
activateControls();
seekRelativeTime(-kSeekTimeMs);
} else if (key == Qt::Key_Right) {
activateControls();
seekRelativeTime(kSeekTimeMs);
}
return;
}
}
@@ -4598,7 +4630,7 @@ void OverlayWidget::clearBeforeHide() {
_groupThumbs = nullptr;
_groupThumbsRect = QRect();
for (const auto child : _widget->children()) {
if (child->isWidgetType()) {
if (child->isWidgetType() && _hideWorkaround.get() != child) {
static_cast<QWidget*>(child)->hide();
}
}

View File

@@ -294,6 +294,8 @@ private:
void setZoomLevel(int newZoom, bool force = false);
void updatePlaybackState();
void seekRelativeTime(crl::time time);
void restartAtProgress(float64 progress);
void restartAtSeekPosition(crl::time position);
void refreshClipControllerGeometry();

View File

@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/win/windows_app_user_model_id.h"
#include "platform/win/windows_dlls.h"
#include "base/platform/base_platform_info.h"
#include "base/platform/win/base_windows_winrt.h"
#include "base/call_delayed.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
@@ -28,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <qpa/qplatformnativeinterface.h>
#include <Shobjidl.h>
#include <ShObjIdl_core.h>
#include <shellapi.h>
#include <roapi.h>
@@ -546,5 +548,29 @@ void psSendToMenu(bool send, bool silent) {
}
bool psLaunchMaps(const Data::LocationPoint &point) {
return QDesktopServices::openUrl(qsl("bingmaps:?lvl=16&collection=point.%1_%2_Point").arg(point.latAsString()).arg(point.lonAsString()));
const auto aar = base::WinRT::TryCreateInstance<
IApplicationAssociationRegistration
>(CLSID_ApplicationAssociationRegistration);
if (!aar) {
return false;
}
auto handler = (LPWSTR)nullptr;
const auto guard = gsl::finally([&] {
if (handler) {
::CoTaskMemFree(handler);
}
});
const auto result = aar->QueryCurrentDefault(
L"bingmaps",
AT_URLPROTOCOL,
AL_EFFECTIVE,
&handler);
if (FAILED(result) || !handler) {
return false;
}
const auto url = u"bingmaps:?lvl=16&collection=point.%1_%2_Point"_q;
return QDesktopServices::openUrl(
url.arg(point.latAsString()).arg(point.lonAsString()));
}

View File

@@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image_prepare.h"
#include "ui/chat/attach/attach_extensions.h"
#include "ui/chat/attach/attach_prepare.h"
#include "core/crash_reports.h"
#include <QtCore/QSemaphore>
#include <QtCore/QMimeData>
@@ -40,6 +41,8 @@ bool HasExtensionFrom(const QString &file, const QStringList &extensions) {
bool ValidPhotoForAlbum(
const Image &image,
const QString &mime) {
Expects(!image.data.isNull());
if (image.animated
|| Core::IsMimeSticker(mime)
|| (!mime.isEmpty() && !mime.startsWith(u"image/"))) {
@@ -228,6 +231,8 @@ PreparedList PrepareMediaFromImage(
QImage &&image,
QByteArray &&content,
int previewWidth) {
Expects(!image.isNull());
auto result = PreparedList();
auto file = PreparedFile(QString());
file.content = content;
@@ -288,6 +293,7 @@ void PrepareDetails(PreparedFile &file, int previewWidth) {
using Song = PreparedFileInformation::Song;
if (const auto image = std::get_if<Image>(
&file.information->media)) {
Assert(!image->data.isNull());
if (ValidPhotoForAlbum(*image, file.information->filemime)) {
UpdateImageDetails(file, previewWidth);
file.type = PreparedFile::Type::Photo;
@@ -317,14 +323,29 @@ void UpdateImageDetails(PreparedFile &file, int previewWidth) {
if (!image) {
return;
}
const auto &preview = image->modifications
Assert(!image->data.isNull());
auto preview = image->modifications
? Editor::ImageModified(image->data, image->modifications)
: image->data;
Assert(!preview.isNull());
file.shownDimensions = PrepareShownDimensions(preview);
file.preview = Images::prepareOpaque(preview.scaledToWidth(
std::min(previewWidth, style::ConvertScale(preview.width()))
* cIntRetinaFactor(),
Qt::SmoothTransformation));
const auto toWidth = std::min(
previewWidth,
style::ConvertScale(preview.width())
) * cIntRetinaFactor();
const auto scaled = preview.scaledToWidth(
toWidth,
Qt::SmoothTransformation);
if (scaled.isNull()) {
CrashReports::SetAnnotation("Info", QString("%1x%2:%3*%4->%5;%6x%7"
).arg(preview.width()).arg(preview.height()
).arg(previewWidth).arg(cIntRetinaFactor()
).arg(toWidth
).arg(scaled.width()).arg(scaled.height()));
Unexpected("Scaled is null.");
}
Assert(!scaled.isNull());
file.preview = Images::prepareOpaque(scaled);
Assert(!file.preview.isNull());
file.preview.setDevicePixelRatio(cRetinaFactor());
}

View File

@@ -69,16 +69,16 @@ historyResizeWidth: 6px;
historyPaddingBottom: 8px;
historyToDownPosition: point(12px, 10px);
historyToDownAbove: icon {{ "history_down_arrow", historyToDownFg, point(17px, 23px) }};
historyToDownAboveOver: icon {{ "history_down_arrow", historyToDownFgOver, point(17px, 23px) }};
historyToDownAbove: icon {{ "history_down_arrow", historyToDownFg }};
historyToDownAboveOver: icon {{ "history_down_arrow", historyToDownFgOver }};
historyToDownPaddingTop: 10px;
historyToDownBelow: icon {
{ "history_down_shadow", historyToDownShadow },
{ "history_down_circle", historyToDownBg, point(4px, 4px) },
{ "history_down_circle", historyToDownBg },
};
historyToDownBelowOver: icon {
{ "history_down_shadow", historyToDownShadow },
{ "history_down_circle", historyToDownBgOver, point(4px, 4px) },
{ "history_down_circle", historyToDownBgOver },
};
historyToDown: TwoIconButton {
width: 52px;
@@ -102,8 +102,8 @@ historyToDownBadgeSize: 22px;
historyToDownShownAfter: 480px;
historyToDownDuration: 150;
dialogsToUpAbove: icon {{ "history_down_arrow-flip_vertical", historyToDownFg, point(17px, 20px) }};
dialogsToUpAboveOver: icon {{ "history_down_arrow-flip_vertical", historyToDownFgOver, point(17px, 20px) }};
dialogsToUpAbove: icon {{ "history_down_arrow-flip_vertical", historyToDownFg, point(0px, 1px) }};
dialogsToUpAboveOver: icon {{ "history_down_arrow-flip_vertical", historyToDownFgOver, point(0px, 1px) }};
dialogsToUp: TwoIconButton(historyToDown) {
iconAbove: dialogsToUpAbove;
@@ -741,6 +741,10 @@ historyPollBottomButtonSkip: 15px;
historyPollBottomButtonTop: 4px;
historyPollChoiceRight: icon {{ "poll_choice_right", activeButtonFg }};
historyPollChoiceWrong: icon {{ "poll_choice_wrong", activeButtonFg }};
historyPollOutChoiceRight: icon {{ "poll_choice_right", historyFileOutIconFg }};
historyPollOutChoiceRightSelected: icon {{ "poll_choice_right", historyFileOutIconFgSelected }};
historyPollInChoiceRight: icon {{ "poll_choice_right", historyFileInIconFg }};
historyPollInChoiceRightSelected: icon {{ "poll_choice_right", historyFileInIconFgSelected }};
historyPollOutChosen: icon {{ "poll_select_check", historyFileOutIconFg }};
historyPollOutChosenSelected: icon {{ "poll_select_check", historyFileOutIconFgSelected }};
historyPollInChosen: icon {{ "poll_select_check", historyFileInIconFg }};

View File

@@ -391,6 +391,12 @@ ChatStyle::ChatStyle() {
st::historyPollInChosenSelected,
st::historyPollOutChosen,
st::historyPollOutChosenSelected);
make(
&MessageStyle::historyPollChoiceRight,
st::historyPollInChoiceRight,
st::historyPollInChoiceRightSelected,
st::historyPollOutChoiceRight,
st::historyPollOutChoiceRightSelected);
make(
&MessageImageStyle::msgDateImgBg,
st::msgDateImgBg,
@@ -473,6 +479,12 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
_msgSelectOverlayCornersSmall = {};
_msgSelectOverlayCornersLarge = {};
for (auto &stm : _messageStyles) {
const auto same = (stm.textPalette.linkFg->c == stm.historyTextFg->c);
stm.textPalette.linkAlwaysActive = same ? 1 : 0;
stm.semiboldPalette.linkAlwaysActive = same ? 1 : 0;
}
_paletteChanged.fire({});
}
@@ -598,6 +610,7 @@ void ChatStyle::make(style::icon &my, const style::icon &original) const {
void ChatStyle::make(
style::TextPalette &my,
const style::TextPalette &original) const {
my.linkAlwaysActive = original.linkAlwaysActive;
make(my.linkFg, original.linkFg);
make(my.monoFg, original.monoFg);
make(my.selectBg, original.selectBg);

View File

@@ -69,6 +69,7 @@ struct MessageStyle {
style::icon historyQuizTimer = { Qt::Uninitialized };
style::icon historyQuizExplain = { Qt::Uninitialized };
style::icon historyPollChosen = { Qt::Uninitialized };
style::icon historyPollChoiceRight = { Qt::Uninitialized };
};
struct MessageImageStyle {

View File

@@ -265,8 +265,6 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
adjust(p.msgOutReplyBarColor(), by);
adjust(p.msgWaveformOutActive(), by);
adjust(p.msgWaveformOutInactive(), by);
//adjust(p.historyTextOutFg(), by); // windowFg
//adjust(p.historyFileNameOutFg(), by); // historyTextOutFg
adjust(p.historyFileOutRadialFg(), by); // historyFileOutIconFg
adjust(p.mediaOutFg(), by);
@@ -291,6 +289,40 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
adjust(p.historyOutIconFg(), colorizer);
adjust(p.historySendingOutIconFg(), colorizer);
adjust(p.historyCallArrowOutFg(), colorizer);
if (!descriptor.basedOnDark) {
adjust(p.msgOutBgSelected(), by);
adjust(p.msgOutShadowSelected(), by);
adjust(p.msgOutServiceFgSelected(), by);
adjust(p.msgOutDateFgSelected(), by);
adjust(p.msgFileThumbLinkOutFgSelected(), by);
adjust(p.msgFileOutBgSelected(), by);
adjust(p.msgOutReplyBarSelColor(), by);
adjust(p.msgWaveformOutActiveSelected(), by);
adjust(p.msgWaveformOutInactiveSelected(), by);
adjust(p.historyFileOutRadialFgSelected(), by);
adjust(p.mediaOutFgSelected(), by);
adjust(p.historyLinkOutFgSelected(), by);
adjust(p.msgOutMonoFgSelected(), by);
adjust(p.historyOutIconFgSelected(), by);
// adjust(p.historySendingOutIconFgSelected(), by);
adjust(p.historyCallArrowOutFgSelected(), by);
adjust(p.historyFileOutIconFgSelected(), by); // msgOutBg
adjust(p.msgOutServiceFgSelected(), colorizer);
adjust(p.msgOutDateFgSelected(), colorizer);
adjust(p.msgFileThumbLinkOutFgSelected(), colorizer);
adjust(p.msgFileOutBgSelected(), colorizer);
adjust(p.msgOutReplyBarSelColor(), colorizer);
adjust(p.msgWaveformOutActiveSelected(), colorizer);
adjust(p.msgWaveformOutInactiveSelected(), colorizer);
adjust(p.mediaOutFgSelected(), colorizer);
adjust(p.historyLinkOutFgSelected(), colorizer);
adjust(p.historyOutIconFgSelected(), colorizer);
//adjust(p.historySendingOutIconFgSelected(), colorizer);
adjust(p.historyCallArrowOutFgSelected(), colorizer);
}
}
auto outBgColors = descriptor.bubblesData.colors;
if (outBgColors.empty()) {

View File

@@ -98,25 +98,21 @@ System::SkipState System::skipNotification(
not_null<HistoryItem*> item) const {
const auto history = item->history();
const auto notifyBy = item->specialNotificationPeer();
if (App::quitting() || !history->currentNotification()) {
if (App::quitting()
|| !history->currentNotification()
|| item->skipNotification()) {
return { SkipState::Skip };
} else if (!Core::App().settings().notifyFromAll()
&& &history->session().account() != &Core::App().domain().active()) {
return { SkipState::Skip };
}
const auto scheduled = item->out() && item->isFromScheduled();
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
if (forwarded->imported) {
return { SkipState::Skip };
}
}
history->owner().requestNotifySettings(history->peer);
if (notifyBy) {
history->owner().requestNotifySettings(notifyBy);
}
const auto scheduled = item->out() && item->isFromScheduled();
if (history->owner().notifyMuteUnknown(history->peer)) {
return { SkipState::Unknown, item->isSilent() };
} else if (!history->owner().notifyIsMuted(history->peer)) {

View File

@@ -25,6 +25,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Window {
namespace {
constexpr auto kDarkValueThreshold = 0.5;
[[nodiscard]] rpl::producer<QString> PeerThemeEmojiValue(
not_null<PeerData*> peer) {
return peer->session().changes().peerFlagsValue(
@@ -49,9 +51,17 @@ namespace {
[[nodiscard]] auto MaybeCloudThemeValueFromPeer(
not_null<PeerData*> peer)
-> rpl::producer<std::optional<Data::CloudTheme>> {
auto isThemeDarkValue = rpl::single(
rpl::empty_value()
) | rpl::then(
style::PaletteChanged()
) | rpl::map([] {
return (st::dialogsBg->c.valueF() < kDarkValueThreshold);
}) | rpl::distinct_until_changed();
return rpl::combine(
MaybeChatThemeDataValueFromPeer(peer),
Theme::IsNightModeValue()
std::move(isThemeDarkValue)
) | rpl::map([](std::optional<Data::ChatTheme> theme, bool night) {
return !theme
? std::nullopt

View File

@@ -330,26 +330,6 @@ bool CopyColorsToPalette(
return true;
}
[[nodiscard]] QString GenerateSlug() {
const auto letters = uint8('Z' + 1 - 'A');
const auto digits = uint8('9' + 1 - '0');
const auto values = uint8(2 * letters + digits);
auto result = QString();
result.reserve(kRandomSlugSize);
for (auto i = 0; i != kRandomSlugSize; ++i) {
const auto value = base::RandomValue<uint8>() % values;
if (value < letters) {
result.append(char('A' + value));
} else if (value < 2 * letters) {
result.append(char('a' + (value - letters)));
} else {
result.append(char('0' + (value - 2 * letters)));
}
}
return result;
}
[[nodiscard]] QByteArray PackTheme(const ParsedTheme &parsed) {
zlib::FileToWrite zip;
@@ -1018,5 +998,25 @@ ParsedTheme ParseTheme(
return result();
}
[[nodiscard]] QString GenerateSlug() {
const auto letters = uint8('Z' + 1 - 'A');
const auto digits = uint8('9' + 1 - '0');
const auto values = uint8(2 * letters + digits);
auto result = QString();
result.reserve(kRandomSlugSize);
for (auto i = 0; i != kRandomSlugSize; ++i) {
const auto value = base::RandomValue<uint8>() % values;
if (value < letters) {
result.append(char('A' + value));
} else if (value < 2 * letters) {
result.append(char('a' + (value - letters)));
} else {
result.append(char('0' + (value - 2 * letters)));
}
}
return result;
}
} // namespace Theme
} // namespace Window

View File

@@ -54,5 +54,7 @@ void SaveThemeBox(
bool onlyPalette = false,
bool parseCurrent = true);
[[nodiscard]] QString GenerateSlug();
} // namespace Theme
} // namespace Window

View File

@@ -75,7 +75,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Window {
namespace {
constexpr auto kCustomThemesInMemory = 5;
constexpr auto kMaxChatEntryHistorySize = 50;
constexpr auto kDayBaseFile = ":/gui/day-custom-base.tdesktop-theme"_cs;
constexpr auto kNightBaseFile = ":/gui/night-custom-base.tdesktop-theme"_cs;
[[nodiscard]] Fn<void(style::palette&)> PreparePaletteCallback(
bool dark,
@@ -92,21 +95,16 @@ constexpr auto kMaxChatEntryHistorySize = 50;
? ColorizerFrom(*i, *accent)
: style::colorizer();
if (dark) {
auto instance = Instance();
const auto loaded = LoadFromFile(
i->path,
&instance,
nullptr,
nullptr,
colorizer);
Assert(loaded);
palette.finalize();
palette = instance.palette;
} else {
palette.finalize(colorizer);
}
auto instance = Instance();
const auto loaded = LoadFromFile(
(dark ? kNightBaseFile : kDayBaseFile).utf16(),
&instance,
nullptr,
nullptr,
colorizer);
Assert(loaded);
palette.finalize();
palette = instance.palette;
};
}
@@ -508,9 +506,10 @@ void SessionNavigation::showPollResults(
}
struct SessionController::CachedTheme {
std::shared_ptr<Ui::ChatTheme> theme;
std::weak_ptr<Ui::ChatTheme> theme;
std::shared_ptr<Data::DocumentMedia> media;
Data::WallPaper paper;
bool caching = false;
rpl::lifetime lifetime;
};
@@ -1396,10 +1395,13 @@ auto SessionController::cachedChatThemeValue(
return rpl::single(_defaultChatTheme);
}
const auto i = _customChatThemes.find(key);
if (i != end(_customChatThemes) && i->second.theme) {
return rpl::single(i->second.theme);
if (i != end(_customChatThemes)) {
if (auto strong = i->second.theme.lock()) {
pushToLastUsed(strong);
return rpl::single(std::move(strong));
}
}
if (i == end(_customChatThemes)) {
if (i == end(_customChatThemes) || !i->second.caching) {
cacheChatTheme(data);
}
const auto limit = Data::CloudThemes::TestingColors() ? (1 << 20) : 1;
@@ -1408,10 +1410,27 @@ auto SessionController::cachedChatThemeValue(
_defaultChatTheme
) | rpl::then(_cachedThemesStream.events(
) | rpl::filter([=](const std::shared_ptr<Ui::ChatTheme> &theme) {
return (theme->key() == key);
if (theme->key() != key) {
return false;
}
pushToLastUsed(theme);
return true;
}) | rpl::take(limit));
}
void SessionController::pushToLastUsed(
const std::shared_ptr<Ui::ChatTheme> &theme) {
const auto i = ranges::find(_lastUsedCustomChatThemes, theme);
if (i == end(_lastUsedCustomChatThemes)) {
if (_lastUsedCustomChatThemes.size() >= kCustomThemesInMemory) {
_lastUsedCustomChatThemes.pop_back();
}
_lastUsedCustomChatThemes.push_front(theme);
} else if (i != begin(_lastUsedCustomChatThemes)) {
std::rotate(begin(_lastUsedCustomChatThemes), i, i + 1);
}
}
void SessionController::setChatStyleTheme(
const std::shared_ptr<Ui::ChatTheme> &theme) {
if (_chatStyleTheme.lock() == theme) {
@@ -1450,9 +1469,22 @@ void SessionController::cacheChatTheme(const Data::CloudTheme &data) {
const auto document = data.paper->document();
const auto media = document ? document->createMediaView() : nullptr;
data.paper->loadDocument();
auto &theme = _customChatThemes.emplace(
key,
CachedTheme{ .media = media, .paper = *data.paper }).first->second;
auto &theme = [&]() -> CachedTheme& {
const auto i = _customChatThemes.find(key);
if (i != end(_customChatThemes)) {
i->second.media = media;
i->second.paper = *data.paper;
i->second.caching = true;
return i->second;
}
return _customChatThemes.emplace(
key,
CachedTheme{
.media = media,
.paper = *data.paper,
.caching = true,
}).first->second;
}();
auto descriptor = Ui::ChatThemeDescriptor{
.id = key,
.preparePalette = PreparePaletteCallback(
@@ -1488,6 +1520,7 @@ void SessionController::cacheChatThemeDone(
if (i == end(_customChatThemes)) {
return;
}
i->second.caching = false;
i->second.theme = result;
if (i->second.media) {
if (i->second.media->loaded(true)) {
@@ -1513,10 +1546,11 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) {
theme.lifetime.destroy();
theme.media = nullptr;
});
if (!theme.media || !theme.theme || !theme.media->loaded(true)) {
const auto strong = theme.theme.lock();
if (!theme.media || !strong || !theme.media->loaded(true)) {
return;
}
const auto key = theme.theme->key();
const auto key = strong->key();
const auto weak = base::make_weak(this);
crl::async([=, data = backgroundData(theme, false)] {
crl::on_main(weak, [
@@ -1525,7 +1559,9 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) {
]() mutable {
const auto i = _customChatThemes.find(key);
if (i != end(_customChatThemes)) {
i->second.theme->updateBackgroundImageFrom(std::move(result));
if (const auto strong = i->second.theme.lock()) {
strong->updateBackgroundImageFrom(std::move(result));
}
}
});
});

View File

@@ -464,6 +464,7 @@ private:
[[nodiscard]] Ui::ChatThemeBackgroundData backgroundData(
CachedTheme &theme,
bool generateGradient = true) const;
void pushToLastUsed(const std::shared_ptr<Ui::ChatTheme> &theme);
const not_null<Controller*> _window;
const std::unique_ptr<ChatHelpers::EmojiInteractions> _emojiInteractions;
@@ -498,6 +499,7 @@ private:
rpl::event_stream<std::shared_ptr<Ui::ChatTheme>> _cachedThemesStream;
const std::unique_ptr<Ui::ChatStyle> _chatStyle;
std::weak_ptr<Ui::ChatTheme> _chatStyleTheme;
std::deque<std::shared_ptr<Ui::ChatTheme>> _lastUsedCustomChatThemes;
rpl::lifetime _lifetime;

View File

@@ -29,7 +29,7 @@ ENV LibrariesPath /usr/src/Libraries
WORKDIR $LibrariesPath
FROM builder AS patches
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout 01779db1de
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout 9d2a07ba8b
FROM builder AS extra-cmake-modules
@@ -646,7 +646,11 @@ WORKDIR glibmm
RUN git apply ../patches/glibmm.patch
ENV ACLOCAL_PATH="/usr/local/share/aclocal"
RUN NOCONFIGURE=1 ./autogen.sh
RUN ./configure --enable-maintainer-mode --enable-static --disable-documentation
RUN CC=\"gcc -flto\" CXX=\"g++ -flto\" AR=gcc-ar RANLIB=gcc-ranlib ./configure \
--enable-maintainer-mode \
--enable-static \
--disable-documentation
RUN make -j$(nproc)
RUN make DESTDIR="$LibrariesPath/glibmm-cache" install

View File

@@ -0,0 +1,7 @@
set -e
FullExecPath=$PWD
pushd `dirname $0` > /dev/null
FullScriptPath=`pwd`
popd > /dev/null
./build/docker/centos_env/prepare.sh

View File

@@ -246,23 +246,26 @@ def winFailOnEach(command):
result = result + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%\r\n'
return result
def run(command):
def printCommands(commands):
print('---------------------------------COMMANDS-LIST----------------------------------')
print(command, end='')
print(commands, end='')
print('--------------------------------------------------------------------------------')
def run(commands):
printCommands(commands)
if win:
if os.path.exists("command.bat"):
os.remove("command.bat")
with open("command.bat", 'w') as file:
file.write('@echo OFF\r\n' + winFailOnEach(command))
file.write('@echo OFF\r\n' + winFailOnEach(commands))
result = subprocess.run("command.bat", shell=True, env=modifiedEnv).returncode == 0
if result and os.path.exists("command.bat"):
os.remove("command.bat")
return result
elif re.search(r'\%', command):
error('Bad command: ' + command)
elif re.search(r'\%', commands):
error('Bad command: ' + commands)
else:
return subprocess.run("set -e\n" + command, shell=True, env=modifiedEnv).returncode == 0
return subprocess.run("set -e\n" + commands, shell=True, env=modifiedEnv).returncode == 0
# Thanks https://stackoverflow.com/a/510364
class _Getch:
@@ -328,6 +331,7 @@ def runStages():
prefix = '[' + str(index) + '/' + str(count) + '](' + stage['location'] + '/' + stage['name'] + version + ')'
print(prefix + ': ', end = '', flush=True)
stage['key'] = computeCacheKey(stage)
commands = removeDir(stage['name']) + '\n' + stage['commands']
checkResult = 'Forced' if len(onlyStages) > 0 else checkCacheKey(stage)
if checkResult == 'Good':
print('SKIPPING')
@@ -340,11 +344,15 @@ def runStages():
if rebuildStale:
checkResult == 'Rebuild'
else:
print('(r)ebuild, rebuild (a)ll, (s)kip, (q)uit?: ', end='', flush=True)
print('(r)ebuild, rebuild (a)ll, (s)kip, (p)rint, (q)uit?: ', end='', flush=True)
while True:
ch = 'r' if rebuildStale else getch()
if ch == 'q':
finish(0)
elif ch == 'p':
printCommands(commands)
checkResult = 'Printed'
break
elif ch == 's':
checkResult = 'Skip'
break
@@ -355,13 +363,14 @@ def runStages():
checkResult = 'Rebuild'
rebuildStale = True
break
if checkResult == 'Printed':
continue
if checkResult == 'Skip':
print('SKIPPING')
continue
clearCacheKey(stage)
print('BUILDING:')
os.chdir(stage['directory'])
commands = removeDir(stage['name']) + '\n' + stage['commands']
if not run(commands):
print(prefix + ': FAILED')
finish(1)
@@ -370,7 +379,7 @@ def runStages():
stage('patches', """
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout 1a1d9e6d2c
git checkout 97eee9f4e5
""")
stage('depot_tools', """
@@ -387,6 +396,7 @@ depends:patches/gyp.diff
git apply $LIBS_DIR/patches/gyp.diff
mac:
python3 -m pip install git+https://github.com/nodejs/gyp-next@v0.10.0
mkdir gyp
""", 'ThirdParty')
stage('yasm', """
@@ -489,13 +499,19 @@ mac:
""")
stage('opus', """
git clone -b td-v1.3.1 https://github.com/telegramdesktop/opus.git
git clone -b v1.3.1 https://github.com/xiph/opus.git
cd opus
git cherry-pick 927de8453c
win:
cd win32\\VS2015
msbuild opus.sln /property:Configuration=Debug /property:Platform="%WIN32X64%"
cmake -B out . ^
-A %WIN32X64% ^
-DCMAKE_INSTALL_PREFIX=%LIBS_DIR%/local/opus ^
-DCMAKE_C_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" ^
-DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG"
cmake --build out --config Debug
release:
msbuild opus.sln /property:Configuration=Release /property:Platform="%WIN32X64%"
cmake --build out --config Release
cmake --install out --config Release
mac:
./autogen.sh
CFLAGS="$MIN_VER $UNGUARDED" CPPFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --prefix=$USED_PREFIX
@@ -759,7 +775,7 @@ stage('tg_angle', """
win:
git clone https://github.com/desktop-app/tg_angle.git
cd tg_angle
git checkout ec51cc6
git checkout 0bb011f9e4
mkdir out
cd out
mkdir Debug
@@ -793,10 +809,11 @@ win:
for /r %%i in (..\\..\\patches\\qtbase_5_15_2\\*) do git apply %%i
cd ..
SET CONFIGURATIONS=-debug-and-release
release:
SET CONFIGURATIONS=-debug
release:
SET CONFIGURATIONS=-debug-and-release
win:
""" + removeDir("\"%LIBS_DIR%\\Qt-5.15.2\"") + """
SET ANGLE_DIR=%LIBS_DIR%\\tg_angle
SET ANGLE_LIBS_DIR=%ANGLE_DIR%\\out
SET MOZJPEG_DIR=%LIBS_DIR%\\mozjpeg
@@ -837,9 +854,9 @@ mac:
find ../../patches/qtbase_5_15_2 -type f -print0 | sort -z | xargs -0 git apply
cd ..
CONFIGURATIONS=-debug-and-release
release:
CONFIGURATIONS=-debug
release:
CONFIGURATIONS=-debug-and-release
mac:
./configure -prefix "$USED_PREFIX/Qt-5.15.2" \
$CONFIGURATIONS \

View File

@@ -34,7 +34,8 @@ for arg in sys.argv:
versionMajor = match.group(1)
versionMinor = match.group(2)
versionPatch = match.group(4) if match.group(4) else '0'
if len(match.group(5)) > 0:
versionAlphaBeta = match.group(5) if match.group(5) else ''
if len(versionAlphaBeta) > 0:
if match.group(6) == 'beta':
versionBeta = True
else:

View File

@@ -1,7 +1,7 @@
AppVersion 3000005
AppVersionStrMajor 3.0
AppVersionStrSmall 3.0.5
AppVersionStr 3.0.5
AppVersion 3001003
AppVersionStrMajor 3.1
AppVersionStrSmall 3.1.3
AppVersionStr 3.1.3
BetaChannel 1
AlphaVersion 0
AppVersionOriginal 3.0.5.beta
AppVersionOriginal 3.1.3.beta

View File

@@ -1,3 +1,32 @@
3.1.3 beta (27.09.21)
- Fix illegal instruction crash in opus encoder.
3.1.2 beta (26.09.21)
- Control video in fullscreen mode using arrows and numbers.
- Open locations in browser if default Bing Maps is not installed.
- Reconnect without timeout when network availability changes.
- Crash fixes.
3.1.1 (24.09.21)
- Crash fixes.
3.1 (19.09.21)
- Some animated emoji now have extra effects.
- Send :fireworks: :tada:, :balloon:, :like:, :poop: or :heart: to any private chat, then click on the animated emoji to launch the effect.
- If your chat partner also has the chat open, you will both see the effects.
- See the "Watching" status when your chat partner is enjoying emoji effects with you.
- More interactive emoji coming soon.
- Right click one of your outgoing messages in small groups to see who recently viewed it.
- To protect privacy, read receipts are only stored for 7 days after the message was sent.
- Record video and audio from live broadcasts in your group or channel.
- Admins can start recording from the '...' menu.
- Choose between recording in portrait or landscape orientation.
- Finished recordings are sent to the admin's Saved Messages and can be easily shared.
3.0.5 beta (17.09.21)
- Add support for Emoji 13.1.

2
cmake

Submodule cmake updated: 3c8e9a0c75...1dacc0ac4f

View File

@@ -42,7 +42,16 @@ apps:
slots:
- tdesktop-mpris
hooks:
configure:
command-chain:
- bin/hooks-configure-desktop
plugs:
- desktop
plugs:
desktop:
mount-host-font-cache: false
# Support for common GTK themes
# https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235
gsettings:
@@ -134,7 +143,7 @@ parts:
snapcraftctl set-version "$version"
sed -i 's|^Icon=.*|Icon=${SNAP}/meta/gui/icon.png|g' lib/xdg/telegramdesktop.desktop
sed -i 's|^Icon=telegram$|Icon=${SNAP}/meta/gui/icon.png|g' lib/xdg/telegramdesktop.desktop
override-build: |
snapcraftctl build
rm -rf "$SNAPCRAFT_PART_INSTALL/usr/share/icons"