Compare commits

..

55 Commits

Author SHA1 Message Date
John Preston
ede4c0f781 Beta version 3.3.1.
- Switch between contacts list sorting modes.
- Sort contacts list by last seen time by default.
- Fix disappearing Send As Channel button after message editing.
- Fix file upload cancelling.
- Fix crash in video capture on macOS.
- Fix labels in the About box.
- Use Qt 6.2.2 for macOS and Linux builds.
- Allow installing x64 Windows version on Windows ARM.
2021-12-23 00:07:26 +00:00
John Preston
75337ad1c2 Fix shared media list in migrated groups. 2021-12-23 00:07:26 +00:00
John Preston
e05b2f3b38 Fix build on Linux. 2021-12-22 17:32:35 +00:00
John Preston
0f15adb208 Sort contacts by last seen by default.
Fixes #5515.
2021-12-22 15:14:16 +00:00
John Preston
a7e552ccab Fix assertion violation in media overview.
Regression was introduced in 5e7e7eaa83.
2021-12-22 13:05:54 +00:00
John Preston
797433ebe9 Fix disappearing Send As Channel button.
Fixes #17359.
2021-12-22 12:32:09 +00:00
John Preston
633532b88d Fix build on Windows. 2021-12-22 11:47:17 +00:00
John Preston
a0dcade9d8 Remove redundant freedesktop.org.xml. 2021-12-22 10:42:32 +00:00
John Preston
2a0babe5ab Fix file upload cancelling.
Fixes #17408.
2021-12-22 10:34:00 +00:00
23rd
dd92f7fb9d Slightly refactored AddContactBox. 2021-12-22 10:27:43 +00:00
John Preston
7ad08b3ef8 Update submodules. 2021-12-22 10:23:54 +00:00
John Preston
73917e8a4b Re-apply crash fix on macOS video capture. 2021-12-22 10:17:50 +00:00
Ilya Fedin
dc7aef3f86 Move HFLAGS to other variables in Dockerfile 2021-12-22 14:15:48 +04:00
Ilya Fedin
d89597bf64 Activate crl dispatch backend on Linux
Linux is the only platform where slow QThreadPool is used, let's use dispatch here as well
2021-12-22 14:15:48 +04:00
Magnus Groß
c2b2d0a92a Do not destroy drag after launchDrag()
On X11 we need to keep the QDrag around a little longer.

Right now, drag is scoped local to launchDrag() and will be destroyed
immediately when launchDrag() finishes. However for X11 we must keep the
drag object alive a little longer. It may only be destroyed once the
drag operation has been accepted by another window, otherwise drag and
drop is broken on Linux and no action happens when something is dragged
from Telegram into another window.

This is because there is still communication happening in the XDND
protocol once QDrag::exec() finishes. See the documentation for
reference: https://freedesktop.org/wiki/Specifications/XDND/

Fixes #17291
2021-12-22 14:15:36 +04:00
John Preston
b341dddbb9 Move macOS and Linux builds to Qt 6.2.2. 2021-12-22 10:13:31 +00:00
John Preston
999e4264c5 Move macOS and Linux builds to Qt 6.2.2. 2021-12-22 10:13:29 +00:00
John Preston
aee11469c4 Fix crash in video capture on macOS.
Fixes #17420.
2021-12-22 10:11:57 +00:00
John Preston
651cfe5b7e Fix about box text labels layout. 2021-12-22 10:11:57 +00:00
John Preston
a34b2a5472 Fix build with DESKTOP_APP_USE_PACKAGED_RLOTTIE. 2021-12-22 10:11:57 +00:00
John Preston
5e7e7eaa83 FullMsgId rely on PeerId instead of ChannelId. 2021-12-22 10:11:57 +00:00
Ilya Fedin
a8f05a01ed Build kwayland as external project
This will simplify packaged Qt 6 build
2021-12-22 14:09:32 +04:00
Ilya Fedin
fedd21b0a6 Use QFontMetrics::height in PreLaunchWindow 2021-12-22 14:08:22 +04:00
Ilya Fedin
7ff7473db6 Auto-check for many instance
This option was invented when single instance check wasn't adapted for -workdir. Now, -workdir can work without -many and this option is redudant, but auto-update prevention is helpful. Let's autodetect whether the binary is already running with a lock file.
2021-12-22 14:07:22 +04:00
Vitaly Zaitsev
d89aab08bf Fixed build against OpenSSL 3.0.
Deprecated function FIPS_mode_set() was removed in OpenSSL 3.0.

Switched to EVP_default_properties_enable_fips() as described in OpenSSL
3.0 migration guide.

Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
2021-12-19 16:35:13 +04:00
Ilya Fedin
b2fb5424ed Get rid of deprecated OpenSSL <1.1 functions 2021-12-16 13:05:53 +04:00
John Preston
e7e34d50ba Fix building on Windows. 2021-12-14 16:27:57 +04:00
John Preston
19320cc5d8 Fix dependencies build on M1. 2021-12-14 11:33:59 +04:00
k1ee
107a87c7ce Add support to build on M1 Mac
On M1 mac, some dependencies build two `arm64` builds and makes `lipo` fail.
2021-12-14 11:32:13 +04:00
RadRussianRus
2cb1d2c0bc Removed explicit definition of cmake generator
Even though TDesktop build migrated to VS 2022, dependencies script still had "Visual Studio 16 2019" for mozjpeg and openal-soft as a generator. Removing these lines allows to use latest Visual Studio without changing the script.
2021-12-13 14:26:05 +04:00
Ilya Fedin
48ab88a9ca Don't use QPlatformNativeInterface for native window handle on Windows 2021-12-13 14:24:34 +04:00
Ilya Fedin
33b7ac209e Don't use QPlatformNativeInterface-based XCB::GetRootWindowFromQt 2021-12-13 14:24:34 +04:00
Ilya Fedin
4a0ffdc9f5 Result binary shouldn't be in bin subfolder with any generator on macOS
Since MACOSX_BUNDLE is used
2021-12-11 07:29:02 +04:00
Ilya Fedin
1ec2c16d27 Fix path to result binary in Linux action 2021-12-11 07:29:02 +04:00
John Preston
4b03fd0f23 Version 3.3: Fix build with GCC. 2021-12-08 08:35:03 +04:00
John Preston
9f117cd680 Version 3.3: Update submodules. 2021-12-07 16:29:38 +04:00
John Preston
f6d29991d6 Version 3.3.
- Content creators can restrict the ability to save media
and forward messages from their groups and channels.
- Clear messages in one-on-one chats from a specific day or date range.
- Comment as one of your channels in public groups and channel comments.
- When you request to join a community and its admin
or bot-admin contacts you with a message,
you will see which chat they are from at the top of the chat.
- Bot-admins can now ask users to complete tasks
before they are allowed to join - like accepting community rules,
passing a test, or making a donation to the content creators.
2021-12-07 15:52:33 +04:00
John Preston
1a0d430291 Fix crash in admin log right click.
Fixes #17325.
2021-12-07 15:42:30 +04:00
John Preston
e3b9927faa Reset session on receiving a really old msgId. 2021-12-07 10:05:41 +04:00
John Preston
d199e16a6e Load cloud image without active view only once. 2021-12-07 10:01:56 +04:00
John Preston
01c2be3f01 Add some checks for actions in a locked state. 2021-12-07 10:01:56 +04:00
Ilya Fedin
6db537d1ec Rename telegramdesktop.appdata.xml -> telegramdesktop.metainfo.xml
.appinfo.xml is legacy according to https://freedesktop.org/software/appstream/docs/chap-Metadata.html#spec-component-location
2021-12-06 11:53:28 +04:00
John Preston
e708b2d39c Move some icons, fix verified check scaling. 2021-12-03 15:30:40 +04:00
John Preston
ebd9587821 Fix admin ranks in participants edit. 2021-12-03 15:02:45 +04:00
John Preston
9e5117d336 Respect autodownload settings in reply previews. 2021-12-03 14:59:08 +04:00
John Preston
1c2ea8d84a Fix semi-transparent inline result thumbnails. 2021-12-02 16:03:13 +04:00
John Preston
235484b719 Fix saving group type without changing username. 2021-12-02 15:26:58 +04:00
John Preston
b9ea5718a2 Fix "about request admin panel" box hiding. 2021-12-02 15:00:27 +04:00
John Preston
db0c57a186 Fix reply-to-media timestamps in captions. 2021-12-02 14:42:50 +04:00
John Preston
0fa458737a Fix shared media loading. 2021-12-02 13:54:30 +04:00
John Preston
caaeff32c5 Move global privacy setting down. 2021-12-02 13:36:49 +04:00
John Preston
c4c234f0d3 Pass FilterId to pinnedIndexChanged. 2021-12-02 13:36:49 +04:00
John Preston
894e7c5828 Fix imported messages without a sender name. 2021-12-02 13:36:49 +04:00
John Preston
afcebb136c Don't use MTP for PeerData::isSelf. 2021-12-02 13:36:49 +04:00
Ilya Fedin
8592326a3c Revert "Use kernel accelerated sendfile to copy files on Linux"
This reverts commit 34534a9653.
2021-12-02 09:15:23 +04:00
210 changed files with 1121 additions and 35212 deletions

View File

@@ -107,7 +107,7 @@ jobs:
- name: Check.
run: |
filePath="$REPO_NAME/out/Debug/bin/Telegram"
filePath="$REPO_NAME/out/Debug/Telegram"
if test -f "$filePath"; then
echo "Build successfully done! :)"
@@ -121,7 +121,7 @@ jobs:
- name: Move artifact.
if: env.UPLOAD_ARTIFACT == 'true'
run: |
cd $REPO_NAME/out/Debug/bin
cd $REPO_NAME/out/Debug
mkdir artifact
mv Telegram artifact/
- uses: actions/upload-artifact@master
@@ -129,4 +129,4 @@ jobs:
name: Upload artifact.
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.REPO_NAME }}/out/Debug/bin/artifact/
path: ${{ env.REPO_NAME }}/out/Debug/artifact/

6
.gitmodules vendored
View File

@@ -94,3 +94,9 @@
[submodule "Telegram/ThirdParty/jemalloc"]
path = Telegram/ThirdParty/jemalloc
url = https://github.com/jemalloc/jemalloc
[submodule "Telegram/ThirdParty/kwayland"]
path = Telegram/ThirdParty/kwayland
url = https://github.com/KDE/kwayland.git
[submodule "Telegram/ThirdParty/dispatch"]
path = Telegram/ThirdParty/dispatch
url = https://github.com/apple/swift-corelibs-libdispatch

View File

@@ -1407,7 +1407,7 @@ PRIVATE
G_LOG_DOMAIN="Telegram"
)
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode"
if (APPLE
OR "${CMAKE_GENERATOR}" STREQUAL "Ninja Multi-Config"
OR NOT CMAKE_EXECUTABLE_SUFFIX STREQUAL ""
OR NOT "${output_name}" STREQUAL "Telegram")
@@ -1526,8 +1526,8 @@ endif()
if (LINUX AND DESKTOP_APP_USE_PACKAGED)
include(GNUInstallDirs)
configure_file("../lib/xdg/telegramdesktop.appdata.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.appdata.xml" @ONLY)
generate_appdata_changelog(Telegram "${CMAKE_SOURCE_DIR}/changelog.txt" "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.appdata.xml")
configure_file("../lib/xdg/telegramdesktop.metainfo.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.metainfo.xml" @ONLY)
generate_appdata_changelog(Telegram "${CMAKE_SOURCE_DIR}/changelog.txt" "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.metainfo.xml")
install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "telegram.png")
@@ -1537,5 +1537,5 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED)
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png")
install(FILES "../lib/xdg/telegramdesktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.desktop")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.appdata.xml")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/telegramdesktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.metainfo.xml")
endif()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

View File

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 277 B

View File

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 482 B

View File

Before

Width:  |  Height:  |  Size: 715 B

After

Width:  |  Height:  |  Size: 715 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 255 B

View File

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 344 B

View File

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 197 B

View File

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 273 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 253 B

After

Width:  |  Height:  |  Size: 253 B

View File

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 433 B

View File

Before

Width:  |  Height:  |  Size: 494 B

After

Width:  |  Height:  |  Size: 494 B

View File

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 265 B

View File

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 490 B

View File

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 578 B

View File

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 285 B

View File

Before

Width:  |  Height:  |  Size: 444 B

After

Width:  |  Height:  |  Size: 444 B

View File

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

View File

Before

Width:  |  Height:  |  Size: 128 B

After

Width:  |  Height:  |  Size: 128 B

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

View File

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 146 B

View File

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 170 B

After

Width:  |  Height:  |  Size: 170 B

View File

Before

Width:  |  Height:  |  Size: 362 B

After

Width:  |  Height:  |  Size: 362 B

View File

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 488 B

View File

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 387 B

View File

Before

Width:  |  Height:  |  Size: 638 B

After

Width:  |  Height:  |  Size: 638 B

View File

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 907 B

View File

Before

Width:  |  Height:  |  Size: 158 B

After

Width:  |  Height:  |  Size: 158 B

View File

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 309 B

View File

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 321 B

View File

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 367 B

View File

Before

Width:  |  Height:  |  Size: 1013 B

After

Width:  |  Height:  |  Size: 1013 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 223 B

View File

Before

Width:  |  Height:  |  Size: 432 B

After

Width:  |  Height:  |  Size: 432 B

View File

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 512 B

View File

Before

Width:  |  Height:  |  Size: 145 B

After

Width:  |  Height:  |  Size: 145 B

View File

Before

Width:  |  Height:  |  Size: 261 B

After

Width:  |  Height:  |  Size: 261 B

View File

Before

Width:  |  Height:  |  Size: 272 B

After

Width:  |  Height:  |  Size: 272 B

View File

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View File

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 450 B

View File

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 694 B

File diff suppressed because it is too large Load Diff

View File

@@ -83,9 +83,6 @@
<file alias="settings/devices/device_web_firefox.lottie">../../icons/settings/devices/device_web_firefox.lottie</file>
<file alias="settings/devices/device_web_safari.lottie">../../icons/settings/devices/device_web_safari.lottie</file>
</qresource>
<qresource prefix="/qt-project.org">
<file>../qmime/freedesktop.org.xml</file>
</qresource>
<qresource prefix="/misc">
<file alias="default_shortcuts-custom.json">../../default_shortcuts-custom.json</file>
<file alias="telegramdesktop.desktop">../../../../lib/xdg/telegramdesktop.desktop</file>

View File

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

View File

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

View File

@@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/sendfile.h>
#include <cstdlib>
#include <unistd.h>
#include <dirent.h>
@@ -98,6 +97,11 @@ bool copyFile(const char *from, const char *to, bool writeprotected) {
fclose(ffrom);
return false;
}
static const int BufSize = 65536;
char buf[BufSize];
while (size_t size = fread(buf, 1, BufSize, ffrom)) {
fwrite(buf, 1, size, fto);
}
struct stat fst; // from http://stackoverflow.com/questions/5486774/keeping-fileowner-and-permissions-after-copying-file-in-c
//let's say this wont fail since you already worked OK on that fp
@@ -106,33 +110,6 @@ bool copyFile(const char *from, const char *to, bool writeprotected) {
fclose(fto);
return false;
}
ssize_t copied = sendfile(
fileno(fto),
fileno(ffrom),
nullptr,
fst.st_size);
if (copied == -1) {
writeLog(
"Copy by sendfile '%s' to '%s' failed, error: %d, fallback now.",
from,
to,
int(errno));
static const int BufSize = 65536;
char buf[BufSize];
while (size_t size = fread(buf, 1, BufSize, ffrom)) {
fwrite(buf, 1, size, fto);
}
} else {
writeLog(
"Copy by sendfile '%s' to '%s' done, size: %d, result: %d.",
from,
to,
int(fst.st_size),
int(copied));
}
//update to the same uid/gid
if (!writeprotected && fchown(fileno(fto), fst.st_uid, fst.st_gid) != 0) {
fclose(ffrom);

View File

@@ -118,7 +118,7 @@ void PeerPhoto::upload(not_null<PeerData*> peer, QImage &&image) {
std::move(image));
const auto fakeId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto already = ranges::find(
_uploads,

View File

@@ -74,7 +74,7 @@ void SendExistingMedia(
api->sendAction(message.action);
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
@@ -255,7 +255,7 @@ bool SendDice(MessageToSend &message) {
api->sendAction(message.action);
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();
@@ -346,10 +346,8 @@ void SendConfirmedFile(
const std::shared_ptr<FileLoadResult> &file) {
const auto isEditing = (file->type != SendMediaType::Audio)
&& (file->to.replaceMediaOf != 0);
const auto channelId = peerToChannel(file->to.peer);
const auto newId = FullMsgId(
channelId,
file->to.peer,
isEditing
? file->to.replaceMediaOf
: session->data().nextLocalMessageId());

View File

@@ -87,7 +87,7 @@ std::optional<HistoryItem*> SingleMessageSearch::performLookupByChannel(
Expects(!_requestKey.empty());
const auto postId = _requestKey.postId;
if (const auto item = _session->data().message(channel, postId)) {
if (const auto item = _session->data().message(channel->id, postId)) {
_cache.emplace(_requestKey, item->fullId());
return item;
} else if (!ready) {
@@ -112,7 +112,7 @@ std::optional<HistoryItem*> SingleMessageSearch::performLookupByChannel(
&& received.messageIds.front() == postId) {
_cache.emplace(
_requestKey,
FullMsgId(peerToChannel(channel->id), postId));
FullMsgId(channel->id, postId));
ready();
} else {
fail();

View File

@@ -730,7 +730,7 @@ void Updates::addActiveChat(rpl::producer<PeerData*> chat) {
}
void Updates::requestChannelRangeDifference(not_null<History*> history) {
Expects(history->isChannel());
Expects(history->peer->isChannel());
const auto channel = history->peer->asChannel();
if (const auto requestId = _rangeDifferenceRequests.take(channel)) {
@@ -1181,7 +1181,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
const auto &d = update.c_updateReadMessagesContents();
auto possiblyReadMentions = base::flat_set<MsgId>();
for (const auto &msgId : d.vmessages().v) {
if (const auto item = _session->data().message(NoChannel, msgId.v)) {
if (const auto item = _session->data().nonChannelMessage(msgId.v)) {
if (item->isUnreadMedia() || item->isUnreadMention()) {
item->markMediaRead();
_session->data().requestItemRepaint(item);
@@ -1249,7 +1249,7 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updateDeleteMessages: {
auto &d = update.c_updateDeleteMessages();
_session->data().processMessagesDeleted(NoChannel, d.vmessages().v);
_session->data().processNonChannelMessagesDeleted(d.vmessages().v);
} break;
case mtpc_updateNewChannelMessage: {
@@ -1278,9 +1278,9 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updatePinnedChannelMessages: {
const auto &d = update.c_updatePinnedChannelMessages();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
for (const auto &msgId : d.vmessages().v) {
const auto item = session().data().message(channelId, msgId.v);
const auto item = session().data().message(peerId, msgId.v);
if (item) {
item->setIsPinned(d.is_pinned());
}
@@ -1299,13 +1299,16 @@ void Updates::applyUpdateNoPtsCheck(const MTPUpdate &update) {
case mtpc_updateDeleteChannelMessages: {
auto &d = update.c_updateDeleteChannelMessages();
_session->data().processMessagesDeleted(d.vchannel_id().v, d.vmessages().v);
_session->data().processMessagesDeleted(
peerFromChannel(d.vchannel_id().v),
d.vmessages().v);
} break;
case mtpc_updatePinnedMessages: {
const auto &d = update.c_updatePinnedMessages();
const auto peerId = peerFromMTP(d.vpeer());
for (const auto &msgId : d.vmessages().v) {
const auto item = session().data().message(0, msgId.v);
const auto item = session().data().message(peerId, msgId.v);
if (item) {
item->setIsPinned(d.is_pinned());
}
@@ -1424,7 +1427,7 @@ void Updates::applyUpdates(
const auto sent = owner.messageSentData(randomId);
const auto lookupMessage = [&] {
return sent.peerId
? owner.message(peerToChannel(sent.peerId), d.vid().v)
? owner.message(sent.peerId, d.vid().v)
: nullptr;
};
if (const auto id = owner.messageIdByRandomId(randomId)) {
@@ -1439,9 +1442,9 @@ void Updates::applyUpdates(
const auto list = d.ventities();
if (list && !MentionUsersLoaded(&session(), *list)) {
session().api().requestMessageData(
item->history()->peer->asChannel(),
item->history()->peer,
item->id,
ApiWrap::RequestMessageDataCallback());
nullptr);
}
item->applySentMessage(sent.text, d, wasAlready);
}
@@ -1527,9 +1530,8 @@ void Updates::feedUpdate(const MTPUpdate &update) {
if (local->isScheduled()) {
session().data().scheduledMessages().apply(d, local);
} else {
const auto channel = id.channel;
const auto existing = session().data().message(
channel,
id.peer,
newId);
if (existing && !local->mainView()) {
const auto history = local->history();
@@ -1566,7 +1568,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
auto possiblyReadMentions = base::flat_set<MsgId>();
for (const auto &msgId : d.vmessages().v) {
if (auto item = session().data().message(channel, msgId.v)) {
if (auto item = session().data().message(channel->id, msgId.v)) {
if (item->isUnreadMedia() || item->isUnreadMention()) {
item->markMediaRead();
session().data().requestItemRepaint(item);
@@ -2146,24 +2148,26 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateChannelMessageViews: {
const auto &d = update.c_updateChannelMessageViews();
if (const auto item = session().data().message(d.vchannel_id().v, d.vid().v)) {
const auto peerId = peerFromChannel(d.vchannel_id());
if (const auto item = session().data().message(peerId, d.vid().v)) {
item->setViewsCount(d.vviews().v);
}
} break;
case mtpc_updateChannelMessageForwards: {
const auto &d = update.c_updateChannelMessageForwards();
if (const auto item = session().data().message(d.vchannel_id().v, d.vid().v)) {
const auto peerId = peerFromChannel(d.vchannel_id());
if (const auto item = session().data().message(peerId, d.vid().v)) {
item->setForwardsCount(d.vforwards().v);
}
} break;
case mtpc_updateReadChannelDiscussionInbox: {
const auto &d = update.c_updateReadChannelDiscussionInbox();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
const auto msgId = d.vtop_msg_id().v;
const auto readTillId = d.vread_max_id().v;
const auto item = session().data().message(channelId, msgId);
const auto item = session().data().message(peerId, msgId);
const auto unreadCount = item
? session().data().countUnreadRepliesLocally(item, readTillId)
: std::nullopt;
@@ -2175,7 +2179,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
}
if (const auto broadcastId = d.vbroadcast_id()) {
if (const auto post = session().data().message(
broadcastId->v,
peerFromChannel(*broadcastId),
d.vbroadcast_post()->v)) {
post->setRepliesInboxReadTill(readTillId, unreadCount);
}
@@ -2184,10 +2188,10 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadChannelDiscussionOutbox: {
const auto &d = update.c_updateReadChannelDiscussionOutbox();
const auto channelId = d.vchannel_id().v;
const auto peerId = peerFromChannel(d.vchannel_id());
const auto msgId = d.vtop_msg_id().v;
const auto readTillId = d.vread_max_id().v;
const auto item = session().data().message(channelId, msgId);
const auto item = session().data().message(peerId, msgId);
if (item) {
item->setRepliesOutboxReadTill(readTillId);
if (const auto post = item->lookupDiscussionPostOriginal()) {

View File

@@ -95,9 +95,8 @@ void ViewsManager::done(
if (id != requestId) {
continue;
}
const auto channel = peerToChannel(peer->id);
for (auto j = 0, l = int(ids.size()); j < l; ++j) {
if (const auto item = owner.message(channel, ids[j].v)) {
if (const auto item = owner.message(peer->id, ids[j].v)) {
v[j].match([&](const MTPDmessageViews &data) {
if (const auto views = data.vviews()) {
item->setViewsCount(views->v);

View File

@@ -510,14 +510,14 @@ void ApiWrap::sendMessageFail(
}
void ApiWrap::requestMessageData(
ChannelData *channel,
PeerData *peer,
MsgId msgId,
RequestMessageDataCallback callback) {
auto &requests = channel
? _channelMessageDataRequests[channel][msgId]
Fn<void()> done) {
auto &requests = (peer && peer->isChannel())
? _channelMessageDataRequests[peer->asChannel()][msgId]
: _messageDataRequests[msgId];
if (callback) {
requests.callbacks.push_back(callback);
if (done) {
requests.callbacks.push_back(std::move(done));
}
if (!requests.requestId) {
_messageDataResolveDelayed.call();
@@ -539,19 +539,19 @@ QVector<MTPInputMessage> ApiWrap::collectMessageIds(
auto ApiWrap::messageDataRequests(ChannelData *channel, bool onlyExisting)
-> MessageDataRequests* {
if (channel) {
auto i = _channelMessageDataRequests.find(channel);
if (i == end(_channelMessageDataRequests)) {
if (onlyExisting) {
return nullptr;
}
i = _channelMessageDataRequests.emplace(
channel,
MessageDataRequests()).first;
}
return &i->second;
if (!channel) {
return &_messageDataRequests;
}
return &_messageDataRequests;
const auto i = _channelMessageDataRequests.find(channel);
if (i != end(_channelMessageDataRequests)) {
return &i->second;
} else if (onlyExisting) {
return nullptr;
}
return &_channelMessageDataRequests.emplace(
channel,
MessageDataRequests()
).first->second;
}
void ApiWrap::resolveMessageDatas() {
@@ -614,20 +614,31 @@ void ApiWrap::finalizeMessageDataRequest(
ChannelData *channel,
mtpRequestId requestId) {
auto requests = messageDataRequests(channel, true);
if (requests) {
for (auto i = requests->begin(); i != requests->cend();) {
if (i->second.requestId == requestId) {
for (const auto &callback : i->second.callbacks) {
callback(channel, i->first);
}
i = requests->erase(i);
if (!requests) {
return;
}
auto callbacks = std::vector<Fn<void()>>();
for (auto i = requests->begin(); i != requests->cend();) {
if (i->second.requestId == requestId) {
auto &list = i->second.callbacks;
if (callbacks.empty()) {
callbacks = std::move(list);
} else {
++i;
callbacks.insert(
end(callbacks),
std::make_move_iterator(begin(list)),
std::make_move_iterator(end(list)));
}
i = requests->erase(i);
} else {
++i;
}
if (channel && requests->empty()) {
_channelMessageDataRequests.remove(channel);
}
}
if (channel && requests->empty()) {
_channelMessageDataRequests.remove(channel);
}
for (const auto &callback : callbacks) {
callback();
}
}
@@ -646,7 +657,7 @@ QString ApiWrap::exportDirectMessageLink(
if (inRepliesContext) {
if (const auto rootId = item->replyToTop()) {
const auto root = item->history()->owner().message(
peerToChannel(channel->id),
channel->id,
rootId);
const auto sender = root
? root->discussionPostOriginalSender()
@@ -1388,9 +1399,8 @@ void ApiWrap::deleteAllFromParticipant(
const auto ids = history
? history->collectMessagesFromParticipantToDelete(from)
: std::vector<MsgId>();
const auto channelId = peerToChannel(channel->id);
for (const auto &msgId : ids) {
if (const auto item = _session->data().message(channelId, msgId)) {
if (const auto item = _session->data().message(channel->id, msgId)) {
item->destroy();
}
}
@@ -2225,11 +2235,7 @@ void ApiWrap::resolveWebPages() {
if (i.key()->pendingTill <= t) {
const auto item = _session->data().findWebPageItem(i.key());
if (item) {
if (item->channelId() == NoChannel) {
ids.push_back(MTP_inputMessageID(MTP_int(item->id)));
i.value() = -1;
} else {
auto channel = item->history()->peer->asChannel();
if (const auto channel = item->history()->peer->asChannel()) {
auto channelMap = idsByChannel.find(channel);
if (channelMap == idsByChannel.cend()) {
channelMap = idsByChannel.emplace(
@@ -2244,6 +2250,9 @@ void ApiWrap::resolveWebPages() {
MTP_inputMessageID(MTP_int(item->id)));
}
i.value() = -channelMap->second.first - 2;
} else {
ids.push_back(MTP_inputMessageID(MTP_int(item->id)));
i.value() = -1;
}
}
} else {
@@ -2927,14 +2936,13 @@ void ApiWrap::preloadEnoughUnreadMentions(not_null<History*> history) {
void ApiWrap::checkForUnreadMentions(
const base::flat_set<MsgId> &possiblyReadMentions,
ChannelData *channel) {
for (auto msgId : possiblyReadMentions) {
requestMessageData(channel, msgId, [=](
ChannelData *channel,
MsgId msgId) {
if (const auto item = _session->data().message(channel, msgId)) {
if (item->mentionsMe()) {
item->markMediaRead();
}
for (const auto msgId : possiblyReadMentions) {
requestMessageData(channel, msgId, [=] {
const auto item = channel
? _session->data().message(channel->id, msgId)
: _session->data().nonChannelMessage(msgId);
if (item && item->mentionsMe()) {
item->markMediaRead();
}
});
}
@@ -3206,7 +3214,7 @@ void ApiWrap::forwardMessages(
const auto randomId = base::RandomValue<uint64>();
if (genClientSideMessage) {
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto self = _session->user();
const auto messageFromId = sendAs
@@ -3279,7 +3287,7 @@ void ApiWrap::sendSharedContact(
const auto peer = history->peer;
const auto newId = FullMsgId(
history->channelId(),
peer->id,
_session->data().nextLocalMessageId());
const auto anonymousPost = peer->amAnonymous();
@@ -3505,7 +3513,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
auto randomId = base::RandomValue<uint64>();
@@ -3663,7 +3671,7 @@ void ApiWrap::sendInlineResult(
const auto history = action.history;
const auto peer = history->peer;
const auto newId = FullMsgId(
peerToChannel(peer->id),
peer->id,
_session->data().nextLocalMessageId());
const auto randomId = base::RandomValue<uint64>();

View File

@@ -147,11 +147,7 @@ public:
bool archived,
Fn<void()> callback);
using RequestMessageDataCallback = Fn<void(ChannelData*, MsgId)>;
void requestMessageData(
ChannelData *channel,
MsgId msgId,
RequestMessageDataCallback callback);
void requestMessageData(PeerData *peer, MsgId msgId, Fn<void()> done);
QString exportDirectMessageLink(
not_null<HistoryItem*> item,
bool inRepliesContext);
@@ -365,7 +361,7 @@ public:
private:
struct MessageDataRequest {
using Callbacks = std::vector<RequestMessageDataCallback>;
using Callbacks = std::vector<Fn<void()>>;
mtpRequestId requestId = 0;
Callbacks callbacks;
@@ -520,7 +516,7 @@ private:
MessageDataRequests _messageDataRequests;
base::flat_map<
ChannelData*,
not_null<ChannelData*>,
MessageDataRequests> _channelMessageDataRequests;
SingleQueuedInvokation _messageDataResolveDelayed;

View File

@@ -80,9 +80,15 @@ void AboutBox::prepare() {
void AboutBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
const auto available = width()
- st::boxPadding.left()
- st::boxPadding.right();
_version->moveToLeft(st::boxPadding.left(), st::aboutVersionTop);
_text1->resizeToWidth(available);
_text1->moveToLeft(st::boxPadding.left(), st::aboutTextTop);
_text2->resizeToWidth(available);
_text2->moveToLeft(st::boxPadding.left(), _text1->y() + _text1->height() + st::aboutSkip);
_text3->resizeToWidth(available);
_text3->moveToLeft(st::boxPadding.left(), _text2->y() + _text2->height() + st::aboutSkip);
}

View File

@@ -418,32 +418,34 @@ void AddContactBox::save() {
MTP_string(lastName)))
)).done(crl::guard(this, [=](
const MTPcontacts_ImportedContacts &result) {
result.match([&](const MTPDcontacts_importedContacts &data) {
_session->data().processUsers(data.vusers());
const auto extractUser = [&](const MTPImportedContact &data) {
return data.match([&](const MTPDimportedContact &data) {
return (data.vclient_id().v == _contactId)
? _session->data().userLoaded(data.vuser_id())
: nullptr;
});
};
const auto &list = data.vimported().v;
const auto user = list.isEmpty()
? nullptr
: extractUser(list.front());
if (user) {
if (user->isContact() || user->session().supportMode()) {
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
}
Ui::hideLayer();
} else if (isBoxShown()) {
hideChildren();
_retrying = true;
updateButtons();
update();
}
const auto &data = result.match([](
const auto &data) -> const MTPDcontacts_importedContacts& {
return data;
});
_session->data().processUsers(data.vusers());
const auto extractUser = [&](const MTPImportedContact &data) {
return data.match([&](const MTPDimportedContact &data) {
return (data.vclient_id().v == _contactId)
? _session->data().userLoaded(data.vuser_id())
: nullptr;
});
};
const auto &list = data.vimported().v;
const auto user = list.isEmpty()
? nullptr
: extractUser(list.front());
if (user) {
if (user->isContact() || user->session().supportMode()) {
Ui::showPeerHistory(user, ShowAtTheEndMsgId);
}
Ui::hideLayer();
} else if (isBoxShown()) {
hideChildren();
_retrying = true;
updateButtons();
update();
}
})).send();
}

View File

@@ -160,6 +160,21 @@ contactsAboutFg: windowSubTextFgOver;
contactsAboutTop: 60px;
contactsAboutBottom: 19px;
contactsSortButton: IconButton(defaultIconButton) {
width: 48px;
height: 54px;
icon: icon{{ "contacts_alphabet", boxTitleCloseFg }};
iconOver: icon{{ "contacts_alphabet", boxTitleCloseFgOver }};
iconPosition: point(10px, -1px);
rippleAreaPosition: point(1px, 6px);
rippleAreaSize: 42px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
}
contactsSortOnlineIcon: icon{{ "contacts_online", boxTitleCloseFg }};
contactsSortOnlineIconOver: icon{{ "contacts_online", boxTitleCloseFgOver }};
contactsMarginTop: 4px;
contactsMarginBottom: 4px;
membersMarginTop: 10px;

View File

@@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_folder.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "apiwrap.h"
#include "mainwidget.h"
#include "mainwindow.h"
@@ -26,12 +27,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "dialogs/dialogs_main_list.h"
#include "window/window_session_controller.h" // showAddContact()
#include "base/unixtime.h"
#include "facades.h"
#include "styles/style_boxes.h"
#include "styles/style_profile.h"
namespace {
constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = chat->owner().history(chat);
auto &histories = history->owner().histories();
@@ -110,17 +114,31 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
object_ptr<Ui::BoxContent> PrepareContactsBox(
not_null<Window::SessionController*> sessionController) {
const auto controller = sessionController;
auto delegate = [=](not_null<PeerListBox*> box) {
using Mode = ContactsBoxController::SortMode;
auto controller = std::make_unique<ContactsBoxController>(
&sessionController->session());
const auto raw = controller.get();
auto init = [=](not_null<PeerListBox*> box) {
struct State {
QPointer<Ui::IconButton> toggleSort;
Mode mode = ContactsBoxController::SortMode::Online;
};
const auto state = box->lifetime().make_state<State>();
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
box->addLeftButton(
tr::lng_profile_add_contact(),
[=] { controller->showAddContact(); });
[=] { sessionController->showAddContact(); });
state->toggleSort = box->addTopButton(st::contactsSortButton, [=] {
const auto online = (state->mode == Mode::Online);
state->mode = online ? Mode::Alphabet : Mode::Online;
raw->setSortMode(state->mode);
state->toggleSort->setIconOverride(
online ? &st::contactsSortOnlineIcon : nullptr,
online ? &st::contactsSortOnlineIconOver : nullptr);
});
raw->setSortMode(Mode::Online);
};
return Box<PeerListBox>(
std::make_unique<ContactsBoxController>(
&sessionController->session()),
std::move(delegate));
return Box<PeerListBox>(std::move(controller), std::move(init));
}
void PeerListRowWithLink::setActionLink(const QString &action) {
@@ -368,7 +386,8 @@ ContactsBoxController::ContactsBoxController(
not_null<Main::Session*> session,
std::unique_ptr<PeerListSearchController> searchController)
: PeerListController(std::move(searchController))
, _session(session) {
, _session(session)
, _sortByOnlineTimer([=] { sort(); }) {
}
Main::Session &ContactsBoxController::session() const {
@@ -404,6 +423,7 @@ void ContactsBoxController::rebuildRows() {
};
appendList(session().data().contactsList());
checkForEmptyRows();
sort();
delegate()->peerListRefreshRows();
}
@@ -427,6 +447,66 @@ void ContactsBoxController::rowClicked(not_null<PeerListRow*> row) {
Ui::showPeerHistory(row->peer(), ShowAtUnreadMsgId);
}
void ContactsBoxController::setSortMode(SortMode mode) {
if (_sortMode == mode) {
return;
}
_sortMode = mode;
sort();
if (_sortMode == SortMode::Online) {
session().changes().peerUpdates(
Data::PeerUpdate::Flag::OnlineStatus
) | rpl::filter([=](const Data::PeerUpdate &update) {
return !_sortByOnlineTimer.isActive()
&& delegate()->peerListFindRow(update.peer->id.value);
}) | rpl::start_with_next([=] {
_sortByOnlineTimer.callOnce(kSortByOnlineThrottle);
}, _sortByOnlineLifetime);
} else {
_sortByOnlineTimer.cancel();
_sortByOnlineLifetime.destroy();
}
}
void ContactsBoxController::sort() {
switch (_sortMode) {
case SortMode::Alphabet: sortByName(); break;
case SortMode::Online: sortByOnline(); break;
default: Unexpected("SortMode in ContactsBoxController.");
}
}
void ContactsBoxController::sortByName() {
auto keys = base::flat_map<PeerListRowId, QString>();
keys.reserve(delegate()->peerListFullRowsCount());
const auto key = [&](const PeerListRow &row) {
const auto id = row.id();
const auto i = keys.find(id);
if (i != end(keys)) {
return i->second;
}
const auto peer = row.peer();
const auto history = peer->owner().history(peer);
return keys.emplace(id, history->chatListNameSortKey()).first->second;
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return (key(a).compare(key(b)) < 0);
};
delegate()->peerListSortRows(predicate);
}
void ContactsBoxController::sortByOnline() {
const auto now = base::unixtime::now();
const auto key = [&](const PeerListRow &row) {
const auto user = row.peer()->asUser();
return user ? (std::min(user->onlineTill, now) + 1) : TimeId();
};
const auto predicate = [&](const PeerListRow &a, const PeerListRow &b) {
return key(a) > key(b);
};
delegate()->peerListSortRows(predicate);
}
bool ContactsBoxController::appendRow(not_null<UserData*> user) {
if (auto row = delegate()->peerListFindRow(user->id.value)) {
updateRowHook(row);

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h"
#include "base/flat_set.h"
#include "base/weak_ptr.h"
#include "base/timer.h"
// Not used for now.
//
@@ -136,6 +137,12 @@ public:
not_null<PeerData*> peer) override final;
void rowClicked(not_null<PeerListRow*> row) override;
enum class SortMode {
Alphabet,
Online,
};
void setSortMode(SortMode mode);
protected:
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
virtual void prepareViewHook() {
@@ -144,11 +151,17 @@ protected:
}
private:
void sort();
void sortByName();
void sortByOnline();
void rebuildRows();
void checkForEmptyRows();
bool appendRow(not_null<UserData*> user);
const not_null<Main::Session*> _session;
SortMode _sortMode = SortMode::Alphabet;
base::Timer _sortByOnlineTimer;
rpl::lifetime _sortByOnlineLifetime;
};

View File

@@ -662,7 +662,7 @@ UserData *ParticipantsAdditionalData::applyCreator(
} else {
_adminCanEdit.erase(user);
}
if (data.rank().isEmpty()) {
if (!data.rank().isEmpty()) {
_adminRanks[user] = data.rank();
} else {
_adminRanks.remove(user);
@@ -693,7 +693,7 @@ UserData *ParticipantsAdditionalData::applyAdmin(
} else {
_adminCanEdit.erase(user);
}
if (data.rank().isEmpty()) {
if (!data.rank().isEmpty()) {
_adminRanks[user] = data.rank();
} else {
_adminRanks.remove(user);

View File

@@ -78,8 +78,8 @@ public:
: tr::lng_manage_peer_channel_type();
}
[[nodiscard]] bool isAllowSave() {
return _isAllowSave;
[[nodiscard]] bool goodUsername() const {
return _goodUsername;
}
[[nodiscard]] Privacy getPrivacy() const {
@@ -144,7 +144,7 @@ private:
bool _useLocationPhrases = false;
bool _isGroup = false;
bool _isAllowSave = false;
bool _goodUsername = false;
base::unique_qptr<Ui::VerticalLayout> _wrap;
base::Timer _checkUsernameTimer;
@@ -171,7 +171,8 @@ Controller::Controller(
, _noForwardsSavedValue(noForwardsSavedValue)
, _useLocationPhrases(useLocationPhrases)
, _isGroup(_peer->isChat() || _peer->isMegagroup())
, _isAllowSave(!_usernameSavedValue.value_or(QString()).isEmpty())
, _goodUsername(!_usernameSavedValue.value_or(
_peer->isChannel() ? _peer->asChannel()->username : QString()).isEmpty())
, _wrap(container)
, _checkUsernameTimer([=] { checkUsernameAvailability(); }) {
_peer->updateFull();
@@ -236,7 +237,8 @@ void Controller::createContent() {
if (_controls.privacy->value() == Privacy::NoUsername) {
checkUsernameAvailability();
}
const auto forShowing = _privacySavedValue.value_or(Privacy::NoUsername);
const auto forShowing = _privacySavedValue.value_or(
Privacy::NoUsername);
_controls.inviteLinkWrap->toggle(
(forShowing != Privacy::HasUsername),
anim::type::instant);
@@ -333,8 +335,8 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
Expects(_wrap != nullptr);
const auto channel = _peer->asChannel();
const auto username =
_usernameSavedValue.value_or(channel ? channel->username : QString());
const auto username = _usernameSavedValue.value_or(
channel ? channel->username : QString());
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_wrap,
@@ -505,7 +507,7 @@ void Controller::askUsernameRevoke() {
}
void Controller::usernameChanged() {
_isAllowSave = false;
_goodUsername = false;
const auto username = getUsernameInput();
if (username.isEmpty()) {
_controls.usernameResult = nullptr;
@@ -529,12 +531,12 @@ void Controller::usernameChanged() {
}
void Controller::showUsernameError(rpl::producer<QString> &&error) {
_isAllowSave = false;
_goodUsername = false;
showUsernameResult(std::move(error), &st::editPeerUsernameError);
}
void Controller::showUsernameGood() {
_isAllowSave = true;
_goodUsername = true;
showUsernameResult(
tr::lng_create_channel_link_available(),
&st::editPeerUsernameGood);
@@ -655,7 +657,7 @@ void EditPeerTypeBox::prepare() {
if (_savedCallback.has_value()) {
addButton(tr::lng_settings_save(), [=] {
const auto v = controller->getPrivacy();
if (!controller->isAllowSave() && (v == Privacy::HasUsername)) {
if ((v == Privacy::HasUsername) && !controller->goodUsername()) {
controller->setFocusUsername();
return;
}

View File

@@ -26,9 +26,9 @@ namespace {
if (!top) {
return false;
} else if (peer == migrated) {
return top.channel || (id < top.msg);
return peerIsChannel(top.peer) || (id < top.msg);
} else if (migrated) {
return top.channel && (id < top.msg);
return peerIsChannel(top.peer) && (id < top.msg);
} else {
return (id < top.msg);
}

View File

@@ -550,11 +550,6 @@ QRect Row::elementGeometry(int element, int outerWidth) const {
const auto size = QSize(
st::sessionTerminate.width,
st::sessionTerminate.height);
const auto margins = QMargins(
0,
(st::sessionListItem.height - size.height()) / 2,
st::sessionListThreeDotsSkip,
0);
const auto right = st::sessionTerminateSkip;
const auto top = st::sessionTerminateTop;
const auto left = outerWidth - right - size.width();

View File

@@ -1105,12 +1105,14 @@ QString AppendShareGameScoreUrl(
const FullMsgId &fullId) {
auto shareHashData = QByteArray(0x20, Qt::Uninitialized);
auto shareHashDataInts = reinterpret_cast<uint64*>(shareHashData.data());
auto channel = fullId.channel
? session->data().channelLoaded(fullId.channel)
: static_cast<ChannelData*>(nullptr);
auto channelAccessHash = uint64(channel ? channel->access : 0);
const auto peer = fullId.peer
? session->data().peerLoaded(fullId.peer)
: static_cast<PeerData*>(nullptr);
const auto channelAccessHash = uint64((peer && peer->isChannel())
? peer->asChannel()->access
: 0);
shareHashDataInts[0] = session->userId().bare;
shareHashDataInts[1] = fullId.channel.bare;
shareHashDataInts[1] = fullId.peer.value;
shareHashDataInts[2] = uint64(fullId.msg.bare);
shareHashDataInts[3] = channelAccessHash;
@@ -1190,31 +1192,22 @@ void ShareGameScoreByHash(
return;
}
// Check first 32 bits of channel access hash.
auto channelAccessHash = hashDataInts[3];
//auto channelAccessHashInts = reinterpret_cast<int32*>(&channelAccessHash);
//if (channelAccessHashInts[0] != hashDataInts[3]) {
// Ui::show(Box<Ui::InformBox>(tr::lng_share_wrong_user(tr::now)));
// return;
//}
if (((hashDataInts[1] >> 40) != 0)
|| (!hashDataInts[1] && channelAccessHash)) {
const auto peerId = PeerId(hashDataInts[1]);
const auto channelAccessHash = hashDataInts[3];
if (!peerIsChannel(peerId) && channelAccessHash) {
// If there is no channel id, there should be no channel access_hash.
Ui::show(Box<Ui::InformBox>(tr::lng_share_wrong_user(tr::now)));
return;
}
auto channelId = ChannelId(hashDataInts[1]);
auto msgId = MsgId(int64(hashDataInts[2]));
if (const auto item = session->data().message(channelId, msgId)) {
const auto msgId = MsgId(int64(hashDataInts[2]));
if (const auto item = session->data().message(peerId, msgId)) {
FastShareMessage(item);
} else {
auto resolveMessageAndShareScore = [=](ChannelData *channel) {
session->api().requestMessageData(channel, msgId, [=](
ChannelData *channel,
MsgId msgId) {
if (const auto item = session->data().message(channel, msgId)) {
auto resolveMessageAndShareScore = [=](PeerData *peer) {
session->api().requestMessageData(peer, msgId, [=] {
const auto item = session->data().message(peerId, msgId);
if (item) {
FastShareMessage(item);
} else {
Ui::show(Box<Ui::InformBox>(
@@ -1223,24 +1216,24 @@ void ShareGameScoreByHash(
});
};
const auto channel = channelId
? session->data().channelLoaded(channelId)
const auto peer = peerIsChannel(peerId)
? session->data().peerLoaded(peerId)
: nullptr;
if (channel || !channelId) {
resolveMessageAndShareScore(channel);
if (peer || !peerIsChannel(peerId)) {
resolveMessageAndShareScore(peer);
} else {
session->api().request(MTPchannels_GetChannels(
MTP_vector<MTPInputChannel>(
1,
MTP_inputChannel(
MTP_long(channelId.bare),
MTP_long(peerToChannel(peerId).bare),
MTP_long(channelAccessHash)))
)).done([=](const MTPmessages_Chats &result) {
result.match([&](const auto &data) {
session->data().processChats(data.vchats());
});
if (const auto channel = session->data().channelLoaded(channelId)) {
resolveMessageAndShareScore(channel);
if (const auto peer = session->data().peerLoaded(peerId)) {
resolveMessageAndShareScore(peer);
}
}).send();
}

View File

@@ -245,11 +245,12 @@ bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
return false;
}
if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) {
const auto peerId = to->history()->peer->id;
if (_wasForMsgId == FullMsgId(peerId, to->id) && !force) {
return false;
}
_wasForMsgId = FullMsgId(to->channelId(), to->id);
_wasForMsgId = FullMsgId(peerId, to->id);
auto markupFlags = to->replyKeyboardFlags();
_forceReply = markupFlags & ReplyMarkupFlag::ForceReply;

View File

@@ -164,7 +164,7 @@ void EmojiInteractions::startIncoming(
if (!peer->isUser() || bunch.interactions.empty()) {
return;
}
const auto item = _session->data().message(nullptr, messageId);
const auto item = _session->data().message(peer->id, messageId);
if (!item || !item->isRegular()) {
return;
}

View File

@@ -22,109 +22,6 @@ namespace {
std::map<int, const char*> BetaLogs() {
return {
{
2009004,
"- Choose one from dozens of new gorgeous animated backgrounds"
" in Chat Settings > Chat background.\n"
},
{
2009005,
"- Tile chat background patterns horizontally.\n"
"- Fix a rare crash in spellchecker on Windows.\n"
"- Fix animated chat backgrounds in Saved Messages.\n"
"- Fix \"Sorry, group is inaccessible\" message "
"in scheduled voice chats.\n",
},
{
2009013,
"- See unread comments count when scrolling discussions in channels."
},
{
3000002,
"- Check who've seen your message in small groups "
"from the context menu.\n"
"- Enable recording with video in live streams and video chats."
},
{
3000004,
"- Fix a crash when joining video chat or live broadcast.\n"
"- Add a \"Close to Taskbar\" option when tray icon is disabled "
"(Windows and Linux)."
},
{
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."
},
{
3001005,
"- Choose one of 8 new preset themes for any individual private chat.\n"
"- Click on '...' menu > 'Change Colors' to pick a theme.\n"
"- Both chat participants will see the same theme in that chat "
" on all their devices.\n"
"- Each new theme features colorful gradient message bubbles, "
"beautifully animated backgrounds and unique background patterns.\n"
"- All chat themes have day and night versions and will follow "
"your overall dark mode settings.\n"
"- Implement main window rounded corners on Windows 11.\n"
"- Fix audio capture from AirPods on macOS.\n"
},
{
3001006,
"- Show small media previews in chats list.\n"
"- Show media album previews and caption text in chats list.\n"
"- Add \"Quick Reply\" and \"Mark as Read\" "
"to native Windows notifications.\n"
},
{
3001012,
"- Create special invite links that require admins "
"to approve users before they become members.\n"
"- Admins can view the applicants' profiles and bios "
"by tapping the Join Requests bar at the top of the chat.\n"
"- Add internal labels to your chat's Invite Links "
"to keep them organized.\n"
"- Run natively on Apple Silicon (macOS only).\n"
},
{
3001013,
"- Fix requests to groups / channels processing.\n"
"- Fix internal link previews with View Content button layout.\n"
"- Fix crash in messages search with imported messages results.\n"
"- Don't use fractional system UI scaling on Linux.\n"
"- Fix invite link icons on macOS.\n"
"- Several crash fixes.\n"
},
{
3002006,
"- Try out the new audio player with playlist shuffle and repeat.\n"
@@ -141,6 +38,24 @@ std::map<int, const char*> BetaLogs() {
"- Fix a crash in archived stickers loading.\n"
"- Fix a crash in calls to old Telegram versions.\n"
},
{
3003001,
"- Switch between contacts list sorting modes.\n"
"- Sort contacts list by last seen time by default.\n"
"- Fix disappearing Send As Channel button after message editing.\n"
"- Fix file upload cancelling.\n"
"- Fix crash in video capture on macOS.\n"
"- Fix labels in the About box.\n"
"- Use Qt 6.2.2 for macOS and Linux builds.\n"
"- Allow installing x64 Windows version on Windows ARM.\n"
}
};
};

View File

@@ -43,9 +43,7 @@ PreLaunchWindow::PreLaunchWindow(QString title) {
p.setColor(QPalette::Window, QColor(255, 255, 255));
setPalette(p);
QLabel tmp(this);
tmp.setText(qsl("Tmp"));
_size = tmp.sizeHint().height();
_size = QFontMetrics(QGuiApplication::font()).height();
int paddingVertical = (_size / 2);
int paddingHorizontal = _size;

View File

@@ -460,7 +460,6 @@ void Launcher::processArguments() {
auto parseMap = std::map<QByteArray, KeyFormat> {
{ "-debug" , KeyFormat::NoValues },
{ "-freetype" , KeyFormat::NoValues },
{ "-many" , KeyFormat::NoValues },
{ "-key" , KeyFormat::OneValue },
{ "-autostart" , KeyFormat::NoValues },
{ "-fixprevious" , KeyFormat::NoValues },
@@ -499,7 +498,6 @@ void Launcher::processArguments() {
gUseFreeType = parseResult.contains("-freetype");
gDebugMode = parseResult.contains("-debug");
gManyInstance = parseResult.contains("-many");
gKeyFile = parseResult.value("-key", {}).join(QString()).toLower();
gKeyFile = gKeyFile.replace(QRegularExpression("[^a-z0-9\\-_]"), {});
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart

View File

@@ -439,8 +439,8 @@ bool OpenMediaTimestamp(
const auto parts = base.mid(3).split('_');
const auto documentId = parts.value(0).toULongLong();
const auto itemId = FullMsgId(
parts.value(1).toInt(),
parts.value(2).toInt());
PeerId(parts.value(1).toULongLong()),
MsgId(parts.value(2).toLongLong()));
const auto session = &controller->session();
const auto document = session->data().document(documentId);
session->settings().setMediaLastPlaybackPosition(

View File

@@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h"
#include "app.h"
#include <QtCore/QLockFile>
#include <QtGui/QSessionManager>
#include <QtGui/QScreen>
#include <qpa/qplatformscreen.h>
@@ -99,10 +100,35 @@ int Sandbox::start() {
if (!Core::UpdaterDisabled()) {
_updateChecker = std::make_unique<Core::UpdateChecker>();
}
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 };
hashMd5Hex(d.constData(), d.size(), h);
_localServerName = Platform::SingleInstanceLocalServerName(h);
{
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 };
hashMd5Hex(d.constData(), d.size(), h);
_localServerName = Platform::SingleInstanceLocalServerName(h);
}
{
const auto d = QFile::encodeName(cExeDir() + cExeName());
QByteArray h;
h.resize(32);
hashMd5Hex(d.constData(), d.size(), h.data());
_lockFile = std::make_unique<QLockFile>(QDir::tempPath() + '/' + h + '-' + cGUIDStr());
_lockFile->setStaleLockTime(0);
if (!_lockFile->tryLock() && _launcher->customWorkingDir()) {
// On Windows, QLockFile has problems detecting a stale lock
// if the machine's hostname contains characters outside the US-ASCII character set.
if constexpr (Platform::IsWindows()) {
// QLockFile::removeStaleLockFile returns false on Windows,
// when the application owning the lock is still running.
if (!_lockFile->removeStaleLockFile()) {
gManyInstance = true;
}
} else {
gManyInstance = true;
}
}
}
connect(
&_localSocket,
@@ -149,13 +175,8 @@ int Sandbox::start() {
restartHint,
Qt::DirectConnection);
if (cManyInstance()) {
LOG(("Many instance allowed, starting..."));
singleInstanceChecked();
} else {
LOG(("Connecting local socket to %1...").arg(_localServerName));
_localSocket.connectToServer(_localServerName);
}
LOG(("Connecting local socket to %1...").arg(_localServerName));
_localSocket.connectToServer(_localServerName);
if (QuitOnStartRequested) {
closeApplication();
@@ -339,12 +360,12 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) {
void Sandbox::singleInstanceChecked() {
if (cManyInstance()) {
Logs::multipleInstances();
LOG(("App Info: Detected another instance"));
}
Ui::DisableCustomScaling();
refreshGlobalProxy();
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
if (!Logs::started() || !Logs::instanceChecked()) {
new NotStartedWindow();
return;
}

View File

@@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtNetwork/QLocalSocket>
#include <QtCore/QAbstractNativeEventFilter>
class QLockFile;
namespace Core {
class Launcher;
@@ -119,6 +121,7 @@ private:
QLocalServer _localServer;
QLocalSocket _localSocket;
LocalClients _localClients;
std::unique_ptr<QLockFile> _lockFile;
bool _secondInstance = false;
bool _started = false;
static bool QuitOnStartRequested;

Some files were not shown because too many files have changed in this diff Show More