mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-29 05:37:45 +00:00
Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
0943d58ea7
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
@ -390,7 +390,7 @@ jobs:
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone -b 1.16 https://gitlab.freedesktop.org/wayland/wayland
|
||||
git clone -b 1.18.0 https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland
|
||||
./autogen.sh \
|
||||
--enable-static \
|
||||
|
2
.github/workflows/mac.yml
vendored
2
.github/workflows/mac.yml
vendored
@ -411,7 +411,7 @@ jobs:
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/qt-cache
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8.diff') }}
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
- name: Use cached Qt 5.12.8.
|
||||
if: steps.cache-qt.outputs.cache-hit == 'true'
|
||||
run: |
|
||||
|
6
.github/workflows/snap.yml
vendored
6
.github/workflows/snap.yml
vendored
@ -13,7 +13,6 @@ on:
|
||||
- '!.github/workflows/snap.yml'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/ffmpeg.diff'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
@ -33,7 +32,6 @@ on:
|
||||
- '!.github/workflows/snap.yml'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Patches/**'
|
||||
- '!Telegram/Patches/ffmpeg.diff'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
@ -45,13 +43,13 @@ on:
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: Ubuntu 18.04
|
||||
name: Ubuntu 20.04
|
||||
if: >
|
||||
!(github.event_name == 'push'
|
||||
&& contains(github.event.head_commit.message, '[skip ci]'))
|
||||
&& !(github.event_name == 'pull_request'
|
||||
&& github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
|
6
.github/workflows/win.yml
vendored
6
.github/workflows/win.yml
vendored
@ -301,7 +301,7 @@ jobs:
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/Qt-5.12.8
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8.diff') }}
|
||||
key: ${{ runner.OS }}-qt-${{ env.CACHE_KEY }}-${{ hashFiles('**/qtbase_5_12_8/*') }}
|
||||
- name: Configure Qt 5.12.8.
|
||||
if: steps.cache-qt.outputs.cache-hit != 'true'
|
||||
shell: cmd
|
||||
@ -397,7 +397,7 @@ jobs:
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
shell: cmd
|
||||
run: |
|
||||
cd %REPO_NAME%\build\bin
|
||||
cd %REPO_NAME%\out\Debug
|
||||
mkdir artifact
|
||||
move Kotatogram.exe artifact/
|
||||
move Updater.exe artifact/
|
||||
@ -406,4 +406,4 @@ jobs:
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: ${{ env.REPO_NAME }}\build\bin\artifact\
|
||||
path: ${{ env.REPO_NAME }}\out\Debug\artifact\
|
||||
|
@ -1224,7 +1224,7 @@ endif()
|
||||
|
||||
set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
|
||||
|
||||
if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR NOT LINUX) AND NOT build_macstore AND NOT build_winstore)
|
||||
if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT build_winstore)
|
||||
add_executable(Updater WIN32)
|
||||
init_target(Updater)
|
||||
|
||||
|
@ -1,225 +0,0 @@
|
||||
diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
|
||||
index 00f93bf59f..52da7036f3 100644
|
||||
--- a/libavcodec/aarch64/Makefile
|
||||
+++ b/libavcodec/aarch64/Makefile
|
||||
@@ -6,6 +6,7 @@ OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o
|
||||
OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o
|
||||
OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o
|
||||
OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o
|
||||
+OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o
|
||||
OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o
|
||||
OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o
|
||||
OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp_init.o
|
||||
@@ -21,6 +22,7 @@ OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_init_aarch64.o
|
||||
OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o
|
||||
OBJS-$(CONFIG_VP9_DECODER) += aarch64/vp9dsp_init_10bpp_aarch64.o \
|
||||
aarch64/vp9dsp_init_12bpp_aarch64.o \
|
||||
+ aarch64/vp9mc_aarch64.o \
|
||||
aarch64/vp9dsp_init_aarch64.o
|
||||
|
||||
# ARMv8 optimizations
|
||||
@@ -41,8 +43,7 @@ NEON-OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_neon.o
|
||||
NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \
|
||||
aarch64/hpeldsp_neon.o
|
||||
NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o
|
||||
-NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o \
|
||||
- aarch64/simple_idct_neon.o
|
||||
+NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o
|
||||
NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o
|
||||
NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o
|
||||
NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o
|
||||
diff --git a/libavcodec/aarch64/idctdsp_init_aarch64.c b/libavcodec/aarch64/idctdsp_init_aarch64.c
|
||||
index 0406e60830..742a3372e3 100644
|
||||
--- a/libavcodec/aarch64/idctdsp_init_aarch64.c
|
||||
+++ b/libavcodec/aarch64/idctdsp_init_aarch64.c
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
+#include "libavutil/cpu.h"
|
||||
+#include "libavutil/arm/cpu.h"
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavcodec/idctdsp.h"
|
||||
#include "idct.h"
|
||||
@@ -28,7 +30,9 @@
|
||||
av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx,
|
||||
unsigned high_bit_depth)
|
||||
{
|
||||
- if (!avctx->lowres && !high_bit_depth) {
|
||||
+ int cpu_flags = av_get_cpu_flags();
|
||||
+
|
||||
+ if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) {
|
||||
if (avctx->idct_algo == FF_IDCT_AUTO ||
|
||||
avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
|
||||
avctx->idct_algo == FF_IDCT_SIMPLENEON) {
|
||||
diff --git a/libavcodec/aarch64/vp9mc_16bpp_neon.S b/libavcodec/aarch64/vp9mc_16bpp_neon.S
|
||||
index cac6428709..53b372c262 100644
|
||||
--- a/libavcodec/aarch64/vp9mc_16bpp_neon.S
|
||||
+++ b/libavcodec/aarch64/vp9mc_16bpp_neon.S
|
||||
@@ -25,31 +25,6 @@
|
||||
// const uint8_t *ref, ptrdiff_t ref_stride,
|
||||
// int h, int mx, int my);
|
||||
|
||||
-function ff_vp9_copy128_aarch64, export=1
|
||||
-1:
|
||||
- ldp x5, x6, [x2]
|
||||
- ldp x7, x8, [x2, #16]
|
||||
- stp x5, x6, [x0]
|
||||
- ldp x9, x10, [x2, #32]
|
||||
- stp x7, x8, [x0, #16]
|
||||
- subs w4, w4, #1
|
||||
- ldp x11, x12, [x2, #48]
|
||||
- stp x9, x10, [x0, #32]
|
||||
- stp x11, x12, [x0, #48]
|
||||
- ldp x5, x6, [x2, #64]
|
||||
- ldp x7, x8, [x2, #80]
|
||||
- stp x5, x6, [x0, #64]
|
||||
- ldp x9, x10, [x2, #96]
|
||||
- stp x7, x8, [x0, #80]
|
||||
- ldp x11, x12, [x2, #112]
|
||||
- stp x9, x10, [x0, #96]
|
||||
- stp x11, x12, [x0, #112]
|
||||
- add x2, x2, x3
|
||||
- add x0, x0, x1
|
||||
- b.ne 1b
|
||||
- ret
|
||||
-endfunc
|
||||
-
|
||||
function ff_vp9_avg64_16_neon, export=1
|
||||
mov x5, x0
|
||||
sub x1, x1, #64
|
||||
diff --git a/libavcodec/aarch64/vp9mc_aarch64.S b/libavcodec/aarch64/vp9mc_aarch64.S
|
||||
new file mode 100644
|
||||
index 0000000000..f17a8cf04a
|
||||
--- /dev/null
|
||||
+++ b/libavcodec/aarch64/vp9mc_aarch64.S
|
||||
@@ -0,0 +1,81 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 Google Inc.
|
||||
+ *
|
||||
+ * This file is part of FFmpeg.
|
||||
+ *
|
||||
+ * FFmpeg is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU Lesser General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2.1 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * FFmpeg is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * Lesser General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public
|
||||
+ * License along with FFmpeg; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+ */
|
||||
+
|
||||
+#include "libavutil/aarch64/asm.S"
|
||||
+
|
||||
+// All public functions in this file have the following signature:
|
||||
+// typedef void (*vp9_mc_func)(uint8_t *dst, ptrdiff_t dst_stride,
|
||||
+// const uint8_t *ref, ptrdiff_t ref_stride,
|
||||
+// int h, int mx, int my);
|
||||
+
|
||||
+function ff_vp9_copy128_aarch64, export=1
|
||||
+1:
|
||||
+ ldp x5, x6, [x2]
|
||||
+ ldp x7, x8, [x2, #16]
|
||||
+ stp x5, x6, [x0]
|
||||
+ ldp x9, x10, [x2, #32]
|
||||
+ stp x7, x8, [x0, #16]
|
||||
+ subs w4, w4, #1
|
||||
+ ldp x11, x12, [x2, #48]
|
||||
+ stp x9, x10, [x0, #32]
|
||||
+ stp x11, x12, [x0, #48]
|
||||
+ ldp x5, x6, [x2, #64]
|
||||
+ ldp x7, x8, [x2, #80]
|
||||
+ stp x5, x6, [x0, #64]
|
||||
+ ldp x9, x10, [x2, #96]
|
||||
+ stp x7, x8, [x0, #80]
|
||||
+ ldp x11, x12, [x2, #112]
|
||||
+ stp x9, x10, [x0, #96]
|
||||
+ stp x11, x12, [x0, #112]
|
||||
+ add x2, x2, x3
|
||||
+ add x0, x0, x1
|
||||
+ b.ne 1b
|
||||
+ ret
|
||||
+endfunc
|
||||
+
|
||||
+function ff_vp9_copy64_aarch64, export=1
|
||||
+1:
|
||||
+ ldp x5, x6, [x2]
|
||||
+ ldp x7, x8, [x2, #16]
|
||||
+ stp x5, x6, [x0]
|
||||
+ ldp x9, x10, [x2, #32]
|
||||
+ stp x7, x8, [x0, #16]
|
||||
+ subs w4, w4, #1
|
||||
+ ldp x11, x12, [x2, #48]
|
||||
+ stp x9, x10, [x0, #32]
|
||||
+ stp x11, x12, [x0, #48]
|
||||
+ add x2, x2, x3
|
||||
+ add x0, x0, x1
|
||||
+ b.ne 1b
|
||||
+ ret
|
||||
+endfunc
|
||||
+
|
||||
+function ff_vp9_copy32_aarch64, export=1
|
||||
+1:
|
||||
+ ldp x5, x6, [x2]
|
||||
+ ldp x7, x8, [x2, #16]
|
||||
+ stp x5, x6, [x0]
|
||||
+ subs w4, w4, #1
|
||||
+ stp x7, x8, [x0, #16]
|
||||
+ add x2, x2, x3
|
||||
+ add x0, x0, x1
|
||||
+ b.ne 1b
|
||||
+ ret
|
||||
+endfunc
|
||||
diff --git a/libavcodec/aarch64/vp9mc_neon.S b/libavcodec/aarch64/vp9mc_neon.S
|
||||
index f67624ca04..abf2bae9db 100644
|
||||
--- a/libavcodec/aarch64/vp9mc_neon.S
|
||||
+++ b/libavcodec/aarch64/vp9mc_neon.S
|
||||
@@ -25,23 +25,6 @@
|
||||
// const uint8_t *ref, ptrdiff_t ref_stride,
|
||||
// int h, int mx, int my);
|
||||
|
||||
-function ff_vp9_copy64_aarch64, export=1
|
||||
-1:
|
||||
- ldp x5, x6, [x2]
|
||||
- ldp x7, x8, [x2, #16]
|
||||
- stp x5, x6, [x0]
|
||||
- ldp x9, x10, [x2, #32]
|
||||
- stp x7, x8, [x0, #16]
|
||||
- subs w4, w4, #1
|
||||
- ldp x11, x12, [x2, #48]
|
||||
- stp x9, x10, [x0, #32]
|
||||
- stp x11, x12, [x0, #48]
|
||||
- add x2, x2, x3
|
||||
- add x0, x0, x1
|
||||
- b.ne 1b
|
||||
- ret
|
||||
-endfunc
|
||||
-
|
||||
function ff_vp9_avg64_neon, export=1
|
||||
mov x5, x0
|
||||
1:
|
||||
@@ -64,19 +47,6 @@ function ff_vp9_avg64_neon, export=1
|
||||
ret
|
||||
endfunc
|
||||
|
||||
-function ff_vp9_copy32_aarch64, export=1
|
||||
-1:
|
||||
- ldp x5, x6, [x2]
|
||||
- ldp x7, x8, [x2, #16]
|
||||
- stp x5, x6, [x0]
|
||||
- subs w4, w4, #1
|
||||
- stp x7, x8, [x0, #16]
|
||||
- add x2, x2, x3
|
||||
- add x0, x0, x1
|
||||
- b.ne 1b
|
||||
- ret
|
||||
-endfunc
|
||||
-
|
||||
function ff_vp9_avg32_neon, export=1
|
||||
1:
|
||||
ld1 {v2.16b, v3.16b}, [x2], x3
|
@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.1.10.0" />
|
||||
Version="2.1.13.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,10,0
|
||||
PRODUCTVERSION 2,1,10,0
|
||||
FILEVERSION 2,1,13,0
|
||||
PRODUCTVERSION 2,1,13,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram FZ-LLC"
|
||||
VALUE "FileDescription", "Telegram Desktop"
|
||||
VALUE "FileVersion", "2.1.10.0"
|
||||
VALUE "FileVersion", "2.1.13.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.10.0"
|
||||
VALUE "ProductVersion", "2.1.13.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,1,10,0
|
||||
PRODUCTVERSION 2,1,10,0
|
||||
FILEVERSION 2,1,13,0
|
||||
PRODUCTVERSION 2,1,13,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", "2.1.10.0"
|
||||
VALUE "FileVersion", "2.1.13.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.1.10.0"
|
||||
VALUE "ProductVersion", "2.1.13.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -254,7 +254,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
QByteArray inner = f.readAll();
|
||||
stream << name << quint32(inner.size()) << inner;
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#ifdef Q_OS_UNIX
|
||||
stream << (QFileInfo(fullName).isExecutable() ? true : false);
|
||||
#endif
|
||||
}
|
||||
@ -467,10 +467,12 @@ int main(int argc, char *argv[])
|
||||
QString outName(QString("tupdate%1").arg(AlphaVersion ? AlphaVersion : version));
|
||||
#elif defined Q_OS_MAC
|
||||
QString outName((targetosx ? QString("tosxupd%1") : QString("tmacupd%1")).arg(AlphaVersion ? AlphaVersion : version));
|
||||
#elif defined Q_OS_LINUX32
|
||||
#elif defined Q_OS_UNIX
|
||||
#ifndef _LP64
|
||||
QString outName(QString("tlinux32upd%1").arg(AlphaVersion ? AlphaVersion : version));
|
||||
#elif defined Q_OS_LINUX64
|
||||
#else
|
||||
QString outName(QString("tlinuxupd%1").arg(AlphaVersion ? AlphaVersion : version));
|
||||
#endif
|
||||
#else
|
||||
#error Unknown platform!
|
||||
#endif
|
||||
|
@ -93,6 +93,7 @@ void SendExistingMedia(
|
||||
};
|
||||
TextUtilities::Trim(caption);
|
||||
auto sentEntities = EntitiesToMTP(
|
||||
session,
|
||||
caption.entities,
|
||||
ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
|
@ -18,11 +18,13 @@ using namespace TextUtilities;
|
||||
|
||||
} // namespace
|
||||
|
||||
EntitiesInText EntitiesFromMTP(const QVector<MTPMessageEntity> &entities) {
|
||||
EntitiesInText EntitiesFromMTP(
|
||||
Main::Session *session,
|
||||
const QVector<MTPMessageEntity> &entities) {
|
||||
auto result = EntitiesInText();
|
||||
if (!entities.isEmpty()) {
|
||||
result.reserve(entities.size());
|
||||
for_const (auto &entity, entities) {
|
||||
for (const auto &entity : entities) {
|
||||
switch (entity.type()) {
|
||||
case mtpc_messageEntityUrl: { auto &d = entity.c_messageEntityUrl(); result.push_back({ EntityType::Url, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityTextUrl: { auto &d = entity.c_messageEntityTextUrl(); result.push_back({ EntityType::CustomUrl, d.voffset().v, d.vlength().v, Clean(qs(d.vurl())) }); } break;
|
||||
@ -32,28 +34,30 @@ EntitiesInText EntitiesFromMTP(const QVector<MTPMessageEntity> &entities) {
|
||||
case mtpc_messageEntityPhone: break; // Skipping phones.
|
||||
case mtpc_messageEntityMention: { auto &d = entity.c_messageEntityMention(); result.push_back({ EntityType::Mention, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityMentionName: {
|
||||
auto &d = entity.c_messageEntityMentionName();
|
||||
auto data = [&d] {
|
||||
if (auto user = Auth().data().userLoaded(d.vuser_id().v)) {
|
||||
return MentionNameDataFromFields({
|
||||
d.vuser_id().v,
|
||||
user->accessHash() });
|
||||
const auto &d = entity.c_messageEntityMentionName();
|
||||
const auto data = [&] {
|
||||
if (session) {
|
||||
if (const auto user = session->data().userLoaded(d.vuser_id().v)) {
|
||||
return MentionNameDataFromFields({
|
||||
d.vuser_id().v,
|
||||
user->accessHash() });
|
||||
}
|
||||
}
|
||||
return MentionNameDataFromFields(d.vuser_id().v);
|
||||
};
|
||||
result.push_back({ EntityType::MentionName, d.voffset().v, d.vlength().v, data() });
|
||||
}();
|
||||
result.push_back({ EntityType::MentionName, d.voffset().v, d.vlength().v, data });
|
||||
} break;
|
||||
case mtpc_inputMessageEntityMentionName: {
|
||||
auto &d = entity.c_inputMessageEntityMentionName();
|
||||
auto data = ([&d]() -> QString {
|
||||
if (d.vuser_id().type() == mtpc_inputUserSelf) {
|
||||
return MentionNameDataFromFields(Auth().userId());
|
||||
const auto &d = entity.c_inputMessageEntityMentionName();
|
||||
const auto data = [&] {
|
||||
if (session && d.vuser_id().type() == mtpc_inputUserSelf) {
|
||||
return MentionNameDataFromFields(session->userId());
|
||||
} else if (d.vuser_id().type() == mtpc_inputUser) {
|
||||
auto &user = d.vuser_id().c_inputUser();
|
||||
return MentionNameDataFromFields({ user.vuser_id().v, user.vaccess_hash().v });
|
||||
}
|
||||
return QString();
|
||||
})();
|
||||
}();
|
||||
if (!data.isEmpty()) {
|
||||
result.push_back({ EntityType::MentionName, d.voffset().v, d.vlength().v, data });
|
||||
}
|
||||
@ -74,11 +78,12 @@ EntitiesInText EntitiesFromMTP(const QVector<MTPMessageEntity> &entities) {
|
||||
}
|
||||
|
||||
MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
not_null<Main::Session*> session,
|
||||
const EntitiesInText &entities,
|
||||
ConvertOption option) {
|
||||
auto v = QVector<MTPMessageEntity>();
|
||||
v.reserve(entities.size());
|
||||
for_const (auto &entity, entities) {
|
||||
for (const auto &entity : entities) {
|
||||
if (entity.length() <= 0) continue;
|
||||
if (option == ConvertOption::SkipLocal
|
||||
&& entity.type() != EntityType::Bold
|
||||
@ -103,15 +108,15 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
case EntityType::Cashtag: v.push_back(MTP_messageEntityCashtag(offset, length)); break;
|
||||
case EntityType::Mention: v.push_back(MTP_messageEntityMention(offset, length)); break;
|
||||
case EntityType::MentionName: {
|
||||
auto inputUser = ([](const QString &data) -> MTPInputUser {
|
||||
auto inputUser = [&](const QString &data) -> MTPInputUser {
|
||||
auto fields = MentionNameDataToFields(data);
|
||||
if (fields.userId == Auth().userId()) {
|
||||
if (session && fields.userId == session->userId()) {
|
||||
return MTP_inputUserSelf();
|
||||
} else if (fields.userId) {
|
||||
return MTP_inputUser(MTP_int(fields.userId), MTP_long(fields.accessHash));
|
||||
}
|
||||
return MTP_inputUserEmpty();
|
||||
})(entity.data());
|
||||
}(entity.data());
|
||||
if (inputUser.type() != mtpc_inputUserEmpty) {
|
||||
v.push_back(MTP_inputMessageEntityMentionName(offset, length, inputUser));
|
||||
}
|
||||
|
@ -9,14 +9,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "ui/text/text_entity.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Api {
|
||||
|
||||
EntitiesInText EntitiesFromMTP(const QVector<MTPMessageEntity> &entities);
|
||||
enum class ConvertOption {
|
||||
WithLocal,
|
||||
SkipLocal,
|
||||
};
|
||||
MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
|
||||
[[nodiscard]] EntitiesInText EntitiesFromMTP(
|
||||
Main::Session *session,
|
||||
const QVector<MTPMessageEntity> &entities);
|
||||
|
||||
[[nodiscard]] MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
not_null<Main::Session*> session,
|
||||
const EntitiesInText &entities,
|
||||
ConvertOption option = ConvertOption::WithLocal);
|
||||
|
||||
|
@ -411,7 +411,7 @@ void ApiWrap::requestTermsUpdate() {
|
||||
const auto &terms = data.vterms_of_service();
|
||||
const auto &fields = terms.c_help_termsOfService();
|
||||
Core::App().lockByTerms(
|
||||
Window::TermsLock::FromMTP(fields));
|
||||
Window::TermsLock::FromMTP(&session(), fields));
|
||||
requestNext(data);
|
||||
} break;
|
||||
default: Unexpected("Type in requestTermsUpdate().");
|
||||
@ -2442,6 +2442,7 @@ void ApiWrap::saveDraftsToCloud() {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
||||
}
|
||||
auto entities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
TextUtilities::ConvertTextTagsToEntities(textWithTags.tags),
|
||||
Api::ConvertOption::SkipLocal);
|
||||
|
||||
@ -4674,6 +4675,7 @@ void ApiWrap::editUploadedFile(
|
||||
}
|
||||
|
||||
auto sentEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
item->originalText().entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
|
||||
@ -4826,8 +4828,11 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_silent;
|
||||
}
|
||||
auto localEntities = Api::EntitiesToMTP(sending.entities);
|
||||
auto localEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
sending.entities);
|
||||
auto sentEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
sending.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
@ -5118,6 +5123,7 @@ void ApiWrap::sendMediaWithRandomId(
|
||||
auto caption = item->originalText();
|
||||
TextUtilities::Trim(caption);
|
||||
auto sentEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
caption.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
|
||||
@ -5794,6 +5800,7 @@ void ApiWrap::rescheduleMessage(
|
||||
Api::SendOptions options) {
|
||||
const auto text = item->originalText().text;
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
item->originalText().entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
const auto media = item->media();
|
||||
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_document_media.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
@ -327,10 +328,6 @@ EditCaptionBox::EditCaptionBox(
|
||||
) | rpl::start_with_next([&](bool checked) {
|
||||
_asFile = checked;
|
||||
}, _wayWrap->lifetime());
|
||||
|
||||
if (_animated) {
|
||||
prepareStreamedPreview();
|
||||
}
|
||||
}
|
||||
|
||||
EditCaptionBox::~EditCaptionBox() = default;
|
||||
@ -590,6 +587,10 @@ void EditCaptionBox::createEditMediaButton() {
|
||||
}
|
||||
|
||||
void EditCaptionBox::prepare() {
|
||||
if (_animated) {
|
||||
prepareStreamedPreview();
|
||||
}
|
||||
|
||||
addButton(tr::lng_settings_save(), [this] { save(); });
|
||||
if (_isAllowedEditMedia) {
|
||||
createEditMediaButton();
|
||||
@ -656,7 +657,10 @@ bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
|
||||
if (result.error == Error::None) {
|
||||
return result;
|
||||
} else if (data->hasImage()) {
|
||||
auto image = qvariant_cast<QImage>(data->imageData());
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
_isImage = true;
|
||||
_photo = true;
|
||||
@ -934,6 +938,7 @@ void EditCaptionBox::save() {
|
||||
TextUtilities::Trim(sending);
|
||||
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
&item->history()->session(),
|
||||
sending.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/send_files_box.h"
|
||||
|
||||
#include "platform/platform_specific.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
@ -2168,7 +2169,10 @@ bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
|
||||
if (result.error == Storage::PreparedList::Error::None) {
|
||||
return result;
|
||||
} else if (data->hasImage()) {
|
||||
auto image = qvariant_cast<QImage>(data->imageData());
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
return Storage::PrepareMediaFromImage(
|
||||
std::move(image),
|
||||
|
@ -326,7 +326,9 @@ void StickersBox::prepare() {
|
||||
_session->api().updateStickers();
|
||||
|
||||
if (_installed.widget()) {
|
||||
connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));
|
||||
connect(_installed.widget(), &Inner::draggingScrollDelta, [=](int delta) {
|
||||
scrollByDraggingDelta(delta);
|
||||
});
|
||||
if (!_megagroupSet) {
|
||||
boxClosing() | rpl::start_with_next([=] {
|
||||
saveChanges();
|
||||
|
@ -798,13 +798,9 @@ void Application::notifyFileDialogShown(bool shown) {
|
||||
}
|
||||
|
||||
QWidget *Application::getModalParent() {
|
||||
#ifdef Q_OS_LINUX
|
||||
return Platform::IsWayland()
|
||||
? App::wnd()
|
||||
: nullptr;
|
||||
#endif // Q_OS_LINUX
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "client/crashpad_client.h"
|
||||
#endif // else for MAC_USE_BREAKPAD
|
||||
|
||||
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32 // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
@ -47,7 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
|
||||
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
|
||||
#endif // Q_OS_UNIX
|
||||
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
|
||||
@ -140,7 +140,7 @@ QMutex ReportingMutex;
|
||||
const char *BreakpadDumpPath = nullptr;
|
||||
const wchar_t *BreakpadDumpPathW = nullptr;
|
||||
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#ifdef Q_OS_UNIX
|
||||
struct sigaction SIG_def[32];
|
||||
|
||||
void SignalHandler(int signum, siginfo_t *info, void *ucontext) {
|
||||
@ -148,9 +148,9 @@ void SignalHandler(int signum, siginfo_t *info, void *ucontext) {
|
||||
sigaction(signum, &SIG_def[signum], 0);
|
||||
}
|
||||
|
||||
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#else // Q_OS_UNIX
|
||||
void SignalHandler(int signum) {
|
||||
#endif // else for Q_OS_MAC || Q_OS_LINUX || Q_OS_LINUX64
|
||||
#endif // else for Q_OS_UNIX
|
||||
|
||||
const char* name = 0;
|
||||
switch (signum) {
|
||||
@ -212,7 +212,7 @@ void SignalHandler(int signum) {
|
||||
}
|
||||
|
||||
// see https://github.com/benbjohnson/bandicoot
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#ifdef Q_OS_UNIX
|
||||
ucontext_t *uc = (ucontext_t*)ucontext;
|
||||
|
||||
void *caller = 0;
|
||||
@ -276,9 +276,9 @@ void SignalHandler(int signum) {
|
||||
|
||||
backtrace_symbols_fd(addresses, size, ReportFileNo);
|
||||
|
||||
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#else // Q_OS_UNIX
|
||||
dump() << "\nBacktrace omitted.\n";
|
||||
#endif // else for Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // else for Q_OS_UNIX
|
||||
|
||||
dump() << "\n";
|
||||
|
||||
@ -294,9 +294,9 @@ google_breakpad::ExceptionHandler* BreakpadExceptionHandler = 0;
|
||||
bool DumpCallback(const wchar_t* _dump_dir, const wchar_t* _minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool success)
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
bool DumpCallback(const char* _dump_dir, const char* _minidump_id, void *context, bool success)
|
||||
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32 // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context, bool success)
|
||||
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
|
||||
#endif // Q_OS_UNIX
|
||||
{
|
||||
if (CrashLogged) return success;
|
||||
CrashLogged = true;
|
||||
@ -392,7 +392,7 @@ void StartCatching(not_null<Core::Launcher*> launcher) {
|
||||
crashpad_client.UseHandler();
|
||||
}
|
||||
#endif // else for MAC_USE_BREAKPAD
|
||||
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
|
||||
#elif defined Q_OS_UNIX
|
||||
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
|
||||
/*FilterCallback*/ 0,
|
||||
@ -401,7 +401,7 @@ void StartCatching(not_null<Core::Launcher*> launcher) {
|
||||
true,
|
||||
-1
|
||||
);
|
||||
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // !DESKTOP_APP_DISABLE_CRASH_REPORTS
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ void Launcher::init() {
|
||||
|
||||
QApplication::setApplicationName(qsl("KotatogramDesktop"));
|
||||
|
||||
#if defined(Q_OS_LINUX) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
||||
QApplication::setDesktopFileName(Platform::GetLauncherFilename());
|
||||
#endif
|
||||
|
||||
|
@ -392,7 +392,9 @@ bool HandleUnknown(
|
||||
const auto callback = [=](const MTPDhelp_deepLinkInfo &result) {
|
||||
const auto text = TextWithEntities{
|
||||
qs(result.vmessage()),
|
||||
Api::EntitiesFromMTP(result.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(
|
||||
session,
|
||||
result.ventities().value_or_empty())
|
||||
};
|
||||
if (result.is_update_app()) {
|
||||
const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
|
||||
#include <QtGui/QSessionManager>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
namespace Core {
|
||||
@ -84,9 +85,9 @@ Sandbox::Sandbox(
|
||||
: QApplication(argc, argv)
|
||||
, _mainThreadId(QThread::currentThreadId())
|
||||
, _handleObservables([=] {
|
||||
Expects(_application != nullptr);
|
||||
|
||||
_application->call_handleObservables();
|
||||
if (_application) {
|
||||
_application->call_handleObservables();
|
||||
}
|
||||
})
|
||||
, _launcher(launcher) {
|
||||
}
|
||||
@ -132,6 +133,19 @@ int Sandbox::start() {
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/telegramdesktop/tdesktop/issues/948
|
||||
// and https://github.com/telegramdesktop/tdesktop/issues/5022
|
||||
const auto restartHint = [](QSessionManager &manager) {
|
||||
manager.setRestartHint(QSessionManager::RestartNever);
|
||||
};
|
||||
|
||||
connect(
|
||||
this,
|
||||
&QGuiApplication::saveStateRequest,
|
||||
this,
|
||||
restartHint,
|
||||
Qt::DirectConnection);
|
||||
|
||||
if (cManyInstance()) {
|
||||
LOG(("Many instance allowed, starting..."));
|
||||
singleInstanceChecked();
|
||||
|
@ -79,68 +79,68 @@ void UiIntegration::startFontsEnd() {
|
||||
}
|
||||
|
||||
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
const TextParseOptions &options) {
|
||||
switch (type) {
|
||||
const EntityLinkData &data,
|
||||
const std::any &context) {
|
||||
const auto my = std::any_cast<Context>(&context);
|
||||
switch (data.type) {
|
||||
case EntityType::Url:
|
||||
return (!data.isEmpty() && UrlClickHandler::IsSuspicious(data))
|
||||
? std::make_shared<HiddenUrlClickHandler>(data)
|
||||
: nullptr;
|
||||
return (!data.data.isEmpty()
|
||||
&& UrlClickHandler::IsSuspicious(data.data))
|
||||
? std::make_shared<HiddenUrlClickHandler>(data.data)
|
||||
: Integration::createLinkHandler(data, context);
|
||||
|
||||
case EntityType::CustomUrl:
|
||||
return !data.isEmpty()
|
||||
? std::make_shared<HiddenUrlClickHandler>(data)
|
||||
: nullptr;
|
||||
return !data.data.isEmpty()
|
||||
? std::make_shared<HiddenUrlClickHandler>(data.data)
|
||||
: Integration::createLinkHandler(data, context);
|
||||
|
||||
case EntityType::BotCommand:
|
||||
return std::make_shared<BotCommandClickHandler>(data);
|
||||
return std::make_shared<BotCommandClickHandler>(data.data);
|
||||
|
||||
case EntityType::Hashtag:
|
||||
if (options.flags & TextTwitterMentions) {
|
||||
if (my && my->type == HashtagMentionType::Twitter) {
|
||||
return std::make_shared<UrlClickHandler>(
|
||||
(qsl("https://twitter.com/hashtag/")
|
||||
+ data.mid(1)
|
||||
+ data.data.mid(1)
|
||||
+ qsl("?src=hash")),
|
||||
true);
|
||||
} else if (options.flags & TextInstagramMentions) {
|
||||
} else if (my && my->type == HashtagMentionType::Instagram) {
|
||||
return std::make_shared<UrlClickHandler>(
|
||||
(qsl("https://instagram.com/explore/tags/")
|
||||
+ data.mid(1)
|
||||
+ data.data.mid(1)
|
||||
+ '/'),
|
||||
true);
|
||||
}
|
||||
return std::make_shared<HashtagClickHandler>(data);
|
||||
return std::make_shared<HashtagClickHandler>(data.data);
|
||||
|
||||
case EntityType::Cashtag:
|
||||
return std::make_shared<CashtagClickHandler>(data);
|
||||
return std::make_shared<CashtagClickHandler>(data.data);
|
||||
|
||||
case EntityType::Mention:
|
||||
if (options.flags & TextTwitterMentions) {
|
||||
if (my && my->type == HashtagMentionType::Twitter) {
|
||||
return std::make_shared<UrlClickHandler>(
|
||||
qsl("https://twitter.com/") + data.mid(1),
|
||||
qsl("https://twitter.com/") + data.data.mid(1),
|
||||
true);
|
||||
} else if (options.flags & TextInstagramMentions) {
|
||||
} else if (my && my->type == HashtagMentionType::Instagram) {
|
||||
return std::make_shared<UrlClickHandler>(
|
||||
qsl("https://instagram.com/") + data.mid(1) + '/',
|
||||
qsl("https://instagram.com/") + data.data.mid(1) + '/',
|
||||
true);
|
||||
}
|
||||
return std::make_shared<MentionClickHandler>(data);
|
||||
return std::make_shared<MentionClickHandler>(data.data);
|
||||
|
||||
case EntityType::MentionName: {
|
||||
auto fields = TextUtilities::MentionNameDataToFields(data);
|
||||
auto fields = TextUtilities::MentionNameDataToFields(data.data);
|
||||
if (fields.userId) {
|
||||
return std::make_shared<MentionNameClickHandler>(
|
||||
text,
|
||||
data.text,
|
||||
fields.userId,
|
||||
fields.accessHash);
|
||||
} else {
|
||||
LOG(("Bad mention name: %1").arg(data));
|
||||
LOG(("Bad mention name: %1").arg(data.data));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return nullptr;
|
||||
return Integration::createLinkHandler(data, context);
|
||||
}
|
||||
|
||||
bool UiIntegration::handleUrlClick(
|
||||
|
@ -13,6 +13,15 @@ namespace Core {
|
||||
|
||||
class UiIntegration : public Ui::Integration {
|
||||
public:
|
||||
enum class HashtagMentionType : uchar {
|
||||
Telegram,
|
||||
Twitter,
|
||||
Instagram,
|
||||
};
|
||||
struct Context {
|
||||
HashtagMentionType type = HashtagMentionType::Telegram;
|
||||
};
|
||||
|
||||
void postponeCall(FnMut<void()> &&callable) override;
|
||||
void registerLeaveSubscription(not_null<QWidget*> widget) override;
|
||||
void unregisterLeaveSubscription(not_null<QWidget*> widget) override;
|
||||
@ -27,10 +36,8 @@ public:
|
||||
void startFontsEnd() override;
|
||||
|
||||
std::shared_ptr<ClickHandler> createLinkHandler(
|
||||
EntityType type,
|
||||
const QString &text,
|
||||
const QString &data,
|
||||
const TextParseOptions &options) override;
|
||||
const EntityLinkData &data,
|
||||
const std::any &context) override;
|
||||
bool handleUrlClick(
|
||||
const QString &url,
|
||||
const QVariant &context) override;
|
||||
|
@ -409,9 +409,9 @@ bool UnpackUpdate(const QString &filepath) {
|
||||
bool executable = false;
|
||||
|
||||
stream >> relativeName >> fileSize >> fileInnerData;
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#ifdef Q_OS_UNIX
|
||||
stream >> executable;
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("Update Error: cant read file from downloaded stream, status: %1").arg(stream.status()));
|
||||
return false;
|
||||
@ -1511,10 +1511,10 @@ bool checkReadyUpdate() {
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
QString curUpdater = (cExeDir() + cExeName() + qsl("/Contents/Frameworks/Updater"));
|
||||
QFileInfo updater(cWorkingDir() + qsl("tupdates/temp/Kotatogram.app/Contents/Frameworks/Updater"));
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
QString curUpdater = (cExeDir() + qsl("Updater"));
|
||||
QFileInfo updater(cWorkingDir() + qsl("tupdates/temp/Updater"));
|
||||
#endif // Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX
|
||||
if (!updater.exists()) {
|
||||
QFileInfo current(curUpdater);
|
||||
if (!current.exists()) {
|
||||
@ -1548,12 +1548,12 @@ bool checkReadyUpdate() {
|
||||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
if (!linuxMoveFile(QFile::encodeName(updater.absoluteFilePath()).constData(), QFile::encodeName(curUpdater).constData())) {
|
||||
ClearAll();
|
||||
return false;
|
||||
}
|
||||
#endif // Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Platform::RemoveQuarantine(QFileInfo(curUpdater).absolutePath());
|
||||
|
@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
|
||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
||||
constexpr auto AppFile = "Kotatogram"_cs;
|
||||
constexpr auto AppVersion = 2001010;
|
||||
constexpr auto AppVersionStr = "2.1.10";
|
||||
constexpr auto AppVersion = 2001013;
|
||||
constexpr auto AppVersionStr = "2.1.13";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
@ -797,7 +797,9 @@ bool DocumentData::saveToCache() const {
|
||||
|| isAnimation()
|
||||
|| isVoiceMessage()
|
||||
|| (type == WallPaperDocument)
|
||||
|| isTheme());
|
||||
|| isTheme()
|
||||
|| (mimeString() == qstr("image/png")
|
||||
&& _filename.startsWith("image_")));
|
||||
}
|
||||
|
||||
void DocumentData::automaticLoadSettingsChanged() {
|
||||
@ -1615,10 +1617,10 @@ bool IsExecutableName(const QString &filepath) {
|
||||
qsl("\
|
||||
applescript action app bin command csh osx workflow terminal url caction \
|
||||
mpkg pkg scpt scptd xhtm webarchive");
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
qsl("bin csh deb desktop ksh out pet pkg pup rpm run sh shar \
|
||||
slp zsh");
|
||||
#else // Q_OS_MAC || Q_OS_LINUX
|
||||
#else // Q_OS_MAC || Q_OS_UNIX
|
||||
qsl("\
|
||||
ad ade adp app application appref-ms asp asx bas bat bin cdxml cer cfg chi \
|
||||
chm cmd cnt com cpl crt csh der diagcab dll drv eml exe fon fxp gadget grp \
|
||||
@ -1631,7 +1633,7 @@ psm1 pssc pst py py3 pyc pyd pyi pyo pyw pywz pyz rb reg rgs scf scr sct \
|
||||
search-ms settingcontent-ms shb shs slk sys t tmp u3p url vb vbe vbp vbs \
|
||||
vbscript vdx vsmacros vsd vsdm vsdx vss vssm vssx vst vstm vstx vsw vsx vtx \
|
||||
website ws wsc wsf wsh xbap xll xnk xs");
|
||||
#endif // !Q_OS_MAC && !Q_OS_LINUX
|
||||
#endif // !Q_OS_MAC && !Q_OS_UNIX
|
||||
const auto list = joined.split(' ');
|
||||
return base::flat_set<QString>(list.begin(), list.end());
|
||||
}();
|
||||
|
@ -45,14 +45,19 @@ Draft::Draft(
|
||||
, previewCancelled(previewCancelled) {
|
||||
}
|
||||
|
||||
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||
const auto history = Auth().data().history(peerId);
|
||||
void ApplyPeerCloudDraft(
|
||||
not_null<Main::Session*> session,
|
||||
PeerId peerId,
|
||||
const MTPDdraftMessage &draft) {
|
||||
const auto history = session->data().history(peerId);
|
||||
const auto textWithTags = TextWithTags {
|
||||
qs(draft.vmessage()),
|
||||
TextUtilities::ConvertEntitiesToTextTags(
|
||||
Api::EntitiesFromMTP(draft.ventities().value_or_empty()))
|
||||
Api::EntitiesFromMTP(
|
||||
session,
|
||||
draft.ventities().value_or_empty()))
|
||||
};
|
||||
auto replyTo = draft.vreply_to_msg_id().value_or_empty();
|
||||
const auto replyTo = draft.vreply_to_msg_id().value_or_empty();
|
||||
if (history->skipCloudDraft(textWithTags.text, replyTo, draft.vdate().v)) {
|
||||
return;
|
||||
}
|
||||
@ -67,8 +72,11 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||
history->applyCloudDraft();
|
||||
}
|
||||
|
||||
void clearPeerCloudDraft(PeerId peerId, TimeId date) {
|
||||
const auto history = Auth().data().history(peerId);
|
||||
void ClearPeerCloudDraft(
|
||||
not_null<Main::Session*> session,
|
||||
PeerId peerId,
|
||||
TimeId date) {
|
||||
const auto history = session->data().history(peerId);
|
||||
if (history->skipCloudDraft(QString(), MsgId(0), date)) {
|
||||
return;
|
||||
}
|
||||
|
@ -11,10 +11,20 @@ namespace Ui {
|
||||
class InputField;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Data {
|
||||
|
||||
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft);
|
||||
void clearPeerCloudDraft(PeerId peerId, TimeId date);
|
||||
void ApplyPeerCloudDraft(
|
||||
not_null<Main::Session*> session,
|
||||
PeerId peerId,
|
||||
const MTPDdraftMessage &draft);
|
||||
void ClearPeerCloudDraft(
|
||||
not_null<Main::Session*> session,
|
||||
PeerId peerId,
|
||||
TimeId date);
|
||||
|
||||
struct Draft {
|
||||
Draft() = default;
|
||||
|
@ -244,8 +244,9 @@ TextWithEntities Media::consumedMessageText() const {
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Media> Media::createView(
|
||||
not_null<HistoryView::Element*> message) {
|
||||
return createView(message, message->data());
|
||||
not_null<HistoryView::Element*> message,
|
||||
HistoryView::Element *replacing) {
|
||||
return createView(message, message->data(), replacing);
|
||||
}
|
||||
|
||||
MediaPhoto::MediaPhoto(
|
||||
@ -386,7 +387,8 @@ bool MediaPhoto::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaPhoto::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
if (_chat) {
|
||||
return std::make_unique<HistoryView::Photo>(
|
||||
message,
|
||||
@ -663,11 +665,15 @@ bool MediaFile::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaFile::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
if (_document->sticker()) {
|
||||
return std::make_unique<HistoryView::UnwrappedMedia>(
|
||||
message,
|
||||
std::make_unique<HistoryView::Sticker>(message, _document));
|
||||
std::make_unique<HistoryView::Sticker>(
|
||||
message,
|
||||
_document,
|
||||
replacing));
|
||||
} else if (_document->isAnimation() || _document->isVideoFile()) {
|
||||
return std::make_unique<HistoryView::Gif>(
|
||||
message,
|
||||
@ -760,7 +766,8 @@ bool MediaContact::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaContact::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Contact>(
|
||||
message,
|
||||
_contact.userId,
|
||||
@ -840,7 +847,8 @@ bool MediaLocation::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaLocation::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Location>(
|
||||
message,
|
||||
_location,
|
||||
@ -900,7 +908,8 @@ bool MediaCall::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaCall::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Call>(message, &_call);
|
||||
}
|
||||
|
||||
@ -995,7 +1004,8 @@ bool MediaWebPage::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaWebPage::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::WebPage>(message, _page);
|
||||
}
|
||||
|
||||
@ -1086,7 +1096,8 @@ bool MediaGame::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaGame::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Game>(
|
||||
message,
|
||||
_game,
|
||||
@ -1151,7 +1162,8 @@ bool MediaInvoice::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaInvoice::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Invoice>(message, &_invoice);
|
||||
}
|
||||
|
||||
@ -1217,7 +1229,8 @@ bool MediaPoll::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaPoll::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::Poll>(message, _poll);
|
||||
}
|
||||
|
||||
@ -1274,7 +1287,8 @@ bool MediaDice::updateSentMedia(const MTPMessageMedia &media) {
|
||||
|
||||
std::unique_ptr<HistoryView::Media> MediaDice::createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) {
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing) {
|
||||
return std::make_unique<HistoryView::UnwrappedMedia>(
|
||||
message,
|
||||
std::make_unique<HistoryView::Dice>(message, this));
|
||||
|
@ -111,9 +111,11 @@ public:
|
||||
virtual bool updateSentMedia(const MTPMessageMedia &media) = 0;
|
||||
virtual std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) = 0;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) = 0;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message);
|
||||
not_null<HistoryView::Element*> message,
|
||||
HistoryView::Element *replacing = nullptr);
|
||||
|
||||
private:
|
||||
const not_null<HistoryItem*> _parent;
|
||||
@ -152,7 +154,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
not_null<PhotoData*> _photo;
|
||||
@ -189,7 +192,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
not_null<DocumentData*> _document;
|
||||
@ -218,7 +222,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
SharedContact _contact;
|
||||
@ -248,7 +253,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
LocationPoint _point;
|
||||
@ -276,7 +282,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
static QString Text(
|
||||
not_null<HistoryItem*> item,
|
||||
@ -312,7 +319,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
not_null<WebPageData*> _page;
|
||||
@ -343,7 +351,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
not_null<GameData*> _game;
|
||||
@ -374,7 +383,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
Invoice _invoice;
|
||||
@ -401,7 +411,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
not_null<PollData*> _poll;
|
||||
@ -425,7 +436,8 @@ public:
|
||||
bool updateSentMedia(const MTPMessageMedia &media) override;
|
||||
std::unique_ptr<HistoryView::Media> createView(
|
||||
not_null<HistoryView::Element*> message,
|
||||
not_null<HistoryItem*> realParent) override;
|
||||
not_null<HistoryItem*> realParent,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
private:
|
||||
QString _emoji;
|
||||
|
@ -45,6 +45,14 @@ PollData::PollData(not_null<Data::Session*> owner, PollId id)
|
||||
, _owner(owner) {
|
||||
}
|
||||
|
||||
Data::Session &PollData::owner() const {
|
||||
return *_owner;
|
||||
}
|
||||
|
||||
Main::Session &PollData::session() const {
|
||||
return _owner->session();
|
||||
}
|
||||
|
||||
bool PollData::closeByTimer() {
|
||||
if (closed()) {
|
||||
return false;
|
||||
@ -151,6 +159,7 @@ bool PollData::applyResults(const MTPPollResults &results) {
|
||||
auto newSolution = TextWithEntities{
|
||||
results.vsolution().value_or_empty(),
|
||||
Api::EntitiesFromMTP(
|
||||
&_owner->session(),
|
||||
results.vsolution_entities().value_or_empty())
|
||||
};
|
||||
if (solution != newSolution) {
|
||||
@ -293,6 +302,7 @@ MTPInputMedia PollDataToInputMedia(
|
||||
TextUtilities::PrepareForSending(solution, prepareFlags);
|
||||
TextUtilities::Trim(solution);
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
&poll->session(),
|
||||
solution.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!solution.text.isEmpty()) {
|
||||
|
@ -11,6 +11,10 @@ namespace Data {
|
||||
class Session;
|
||||
} // namespace Data
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
struct PollAnswer {
|
||||
QString text;
|
||||
QByteArray option;
|
||||
@ -31,6 +35,9 @@ inline bool operator!=(const PollAnswer &a, const PollAnswer &b) {
|
||||
struct PollData {
|
||||
PollData(not_null<Data::Session*> owner, PollId id);
|
||||
|
||||
[[nodiscard]] Data::Session &owner() const;
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
|
||||
enum class Flag {
|
||||
Closed = 0x01,
|
||||
PublicVotes = 0x02,
|
||||
|
@ -152,7 +152,7 @@ void ScheduledMessages::sendNowSimpleMessage(
|
||||
// we know for sure that a message can't have fields such as the author,
|
||||
// views count, etc.
|
||||
|
||||
const auto &history = local->history();
|
||||
const auto history = local->history();
|
||||
auto flags = NewMessageFlags(history->peer)
|
||||
| MTPDmessage::Flag::f_entities
|
||||
| MTPDmessage::Flag::f_from_id
|
||||
@ -175,7 +175,9 @@ void ScheduledMessages::sendNowSimpleMessage(
|
||||
MTP_string(local->originalText().text),
|
||||
MTP_messageMediaEmpty(),
|
||||
MTPReplyMarkup(),
|
||||
Api::EntitiesToMTP(local->originalText().entities),
|
||||
Api::EntitiesToMTP(
|
||||
&history->session(),
|
||||
local->originalText().entities),
|
||||
MTP_int(1),
|
||||
MTPint(),
|
||||
MTP_string(),
|
||||
@ -234,7 +236,7 @@ void ScheduledMessages::checkEntitiesAndUpdate(const MTPDmessage &data) {
|
||||
Assert(existing->date() == kScheduledUntilOnlineTimestamp);
|
||||
existing->updateSentContent({
|
||||
qs(data.vmessage()),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(_session, data.ventities().value_or_empty())
|
||||
}, data.vmedia());
|
||||
existing->updateReplyMarkup(data.vreply_markup());
|
||||
existing->updateForwardedInfo(data.vfwd_from());
|
||||
@ -410,7 +412,9 @@ HistoryItem *ScheduledMessages::append(
|
||||
message.match([&](const MTPDmessage &data) {
|
||||
existing->updateSentContent({
|
||||
qs(data.vmessage()),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(
|
||||
_session,
|
||||
data.ventities().value_or_empty())
|
||||
}, data.vmedia());
|
||||
existing->updateReplyMarkup(data.vreply_markup());
|
||||
existing->updateForwardedInfo(data.vfwd_from());
|
||||
|
@ -1703,7 +1703,9 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
|
||||
if (const auto existing = message(peerToChannel(peer), data.vid().v)) {
|
||||
existing->updateSentContent({
|
||||
qs(data.vmessage()),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(
|
||||
&session(),
|
||||
data.ventities().value_or_empty())
|
||||
}, data.vmedia());
|
||||
existing->updateReplyMarkup(data.vreply_markup());
|
||||
existing->updateForwardedInfo(data.vfwd_from());
|
||||
@ -3725,7 +3727,7 @@ void Session::insertCheckedServiceNotification(
|
||||
MTP_string(sending.text),
|
||||
media,
|
||||
MTPReplyMarkup(),
|
||||
Api::EntitiesToMTP(sending.entities),
|
||||
Api::EntitiesToMTP(&session(), sending.entities),
|
||||
MTPint(),
|
||||
MTPint(),
|
||||
MTPstring(),
|
||||
|
@ -538,13 +538,15 @@ HistoryView::Context InnerWidget::elementContext() {
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> InnerWidget::elementCreate(
|
||||
not_null<HistoryMessage*> message) {
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<HistoryView::Message>(this, message, replacing);
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> InnerWidget::elementCreate(
|
||||
not_null<HistoryService*> message) {
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<HistoryView::Service>(this, message, replacing);
|
||||
}
|
||||
|
||||
bool InnerWidget::elementUnderCursor(
|
||||
@ -1535,13 +1537,13 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
||||
_mouseSelectType = TextSelectType::Letters;
|
||||
//_widget->noSelectingScroll(); // TODO
|
||||
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
if (_selectedItem && _selectedText.from != _selectedText.to) {
|
||||
TextUtilities::SetClipboardText(
|
||||
_selectedItem->selectedText(_selectedText),
|
||||
QClipboard::Selection);
|
||||
}
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
}
|
||||
|
||||
void InnerWidget::updateSelected() {
|
||||
|
@ -89,9 +89,11 @@ public:
|
||||
// HistoryView::ElementDelegate interface.
|
||||
HistoryView::Context elementContext() override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override;
|
||||
not_null<HistoryMessage*> message,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryService*> message) override;
|
||||
not_null<HistoryService*> message,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
bool elementUnderCursor(
|
||||
not_null<const HistoryView::Element*> view) override;
|
||||
void elementAnimationAutoplayAsync(
|
||||
|
@ -111,14 +111,16 @@ bool MediaCanHaveCaption(const MTPMessage &message) {
|
||||
return (mediaType == mtpc_messageMediaDocument || mediaType == mtpc_messageMediaPhoto);
|
||||
}
|
||||
|
||||
TextWithEntities ExtractEditedText(const MTPMessage &message) {
|
||||
TextWithEntities ExtractEditedText(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPMessage &message) {
|
||||
if (message.type() != mtpc_message) {
|
||||
return TextWithEntities();
|
||||
}
|
||||
const auto &data = message.c_message();
|
||||
return {
|
||||
TextUtilities::Clean(qs(data.vmessage())),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(session, data.ventities().value_or_empty())
|
||||
};
|
||||
}
|
||||
|
||||
@ -376,19 +378,20 @@ void GenerateItems(
|
||||
Fn<void(OwnedItem item)> callback) {
|
||||
Expects(history->peer->isChannel());
|
||||
|
||||
auto id = event.vid().v;
|
||||
auto from = Auth().data().user(event.vuser_id().v);
|
||||
auto channel = history->peer->asChannel();
|
||||
auto &action = event.vaction();
|
||||
auto date = event.vdate().v;
|
||||
auto addPart = [&](not_null<HistoryItem*> item) {
|
||||
const auto session = &history->session();
|
||||
const auto id = event.vid().v;
|
||||
const auto from = Auth().data().user(event.vuser_id().v);
|
||||
const auto channel = history->peer->asChannel();
|
||||
const auto &action = event.vaction();
|
||||
const auto date = event.vdate().v;
|
||||
const auto addPart = [&](not_null<HistoryItem*> item) {
|
||||
return callback(OwnedItem(delegate, item));
|
||||
};
|
||||
|
||||
using Flag = MTPDmessage::Flag;
|
||||
auto fromName = from->name;
|
||||
auto fromLink = from->createOpenLink();
|
||||
auto fromLinkText = textcmdLink(1, fromName);
|
||||
const auto fromName = from->name;
|
||||
const auto fromLink = from->createOpenLink();
|
||||
const auto fromLinkText = textcmdLink(1, fromName);
|
||||
|
||||
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
|
||||
auto message = HistoryService::PreparedText { text };
|
||||
@ -542,7 +545,7 @@ void GenerateItems(
|
||||
};
|
||||
|
||||
auto createEditMessage = [&](const MTPDchannelAdminLogEventActionEditMessage &action) {
|
||||
auto newValue = ExtractEditedText(action.vnew_message());
|
||||
auto newValue = ExtractEditedText(session, action.vnew_message());
|
||||
auto canHaveCaption = MediaCanHaveCaption(action.vnew_message());
|
||||
auto text = (!canHaveCaption
|
||||
? tr::lng_admin_log_edited_message
|
||||
@ -554,7 +557,7 @@ void GenerateItems(
|
||||
fromLinkText);
|
||||
addSimpleServiceMessage(text);
|
||||
|
||||
auto oldValue = ExtractEditedText(action.vprev_message());
|
||||
auto oldValue = ExtractEditedText(session, action.vprev_message());
|
||||
auto detachExistingItem = false;
|
||||
auto body = history->createItem(
|
||||
PrepareLogMessage(
|
||||
|
@ -2700,7 +2700,10 @@ void History::applyDialog(
|
||||
|
||||
const auto draft = data.vdraft();
|
||||
if (draft && draft->type() == mtpc_draftMessage) {
|
||||
Data::applyPeerCloudDraft(peer->id, draft->c_draftMessage());
|
||||
Data::ApplyPeerCloudDraft(
|
||||
&session(),
|
||||
peer->id,
|
||||
draft->c_draftMessage());
|
||||
}
|
||||
owner().histories().dialogEntryApplied(this);
|
||||
}
|
||||
@ -3361,7 +3364,9 @@ void HistoryBlock::refreshView(not_null<Element*> view) {
|
||||
Expects(view->block() == this);
|
||||
|
||||
const auto item = view->data();
|
||||
auto refreshed = item->createView(HistoryInner::ElementDelegate());
|
||||
auto refreshed = item->createView(
|
||||
HistoryInner::ElementDelegate(),
|
||||
view);
|
||||
|
||||
auto blockIndex = indexInHistory();
|
||||
auto itemIndex = view->indexInBlock();
|
||||
|
@ -1427,7 +1427,7 @@ void HistoryInner::mouseActionFinish(
|
||||
_widget->noSelectingScroll();
|
||||
_widget->updateTopBarSelection();
|
||||
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
if (!_selected.empty() && _selected.cbegin()->second != FullSelection) {
|
||||
const auto [item, selection] = *_selected.cbegin();
|
||||
if (const auto view = item->mainView()) {
|
||||
@ -1436,7 +1436,7 @@ void HistoryInner::mouseActionFinish(
|
||||
QClipboard::Selection);
|
||||
}
|
||||
}
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
}
|
||||
|
||||
void HistoryInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||
@ -2373,7 +2373,7 @@ HistoryInner::~HistoryInner() {
|
||||
for (const auto &item : _animatedStickersPlayed) {
|
||||
if (const auto view = item->mainView()) {
|
||||
if (const auto media = view->media()) {
|
||||
media->clearStickerLoopPlayed();
|
||||
media->stickerClearLoopPlayed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3323,12 +3323,20 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
|
||||
return HistoryView::Context::History;
|
||||
}
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override {
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing = nullptr) override {
|
||||
return std::make_unique<HistoryView::Message>(
|
||||
this,
|
||||
message,
|
||||
replacing);
|
||||
}
|
||||
std::unique_ptr<HistoryView::Element> elementCreate(
|
||||
not_null<HistoryService*> message) override {
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing = nullptr) override {
|
||||
return std::make_unique<HistoryView::Service>(
|
||||
this,
|
||||
message,
|
||||
replacing);
|
||||
}
|
||||
bool elementUnderCursor(
|
||||
not_null<const HistoryView::Element*> view) override {
|
||||
|
@ -326,7 +326,8 @@ public:
|
||||
[[nodiscard]] PeerData *displayFrom() const;
|
||||
|
||||
[[nodiscard]] virtual std::unique_ptr<HistoryView::Element> createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate) = 0;
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
HistoryView::Element *replacing = nullptr) = 0;
|
||||
|
||||
void updateDate(TimeId newDate);
|
||||
[[nodiscard]] bool canUpdateDate() const;
|
||||
|
@ -458,7 +458,9 @@ HistoryMessage::HistoryMessage(
|
||||
}
|
||||
const auto textWithEntities = TextWithEntities{
|
||||
TextUtilities::Clean(qs(data.vmessage())),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(
|
||||
&history->session(),
|
||||
data.ventities().value_or_empty())
|
||||
};
|
||||
setText(_media ? textWithEntities : EnsureNonEmpty(textWithEntities));
|
||||
if (const auto groupedId = data.vgrouped_id()) {
|
||||
@ -1072,7 +1074,9 @@ void HistoryMessage::applyEdition(const MTPDmessage &message) {
|
||||
|
||||
const auto textWithEntities = TextWithEntities{
|
||||
qs(message.vmessage()),
|
||||
Api::EntitiesFromMTP(message.ventities().value_or_empty())
|
||||
Api::EntitiesFromMTP(
|
||||
&history()->session(),
|
||||
message.ventities().value_or_empty())
|
||||
};
|
||||
setReplyMarkup(message.vreply_markup());
|
||||
if (!isLocalUpdateMedia()) {
|
||||
@ -1383,8 +1387,9 @@ QString HistoryMessage::notificationHeader() const {
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> HistoryMessage::createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate) {
|
||||
return delegate->elementCreate(this);
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
HistoryView::Element *replacing) {
|
||||
return delegate->elementCreate(this, replacing);
|
||||
}
|
||||
|
||||
HistoryMessage::~HistoryMessage() {
|
||||
|
@ -168,7 +168,8 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<HistoryView::Element> createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate) override;
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
~HistoryMessage();
|
||||
|
||||
|
@ -570,8 +570,9 @@ QString HistoryService::inReplyText() const {
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> HistoryService::createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate) {
|
||||
return delegate->elementCreate(this);
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
HistoryView::Element *replacing) {
|
||||
return delegate->elementCreate(this, replacing);
|
||||
}
|
||||
|
||||
QString HistoryService::fromLinkText() const {
|
||||
|
@ -105,7 +105,8 @@ public:
|
||||
QString inReplyText() const override;
|
||||
|
||||
std::unique_ptr<HistoryView::Element> createView(
|
||||
not_null<HistoryView::ElementDelegate*> delegate) override;
|
||||
not_null<HistoryView::ElementDelegate*> delegate,
|
||||
HistoryView::Element *replacing = nullptr) override;
|
||||
|
||||
~HistoryService();
|
||||
|
||||
|
@ -65,6 +65,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "chat_helpers/tabbed_section.h"
|
||||
#include "chat_helpers/bot_keyboard.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwidget.h"
|
||||
#include "mainwindow.h"
|
||||
@ -2102,6 +2103,7 @@ void HistoryWidget::refreshScheduledToggle() {
|
||||
controller()->showSection(
|
||||
HistoryView::ScheduledMemento(_history));
|
||||
});
|
||||
orderWidgets(); // Raise drag areas to the top.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3068,8 +3070,9 @@ void HistoryWidget::saveEditMsg() {
|
||||
if (webPageId == CancelledWebPageId) {
|
||||
sendFlags |= MTPmessages_EditMessage::Flag::f_no_webpage;
|
||||
}
|
||||
auto localEntities = Api::EntitiesToMTP(sending.entities);
|
||||
auto localEntities = Api::EntitiesToMTP(&session(), sending.entities);
|
||||
auto sentEntities = Api::EntitiesToMTP(
|
||||
&session(),
|
||||
sending.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
@ -4605,7 +4608,10 @@ bool HistoryWidget::confirmSendingFiles(
|
||||
}
|
||||
|
||||
if (hasImage) {
|
||||
auto image = qvariant_cast<QImage>(data->imageData());
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
confirmSendingFiles(
|
||||
std::move(image),
|
||||
@ -4755,7 +4761,7 @@ void HistoryWidget::sendFileConfirmed(
|
||||
session().user()).flags;
|
||||
TextUtilities::PrepareForSending(caption, prepareFlags);
|
||||
TextUtilities::Trim(caption);
|
||||
auto localEntities = Api::EntitiesToMTP(caption.entities);
|
||||
auto localEntities = Api::EntitiesToMTP(&session(), caption.entities);
|
||||
|
||||
if (itemToEdit) {
|
||||
if (const auto id = itemToEdit->groupId()) {
|
||||
|
@ -430,12 +430,17 @@ bool AddRescheduleMessageAction(
|
||||
? SendMenuType::ScheduledToUser
|
||||
: SendMenuType::Scheduled;
|
||||
|
||||
using S = Data::ScheduledMessages;
|
||||
const auto date = (item->date() == S::kScheduledUntilOnlineTimestamp)
|
||||
? HistoryView::DefaultScheduleTime()
|
||||
: item->date() + 600;
|
||||
|
||||
Ui::show(
|
||||
HistoryView::PrepareScheduleBox(
|
||||
&request.navigation->session(),
|
||||
sendMenuType,
|
||||
callback,
|
||||
item->date() + 600),
|
||||
date),
|
||||
Ui::LayerOption::KeepOther);
|
||||
});
|
||||
return true;
|
||||
|
@ -56,13 +56,15 @@ bool IsAttachedToPreviousInSavedMessages(
|
||||
|
||||
|
||||
std::unique_ptr<HistoryView::Element> SimpleElementDelegate::elementCreate(
|
||||
not_null<HistoryMessage*> message) {
|
||||
return std::make_unique<HistoryView::Message>(this, message);
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<HistoryView::Message>(this, message, replacing);
|
||||
}
|
||||
|
||||
std::unique_ptr<HistoryView::Element> SimpleElementDelegate::elementCreate(
|
||||
not_null<HistoryService*> message) {
|
||||
return std::make_unique<HistoryView::Service>(this, message);
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<HistoryView::Service>(this, message, replacing);
|
||||
}
|
||||
|
||||
bool SimpleElementDelegate::elementUnderCursor(
|
||||
@ -203,14 +205,15 @@ void DateBadge::paint(Painter &p, int y, int w) const {
|
||||
|
||||
Element::Element(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryItem*> data)
|
||||
not_null<HistoryItem*> data,
|
||||
Element *replacing)
|
||||
: _delegate(delegate)
|
||||
, _data(data)
|
||||
, _isScheduledUntilOnline(IsItemScheduledUntilOnline(data))
|
||||
, _dateTime(_isScheduledUntilOnline ? QDateTime() : ItemDateTime(data))
|
||||
, _context(delegate->elementContext()) {
|
||||
history()->owner().registerItemView(this);
|
||||
refreshMedia();
|
||||
refreshMedia(replacing);
|
||||
if (_context == Context::History) {
|
||||
history()->setHasPendingResizedItems();
|
||||
}
|
||||
@ -342,7 +345,7 @@ bool Element::isHidden() const {
|
||||
return isHiddenByGroup();
|
||||
}
|
||||
|
||||
void Element::refreshMedia() {
|
||||
void Element::refreshMedia(Element *replacing) {
|
||||
_flags &= ~Flag::HiddenByGroup;
|
||||
|
||||
const auto item = data();
|
||||
@ -365,7 +368,7 @@ void Element::refreshMedia() {
|
||||
}
|
||||
const auto session = &history()->session();
|
||||
if (const auto media = _data->media()) {
|
||||
_media = media->createView(this);
|
||||
_media = media->createView(this, replacing);
|
||||
} else if (_data->isIsolatedEmoji()
|
||||
&& session->settings().largeEmoji()) {
|
||||
const auto emoji = _data->isolatedEmoji();
|
||||
@ -376,6 +379,7 @@ void Element::refreshMedia() {
|
||||
std::make_unique<Sticker>(
|
||||
this,
|
||||
sticker.document,
|
||||
replacing,
|
||||
sticker.replacements));
|
||||
} else {
|
||||
_media = std::make_unique<UnwrappedMedia>(
|
||||
|
@ -37,9 +37,11 @@ class ElementDelegate {
|
||||
public:
|
||||
virtual Context elementContext() = 0;
|
||||
virtual std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) = 0;
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing = nullptr) = 0;
|
||||
virtual std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryService*> message) = 0;
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing = nullptr) = 0;
|
||||
virtual bool elementUnderCursor(not_null<const Element*> view) = 0;
|
||||
virtual void elementAnimationAutoplayAsync(
|
||||
not_null<const Element*> element) = 0;
|
||||
@ -63,9 +65,11 @@ public:
|
||||
class SimpleElementDelegate : public ElementDelegate {
|
||||
public:
|
||||
std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override;
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing = nullptr) override;
|
||||
std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryService*> message) override;
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing = nullptr) override;
|
||||
bool elementUnderCursor(not_null<const Element*> view) override;
|
||||
void elementAnimationAutoplayAsync(
|
||||
not_null<const Element*> element) override;
|
||||
@ -134,7 +138,8 @@ class Element
|
||||
public:
|
||||
Element(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryItem*> data);
|
||||
not_null<HistoryItem*> data,
|
||||
Element *replacing);
|
||||
|
||||
enum class Flag : uchar {
|
||||
NeedsResize = 0x01,
|
||||
@ -305,7 +310,7 @@ private:
|
||||
virtual QSize performCountOptimalSize() = 0;
|
||||
virtual QSize performCountCurrentSize(int newWidth) = 0;
|
||||
|
||||
void refreshMedia();
|
||||
void refreshMedia(Element *replacing);
|
||||
|
||||
const not_null<ElementDelegate*> _delegate;
|
||||
const not_null<HistoryItem*> _data;
|
||||
|
@ -1107,13 +1107,15 @@ Context ListWidget::elementContext() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Element> ListWidget::elementCreate(
|
||||
not_null<HistoryMessage*> message) {
|
||||
return std::make_unique<Message>(this, message);
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<Message>(this, message, replacing);
|
||||
}
|
||||
|
||||
std::unique_ptr<Element> ListWidget::elementCreate(
|
||||
not_null<HistoryService*> message) {
|
||||
return std::make_unique<Service>(this, message);
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing) {
|
||||
return std::make_unique<Service>(this, message, replacing);
|
||||
}
|
||||
|
||||
bool ListWidget::elementUnderCursor(
|
||||
@ -2083,7 +2085,7 @@ void ListWidget::mouseActionFinish(
|
||||
_mouseSelectType = TextSelectType::Letters;
|
||||
//_widget->noSelectingScroll(); // #TODO select scroll
|
||||
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
if (_selectedTextItem
|
||||
&& _selectedTextRange.from != _selectedTextRange.to) {
|
||||
if (const auto view = viewForItem(_selectedTextItem)) {
|
||||
@ -2092,7 +2094,7 @@ void ListWidget::mouseActionFinish(
|
||||
QClipboard::Selection);
|
||||
}
|
||||
}
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
}
|
||||
|
||||
void ListWidget::mouseActionUpdate() {
|
||||
|
@ -184,9 +184,11 @@ public:
|
||||
// ElementDelegate interface.
|
||||
Context elementContext() override;
|
||||
std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryMessage*> message) override;
|
||||
not_null<HistoryMessage*> message,
|
||||
Element *replacing = nullptr) override;
|
||||
std::unique_ptr<Element> elementCreate(
|
||||
not_null<HistoryService*> message) override;
|
||||
not_null<HistoryService*> message,
|
||||
Element *replacing = nullptr) override;
|
||||
bool elementUnderCursor(not_null<const Element*> view) override;
|
||||
void elementAnimationAutoplayAsync(
|
||||
not_null<const Element*> view) override;
|
||||
|
@ -217,8 +217,9 @@ LogEntryOriginal::~LogEntryOriginal() = default;
|
||||
|
||||
Message::Message(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryMessage*> data)
|
||||
: Element(delegate, data) {
|
||||
not_null<HistoryMessage*> data,
|
||||
Element *replacing)
|
||||
: Element(delegate, data, replacing) {
|
||||
initLogEntryOriginal();
|
||||
initPsa();
|
||||
}
|
||||
|
@ -41,7 +41,8 @@ class Message : public Element, public base::has_weak_ptr {
|
||||
public:
|
||||
Message(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryMessage*> data);
|
||||
not_null<HistoryMessage*> data,
|
||||
Element *replacing);
|
||||
|
||||
int marginTop() const override;
|
||||
int marginBottom() const override;
|
||||
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_scheduled_messages.h" // kScheduledUntilOnlineTimestamp
|
||||
#include "lang/lang_keys.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "boxes/calendar_box.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
@ -65,17 +66,30 @@ QString TimeString(TimeId time) {
|
||||
).arg(parsed.minute(), 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
|
||||
int ProcessWheelEvent(not_null<QWheelEvent*> e) {
|
||||
// Only a mouse wheel is accepted.
|
||||
constexpr auto step = static_cast<int>(QWheelEvent::DefaultDeltasPerStep);
|
||||
const auto delta = e->angleDelta().y();
|
||||
const auto absDelta = std::abs(delta);
|
||||
if (absDelta != step) {
|
||||
return 0;
|
||||
}
|
||||
return (delta / absDelta);
|
||||
}
|
||||
|
||||
class TimePart final : public Ui::MaskedInputField {
|
||||
public:
|
||||
using MaskedInputField::MaskedInputField;
|
||||
|
||||
void setMaxValue(int value);
|
||||
void setWheelStep(int value);
|
||||
|
||||
rpl::producer<> erasePrevious() const;
|
||||
rpl::producer<QChar> putNext() const;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void wheelEvent(QWheelEvent *e) override;
|
||||
|
||||
void correctValue(
|
||||
const QString &was,
|
||||
@ -86,11 +100,21 @@ protected:
|
||||
private:
|
||||
int _maxValue = 0;
|
||||
int _maxDigits = 0;
|
||||
int _wheelStep = 0;
|
||||
rpl::event_stream<> _erasePrevious;
|
||||
rpl::event_stream<QChar> _putNext;
|
||||
|
||||
};
|
||||
|
||||
int Number(not_null<TimePart*> field) {
|
||||
const auto text = field->getLastText();
|
||||
auto ref = text.midRef(0);
|
||||
while (!ref.isEmpty() && ref.at(0) == '0') {
|
||||
ref = ref.mid(1);
|
||||
}
|
||||
return ref.toInt();
|
||||
}
|
||||
|
||||
class TimeInput final : public Ui::RpWidget {
|
||||
public:
|
||||
TimeInput(QWidget *parent, const QString &value);
|
||||
@ -121,7 +145,6 @@ private:
|
||||
|
||||
int hour() const;
|
||||
int minute() const;
|
||||
int number(const object_ptr<TimePart> &field) const;
|
||||
|
||||
object_ptr<TimePart> _hour;
|
||||
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _separator1;
|
||||
@ -181,6 +204,10 @@ void TimePart::setMaxValue(int value) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimePart::setWheelStep(int value) {
|
||||
_wheelStep = value;
|
||||
}
|
||||
|
||||
rpl::producer<> TimePart::erasePrevious() const {
|
||||
return _erasePrevious.events();
|
||||
}
|
||||
@ -199,6 +226,18 @@ void TimePart::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimePart::wheelEvent(QWheelEvent *e) {
|
||||
const auto direction = ProcessWheelEvent(e);
|
||||
auto time = Number(this) + (direction * _wheelStep);
|
||||
const auto max = _maxValue + 1;
|
||||
if (time < 0) {
|
||||
time += max;
|
||||
} else if (time >= max) {
|
||||
time -= max;
|
||||
}
|
||||
setText(QString::number(time));
|
||||
}
|
||||
|
||||
void TimePart::correctValue(
|
||||
const QString &was,
|
||||
int wasCursor,
|
||||
@ -290,10 +329,12 @@ TimeInput::TimeInput(QWidget *parent, const QString &value)
|
||||
connect(_hour, &Ui::MaskedInputField::changed, changed);
|
||||
connect(_minute, &Ui::MaskedInputField::changed, changed);
|
||||
_hour->setMaxValue(23);
|
||||
_hour->setWheelStep(1);
|
||||
_hour->putNext() | rpl::start_with_next([=](QChar ch) {
|
||||
putNext(_minute, ch);
|
||||
}, lifetime());
|
||||
_minute->setMaxValue(59);
|
||||
_minute->setWheelStep(10);
|
||||
_minute->erasePrevious() | rpl::start_with_next([=] {
|
||||
erasePrevious(_hour);
|
||||
}, lifetime());
|
||||
@ -356,21 +397,12 @@ bool TimeInput::setFocusFast() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int TimeInput::number(const object_ptr<TimePart> &field) const {
|
||||
const auto text = field->getLastText();
|
||||
auto ref = text.midRef(0);
|
||||
while (!ref.isEmpty() && ref.at(0) == '0') {
|
||||
ref = ref.mid(1);
|
||||
}
|
||||
return ref.toInt();
|
||||
}
|
||||
|
||||
int TimeInput::hour() const {
|
||||
return number(_hour);
|
||||
return Number(_hour);
|
||||
}
|
||||
|
||||
int TimeInput::minute() const {
|
||||
return number(_minute);
|
||||
return Number(_minute);
|
||||
}
|
||||
|
||||
QString TimeInput::valueCurrent() const {
|
||||
@ -601,6 +633,24 @@ void ScheduleBox(
|
||||
timeInput->setFocusFast();
|
||||
}, dayInput->lifetime());
|
||||
|
||||
const auto minDate = QDate::currentDate();
|
||||
const auto maxDate = minDate.addYears(1).addDays(-1);
|
||||
|
||||
const auto &dayViewport = dayInput->rawTextEdit()->viewport();
|
||||
base::install_event_filter(dayViewport, [=](not_null<QEvent*> event) {
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
const auto e = static_cast<QWheelEvent*>(event.get());
|
||||
const auto direction = ProcessWheelEvent(e);
|
||||
if (!direction) {
|
||||
return base::EventFilterResult::Continue;
|
||||
}
|
||||
const auto d = date->current().addDays(direction);
|
||||
*date = std::clamp(d, minDate, maxDate);
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
});
|
||||
|
||||
content->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
const auto paddings = width
|
||||
@ -622,16 +672,19 @@ void ScheduleBox(
|
||||
width);
|
||||
}, content->lifetime());
|
||||
|
||||
const auto calendar =
|
||||
content->lifetime().make_state<QPointer<CalendarBox>>();
|
||||
QObject::connect(dayInput, &Ui::InputField::focused, [=] {
|
||||
const auto calendar = std::make_shared<QPointer<CalendarBox>>();
|
||||
if (*calendar) {
|
||||
return;
|
||||
}
|
||||
const auto chosen = [=](QDate chosen) {
|
||||
*date = chosen;
|
||||
(*calendar)->closeBox();
|
||||
};
|
||||
const auto finalize = [=](not_null<CalendarBox*> box) {
|
||||
const auto now = QDate::currentDate();
|
||||
box->setMinDate(now);
|
||||
box->setMaxDate(now.addYears(1).addDays(-1));
|
||||
box->setMinDate(minDate);
|
||||
box->setMaxDate(maxDate);
|
||||
};
|
||||
*calendar = box->getDelegate()->show(Box<CalendarBox>(
|
||||
date->current(),
|
||||
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "facades.h"
|
||||
#include "app.h"
|
||||
@ -265,7 +266,10 @@ bool ScheduledWidget::confirmSendingFiles(
|
||||
}
|
||||
|
||||
if (hasImage) {
|
||||
auto image = qvariant_cast<QImage>(data->imageData());
|
||||
auto image = Platform::GetImageFromClipboard();
|
||||
if (image.isNull()) {
|
||||
image = qvariant_cast<QImage>(data->imageData());
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
confirmSendingFiles(
|
||||
std::move(image),
|
||||
|
@ -309,8 +309,9 @@ void serviceColorsUpdated() {
|
||||
|
||||
Service::Service(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryService*> data)
|
||||
: Element(delegate, data) {
|
||||
not_null<HistoryService*> data,
|
||||
Element *replacing)
|
||||
: Element(delegate, data, replacing) {
|
||||
}
|
||||
|
||||
not_null<HistoryService*> Service::message() const {
|
||||
|
@ -17,7 +17,8 @@ class Service : public Element {
|
||||
public:
|
||||
Service(
|
||||
not_null<ElementDelegate*> delegate,
|
||||
not_null<HistoryService*> data);
|
||||
not_null<HistoryService*> data,
|
||||
Element *replacing);
|
||||
|
||||
int marginTop() const override;
|
||||
int marginBottom() const override;
|
||||
|
@ -26,8 +26,6 @@ public:
|
||||
|
||||
ClickHandlerPtr link() override;
|
||||
|
||||
void clearStickerLoopPlayed() override {
|
||||
}
|
||||
bool hasHeavyPart() const override {
|
||||
return (_start ? _start->hasHeavyPart() : false)
|
||||
|| (_end ? _end->hasHeavyPart() : false);
|
||||
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history_item.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
#include "data/data_document.h"
|
||||
#include "ui/text_options.h"
|
||||
@ -165,6 +166,10 @@ PointState Media::pointState(QPoint point) const {
|
||||
: PointState::Outside;
|
||||
}
|
||||
|
||||
std::unique_ptr<Lottie::SinglePlayer> Media::stickerTakeLottie() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TextState Media::getStateGrouped(
|
||||
const QRect &geometry,
|
||||
RectParts sides,
|
||||
|
@ -24,6 +24,10 @@ enum class SharedMediaType : signed char;
|
||||
using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
|
||||
} // namespace Storage
|
||||
|
||||
namespace Lottie {
|
||||
class SinglePlayer;
|
||||
} // namespace Lottie
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
enum class PointState : char;
|
||||
@ -139,8 +143,9 @@ public:
|
||||
}
|
||||
virtual void stopAnimation() {
|
||||
}
|
||||
virtual void clearStickerLoopPlayed() {
|
||||
virtual void stickerClearLoopPlayed() {
|
||||
}
|
||||
virtual std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie();
|
||||
virtual void checkAnimation() {
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "data/data_session.h"
|
||||
#include "layout.h"
|
||||
#include "facades.h"
|
||||
@ -26,6 +27,11 @@ constexpr auto kMaxForwardedBarLines = 4;
|
||||
|
||||
} // namespace
|
||||
|
||||
auto UnwrappedMedia::Content::stickerTakeLottie()
|
||||
-> std::unique_ptr<Lottie::SinglePlayer> {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UnwrappedMedia::UnwrappedMedia(
|
||||
not_null<Element*> parent,
|
||||
std::unique_ptr<Content> content)
|
||||
@ -387,6 +393,10 @@ TextState UnwrappedMedia::textState(QPoint point, StateRequest request) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Lottie::SinglePlayer> UnwrappedMedia::stickerTakeLottie() {
|
||||
return _content->stickerTakeLottie();
|
||||
}
|
||||
|
||||
int UnwrappedMedia::calculateFullRight(const QRect &inner) const {
|
||||
const auto rightAligned = _parent->hasOutLayout() && !Adaptive::ChatWide();
|
||||
const auto infoWidth = _parent->infoWidth()
|
||||
|
@ -32,8 +32,9 @@ public:
|
||||
[[nodiscard]] virtual DocumentData *document() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual void clearStickerLoopPlayed() {
|
||||
virtual void stickerClearLoopPlayed() {
|
||||
}
|
||||
virtual std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie();
|
||||
virtual bool hasHeavyPart() const {
|
||||
return false;
|
||||
}
|
||||
@ -81,9 +82,10 @@ public:
|
||||
bool hidesForwardedInfo() const override {
|
||||
return _content->hidesForwardedInfo();
|
||||
}
|
||||
void clearStickerLoopPlayed() override {
|
||||
_content->clearStickerLoopPlayed();
|
||||
void stickerClearLoopPlayed() override {
|
||||
_content->stickerClearLoopPlayed();
|
||||
}
|
||||
std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie() override;
|
||||
|
||||
bool hasHeavyPart() const override {
|
||||
return _content->hasHeavyPart();
|
||||
|
@ -57,11 +57,22 @@ namespace {
|
||||
Sticker::Sticker(
|
||||
not_null<Element*> parent,
|
||||
not_null<DocumentData*> data,
|
||||
Element *replacing,
|
||||
const Lottie::ColorReplacements *replacements)
|
||||
: _parent(parent)
|
||||
, _data(data)
|
||||
, _replacements(replacements) {
|
||||
_data->loadThumbnail(parent->data()->fullId());
|
||||
if ((_dataMedia = _data->activeMediaView())) {
|
||||
dataMediaCreated();
|
||||
} else {
|
||||
_data->loadThumbnail(parent->data()->fullId());
|
||||
}
|
||||
if (const auto media = replacing ? replacing->media() : nullptr) {
|
||||
_lottie = media->stickerTakeLottie();
|
||||
if (_lottie) {
|
||||
lottieCreated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sticker::~Sticker() {
|
||||
@ -266,6 +277,12 @@ void Sticker::ensureDataMediaCreated() const {
|
||||
return;
|
||||
}
|
||||
_dataMedia = _data->createMediaView();
|
||||
dataMediaCreated();
|
||||
}
|
||||
|
||||
void Sticker::dataMediaCreated() const {
|
||||
Expects(_dataMedia != nullptr);
|
||||
|
||||
_dataMedia->goodThumbnailWanted();
|
||||
_dataMedia->thumbnailWanted(_parent->data()->fullId());
|
||||
_parent->history()->owner().registerHeavyViewPart(_parent);
|
||||
@ -285,6 +302,12 @@ void Sticker::setupLottie() {
|
||||
Stickers::LottieSize::MessageHistory,
|
||||
_size * cIntRetinaFactor(),
|
||||
Lottie::Quality::High);
|
||||
lottieCreated();
|
||||
}
|
||||
|
||||
void Sticker::lottieCreated() {
|
||||
Expects(_lottie != nullptr);
|
||||
|
||||
_parent->history()->owner().registerHeavyViewPart(_parent);
|
||||
|
||||
_lottie->updates(
|
||||
@ -318,4 +341,8 @@ void Sticker::unloadLottie() {
|
||||
_parent->checkHeavyPart();
|
||||
}
|
||||
|
||||
std::unique_ptr< Lottie::SinglePlayer> Sticker::stickerTakeLottie() {
|
||||
return std::move(_lottie);
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
Sticker(
|
||||
not_null<Element*> parent,
|
||||
not_null<DocumentData*> data,
|
||||
Element *replacing = nullptr,
|
||||
const Lottie::ColorReplacements *replacements = nullptr);
|
||||
~Sticker();
|
||||
|
||||
@ -46,9 +47,10 @@ public:
|
||||
DocumentData *document() override {
|
||||
return _data;
|
||||
}
|
||||
void clearStickerLoopPlayed() override {
|
||||
void stickerClearLoopPlayed() override {
|
||||
_lottieOncePlayed = false;
|
||||
}
|
||||
std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie() override;
|
||||
|
||||
bool hasHeavyPart() const override;
|
||||
void unloadHeavyPart() override;
|
||||
@ -74,8 +76,10 @@ private:
|
||||
[[nodiscard]] QPixmap paintedPixmap(bool selected) const;
|
||||
|
||||
void ensureDataMediaCreated() const;
|
||||
void dataMediaCreated() const;
|
||||
|
||||
void setupLottie();
|
||||
void lottieCreated();
|
||||
void unloadLottie();
|
||||
|
||||
const not_null<Element*> _parent;
|
||||
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "layout.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/history_item.h"
|
||||
@ -199,10 +200,17 @@ QSize WebPage::countOptimalSize() {
|
||||
- st::msgPadding.right()
|
||||
- st::webPageLeft);
|
||||
}
|
||||
auto context = Core::UiIntegration::Context();
|
||||
if (_data->siteName == qstr("Twitter")) {
|
||||
context.type = Core::UiIntegration::HashtagMentionType::Twitter;
|
||||
} else if (_data->siteName == qstr("Instagram")) {
|
||||
context.type = Core::UiIntegration::HashtagMentionType::Instagram;
|
||||
}
|
||||
_description.setMarkedText(
|
||||
st::webPageDescriptionStyle,
|
||||
text,
|
||||
Ui::WebpageTextDescriptionOptions(_data->siteName));
|
||||
Ui::WebpageTextDescriptionOptions(),
|
||||
context);
|
||||
}
|
||||
if (!displayedSiteName().isEmpty()) {
|
||||
_siteNameLines = 1;
|
||||
|
@ -2107,11 +2107,11 @@ void ListWidget::mouseActionFinish(
|
||||
//_widget->noSelectingScroll(); // #TODO scroll by drag
|
||||
//_widget->updateTopBarSelection();
|
||||
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
//if (hasSelectedText()) { // #TODO linux clipboard
|
||||
// TextUtilities::SetClipboardText(_selected.cbegin()->first->selectedText(_selected.cbegin()->second), QClipboard::Selection);
|
||||
//}
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
}
|
||||
|
||||
void ListWidget::applyDragSelection() {
|
||||
|
@ -550,7 +550,7 @@ void Sticker::prepareThumbnail() const {
|
||||
}
|
||||
_dataMedia->checkStickerSmall();
|
||||
if (const auto sticker = _dataMedia->getStickerSmall()) {
|
||||
if (!_lottie && !_thumbLoaded && _dataMedia->loaded()) {
|
||||
if (!_lottie && !_thumbLoaded) {
|
||||
const auto thumbSize = getThumbSize();
|
||||
_thumb = sticker->pix(
|
||||
thumbSize.width(),
|
||||
@ -679,8 +679,6 @@ Video::Video(not_null<Context*> context, not_null<Result*> result)
|
||||
, _link(getResultPreviewHandler())
|
||||
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
|
||||
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {
|
||||
Assert(getResultDocument() != nullptr);
|
||||
|
||||
if (int duration = content_duration()) {
|
||||
_duration = formatDurationText(duration);
|
||||
_durationWidth = st::normalFont->width(_duration);
|
||||
@ -688,10 +686,12 @@ Video::Video(not_null<Context*> context, not_null<Result*> result)
|
||||
}
|
||||
|
||||
bool Video::withThumbnail() const {
|
||||
const auto document = getShownDocument();
|
||||
Assert(document != nullptr);
|
||||
|
||||
return document->hasThumbnail();
|
||||
if (const auto document = getShownDocument()) {
|
||||
if (document->hasThumbnail()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return hasResultThumb();
|
||||
}
|
||||
|
||||
void Video::initDimensions() {
|
||||
@ -761,6 +761,7 @@ void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) co
|
||||
|
||||
void Video::unloadHeavyPart() {
|
||||
_documentMedia = nullptr;
|
||||
ItemBase::unloadHeavyPart();
|
||||
}
|
||||
|
||||
TextState Video::getState(
|
||||
@ -776,17 +777,20 @@ TextState Video::getState(
|
||||
}
|
||||
|
||||
void Video::prepareThumbnail(QSize size) const {
|
||||
const auto document = getShownDocument();
|
||||
if (document->hasThumbnail()) {
|
||||
if (!_documentMedia) {
|
||||
_documentMedia = document->createMediaView();
|
||||
_documentMedia->thumbnailWanted(fileOrigin());
|
||||
}
|
||||
if (!_documentMedia->thumbnail()) {
|
||||
return;
|
||||
if (const auto document = getShownDocument()) {
|
||||
if (document->hasThumbnail()) {
|
||||
if (!_documentMedia) {
|
||||
_documentMedia = document->createMediaView();
|
||||
_documentMedia->thumbnailWanted(fileOrigin());
|
||||
}
|
||||
if (!_documentMedia->thumbnail()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto thumb = _documentMedia->thumbnail();
|
||||
const auto thumb = _documentMedia
|
||||
? _documentMedia->thumbnail()
|
||||
: getResultThumb(fileOrigin());
|
||||
if (!thumb) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,7 +162,6 @@ std::unique_ptr<Result> Result::Create(
|
||||
}
|
||||
} else if (result->_type == Type::Audio
|
||||
|| result->_type == Type::File
|
||||
|| result->_type == Type::Video
|
||||
|| result->_type == Type::Sticker
|
||||
|| result->_type == Type::Gif) {
|
||||
if (!result->_document) {
|
||||
@ -175,24 +174,28 @@ std::unique_ptr<Result> Result::Create(
|
||||
const auto &r = message->c_botInlineMessageMediaAuto();
|
||||
const auto message = qs(r.vmessage());
|
||||
const auto entities = Api::EntitiesFromMTP(
|
||||
session,
|
||||
r.ventities().value_or_empty());
|
||||
if (result->_type == Type::Photo) {
|
||||
if (!result->_photo) {
|
||||
return nullptr;
|
||||
}
|
||||
result->sendData = std::make_unique<internal::SendPhoto>(
|
||||
session,
|
||||
result->_photo,
|
||||
message,
|
||||
entities);
|
||||
} else if (result->_type == Type::Game) {
|
||||
result->createGame();
|
||||
result->sendData = std::make_unique<internal::SendGame>(
|
||||
session,
|
||||
result->_game);
|
||||
} else {
|
||||
if (!result->_document) {
|
||||
return nullptr;
|
||||
}
|
||||
result->sendData = std::make_unique<internal::SendFile>(
|
||||
session,
|
||||
result->_document,
|
||||
message,
|
||||
entities);
|
||||
@ -205,22 +208,10 @@ std::unique_ptr<Result> Result::Create(
|
||||
case mtpc_botInlineMessageText: {
|
||||
const auto &r = message->c_botInlineMessageText();
|
||||
result->sendData = std::make_unique<internal::SendText>(
|
||||
session,
|
||||
qs(r.vmessage()),
|
||||
Api::EntitiesFromMTP(r.ventities().value_or_empty()),
|
||||
Api::EntitiesFromMTP(session, r.ventities().value_or_empty()),
|
||||
r.is_no_webpage());
|
||||
if (result->_type == Type::Photo) {
|
||||
if (!result->_photo) {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (result->_type == Type::Audio
|
||||
|| result->_type == Type::File
|
||||
|| result->_type == Type::Video
|
||||
|| result->_type == Type::Sticker
|
||||
|| result->_type == Type::Gif) {
|
||||
if (!result->_document) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (const auto markup = r.vreply_markup()) {
|
||||
result->_mtpKeyboard = std::make_unique<MTPReplyMarkup>(*markup);
|
||||
}
|
||||
@ -230,7 +221,9 @@ std::unique_ptr<Result> Result::Create(
|
||||
// #TODO layer 72 save period and send live location?..
|
||||
auto &r = message->c_botInlineMessageMediaGeo();
|
||||
if (r.vgeo().type() == mtpc_geoPoint) {
|
||||
result->sendData = std::make_unique<internal::SendGeo>(r.vgeo().c_geoPoint());
|
||||
result->sendData = std::make_unique<internal::SendGeo>(
|
||||
session,
|
||||
r.vgeo().c_geoPoint());
|
||||
} else {
|
||||
badAttachment = true;
|
||||
}
|
||||
@ -242,7 +235,13 @@ std::unique_ptr<Result> Result::Create(
|
||||
case mtpc_botInlineMessageMediaVenue: {
|
||||
auto &r = message->c_botInlineMessageMediaVenue();
|
||||
if (r.vgeo().type() == mtpc_geoPoint) {
|
||||
result->sendData = std::make_unique<internal::SendVenue>(r.vgeo().c_geoPoint(), qs(r.vvenue_id()), qs(r.vprovider()), qs(r.vtitle()), qs(r.vaddress()));
|
||||
result->sendData = std::make_unique<internal::SendVenue>(
|
||||
session,
|
||||
r.vgeo().c_geoPoint(),
|
||||
qs(r.vvenue_id()),
|
||||
qs(r.vprovider()),
|
||||
qs(r.vtitle()),
|
||||
qs(r.vaddress()));
|
||||
} else {
|
||||
badAttachment = true;
|
||||
}
|
||||
@ -253,7 +252,11 @@ std::unique_ptr<Result> Result::Create(
|
||||
|
||||
case mtpc_botInlineMessageMediaContact: {
|
||||
auto &r = message->c_botInlineMessageMediaContact();
|
||||
result->sendData = std::make_unique<internal::SendContact>(qs(r.vfirst_name()), qs(r.vlast_name()), qs(r.vphone_number()));
|
||||
result->sendData = std::make_unique<internal::SendContact>(
|
||||
session,
|
||||
qs(r.vfirst_name()),
|
||||
qs(r.vlast_name()),
|
||||
qs(r.vphone_number()));
|
||||
if (const auto markup = r.vreply_markup()) {
|
||||
result->_mtpKeyboard = std::make_unique<MTPReplyMarkup>(*markup);
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ QString SendDataCommon::getErrorOnSend(
|
||||
SendDataCommon::SentMTPMessageFields SendText::getSentMessageFields() const {
|
||||
SentMTPMessageFields result;
|
||||
result.text = MTP_string(_message);
|
||||
result.entities = Api::EntitiesToMTP(_entities);
|
||||
result.entities = Api::EntitiesToMTP(&session(), _entities);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "history/history_location_manager.h"
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
class History;
|
||||
|
||||
namespace InlineBots {
|
||||
@ -22,11 +26,16 @@ namespace internal {
|
||||
// For each type of message that can be sent there will be a subclass.
|
||||
class SendData {
|
||||
public:
|
||||
SendData() = default;
|
||||
explicit SendData(not_null<Main::Session*> session) : _session(session) {
|
||||
}
|
||||
SendData(const SendData &other) = delete;
|
||||
SendData &operator=(const SendData &other) = delete;
|
||||
virtual ~SendData() = default;
|
||||
|
||||
[[nodiscard]] Main::Session &session() const {
|
||||
return *_session;
|
||||
}
|
||||
|
||||
virtual bool isValid() const = 0;
|
||||
|
||||
virtual void addToHistory(
|
||||
@ -54,6 +63,9 @@ public:
|
||||
virtual QString getLayoutTitle(const Result *owner) const;
|
||||
virtual QString getLayoutDescription(const Result *owner) const;
|
||||
|
||||
private:
|
||||
not_null<Main::Session*> _session;
|
||||
|
||||
};
|
||||
|
||||
// This class implements addHistory() for most of the types hiding
|
||||
@ -61,6 +73,8 @@ public:
|
||||
// Only SendFile and SendPhoto work by their own.
|
||||
class SendDataCommon : public SendData {
|
||||
public:
|
||||
using SendData::SendData;
|
||||
|
||||
struct SentMTPMessageFields {
|
||||
MTPString text = MTP_string();
|
||||
MTPVector<MTPMessageEntity> entities = MTP_vector<MTPMessageEntity>();
|
||||
@ -91,10 +105,12 @@ public:
|
||||
class SendText : public SendDataCommon {
|
||||
public:
|
||||
SendText(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &message,
|
||||
const EntitiesInText &entities,
|
||||
bool/* noWebPage*/)
|
||||
: _message(message)
|
||||
: SendDataCommon(session)
|
||||
, _message(message)
|
||||
, _entities(entities) {
|
||||
}
|
||||
|
||||
@ -113,7 +129,11 @@ private:
|
||||
// Message with geo location point media.
|
||||
class SendGeo : public SendDataCommon {
|
||||
public:
|
||||
explicit SendGeo(const MTPDgeoPoint &point) : _location(point) {
|
||||
SendGeo(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDgeoPoint &point)
|
||||
: SendDataCommon(session)
|
||||
, _location(point) {
|
||||
}
|
||||
|
||||
bool isValid() const override {
|
||||
@ -137,13 +157,19 @@ private:
|
||||
// Message with venue media.
|
||||
class SendVenue : public SendDataCommon {
|
||||
public:
|
||||
SendVenue(const MTPDgeoPoint &point, const QString &venueId,
|
||||
const QString &provider, const QString &title, const QString &address)
|
||||
: _location(point)
|
||||
, _venueId(venueId)
|
||||
, _provider(provider)
|
||||
, _title(title)
|
||||
, _address(address) {
|
||||
SendVenue(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDgeoPoint &point,
|
||||
const QString &venueId,
|
||||
const QString &provider,
|
||||
const QString &title,
|
||||
const QString &address)
|
||||
: SendDataCommon(session)
|
||||
, _location(point)
|
||||
, _venueId(venueId)
|
||||
, _provider(provider)
|
||||
, _title(title)
|
||||
, _address(address) {
|
||||
}
|
||||
|
||||
bool isValid() const override {
|
||||
@ -168,10 +194,15 @@ private:
|
||||
// Message with shared contact media.
|
||||
class SendContact : public SendDataCommon {
|
||||
public:
|
||||
SendContact(const QString &firstName, const QString &lastName, const QString &phoneNumber)
|
||||
: _firstName(firstName)
|
||||
, _lastName(lastName)
|
||||
, _phoneNumber(phoneNumber) {
|
||||
SendContact(
|
||||
not_null<Main::Session*> session,
|
||||
const QString &firstName,
|
||||
const QString &lastName,
|
||||
const QString &phoneNumber)
|
||||
: SendDataCommon(session)
|
||||
, _firstName(firstName)
|
||||
, _lastName(lastName)
|
||||
, _phoneNumber(phoneNumber) {
|
||||
}
|
||||
|
||||
bool isValid() const override {
|
||||
@ -191,10 +222,12 @@ private:
|
||||
class SendPhoto : public SendData {
|
||||
public:
|
||||
SendPhoto(
|
||||
not_null<Main::Session*> session,
|
||||
PhotoData *photo,
|
||||
const QString &message,
|
||||
const EntitiesInText &entities)
|
||||
: _photo(photo)
|
||||
: SendData(session)
|
||||
, _photo(photo)
|
||||
, _message(message)
|
||||
, _entities(entities) {
|
||||
}
|
||||
@ -231,10 +264,12 @@ private:
|
||||
class SendFile : public SendData {
|
||||
public:
|
||||
SendFile(
|
||||
not_null<Main::Session*> session,
|
||||
DocumentData *document,
|
||||
const QString &message,
|
||||
const EntitiesInText &entities)
|
||||
: _document(document)
|
||||
: SendData(session)
|
||||
, _document(document)
|
||||
, _message(message)
|
||||
, _entities(entities) {
|
||||
}
|
||||
@ -270,8 +305,9 @@ private:
|
||||
// Message with game.
|
||||
class SendGame : public SendData {
|
||||
public:
|
||||
SendGame(GameData *game)
|
||||
: _game(game) {
|
||||
SendGame(not_null<Main::Session*> session, GameData *game)
|
||||
: SendData(session)
|
||||
, _game(game) {
|
||||
}
|
||||
|
||||
bool isValid() const override {
|
||||
|
@ -248,7 +248,9 @@ void CodeWidget::codeSubmitDone(const MTPauth_Authorization &result) {
|
||||
}, [&](const MTPDauth_authorizationSignUpRequired &data) {
|
||||
if (const auto terms = data.vterms_of_service()) {
|
||||
terms->match([&](const MTPDhelp_termsOfService &data) {
|
||||
getData()->termsLock = Window::TermsLock::FromMTP(data);
|
||||
getData()->termsLock = Window::TermsLock::FromMTP(
|
||||
nullptr,
|
||||
data);
|
||||
});
|
||||
} else {
|
||||
getData()->termsLock = Window::TermsLock();
|
||||
|
@ -146,7 +146,7 @@ void Widget::handleUpdate(const MTPUpdate &update) {
|
||||
}, [&](const MTPDupdateServiceNotification &data) {
|
||||
const auto text = TextWithEntities{
|
||||
qs(data.vmessage()),
|
||||
Api::EntitiesFromMTP(data.ventities().v)
|
||||
Api::EntitiesFromMTP(nullptr, data.ventities().v)
|
||||
};
|
||||
Ui::show(Box<InformBox>(text));
|
||||
}, [](const auto &) {});
|
||||
|
@ -343,7 +343,7 @@ void start(not_null<Core::Launcher*> launcher) {
|
||||
workingDirChosen = true;
|
||||
} else {
|
||||
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#ifdef Q_OS_UNIX
|
||||
|
||||
if (!cWorkingDir().isEmpty()) {
|
||||
// This value must come from TelegramForcePortable
|
||||
@ -358,16 +358,16 @@ void start(not_null<Core::Launcher*> launcher) {
|
||||
}
|
||||
workingDirChosen = true;
|
||||
|
||||
#if defined Q_OS_LINUX && !defined _DEBUG // fix first version
|
||||
#if !defined Q_OS_MAC && !defined _DEBUG // fix first version
|
||||
moveOldDataFrom = initialWorkingDir;
|
||||
#endif // Q_OS_LINUX && !_DEBUG
|
||||
#endif // !Q_OS_MAC && !_DEBUG
|
||||
|
||||
#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT // Q_OS_UNIX
|
||||
|
||||
cForceWorkingDir(psAppDataPath());
|
||||
workingDirChosen = true;
|
||||
|
||||
#elif defined OS_WIN_STORE // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT
|
||||
#elif defined OS_WIN_STORE // Q_OS_UNIX || Q_OS_WINRT
|
||||
|
||||
#ifdef _DEBUG
|
||||
cForceWorkingDir(cExeDir());
|
||||
@ -385,7 +385,7 @@ void start(not_null<Core::Launcher*> launcher) {
|
||||
workingDirChosen = true;
|
||||
}
|
||||
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || OS_WIN_STORE
|
||||
#endif // Q_OS_UNIX || Q_OS_WINRT || OS_WIN_STORE
|
||||
|
||||
}
|
||||
|
||||
@ -561,7 +561,7 @@ void writeDebug(const char *file, int32 line, const QString &v) {
|
||||
//OutputDebugString(reinterpret_cast<const wchar_t *>(msg.utf16()));
|
||||
#elif defined Q_OS_MAC
|
||||
//objc_outputDebugString(msg);
|
||||
#elif defined Q_OS_LINUX && defined _DEBUG
|
||||
#elif defined Q_OS_UNIX && defined _DEBUG
|
||||
//std::cout << msg.toUtf8().constData();
|
||||
#endif
|
||||
}
|
||||
|
@ -400,6 +400,15 @@ MainWidget::MainWidget(
|
||||
floatPlayerClosed(itemId);
|
||||
}, lifetime());
|
||||
|
||||
// Load current userpic and keep it loaded.
|
||||
Notify::PeerUpdateValue(
|
||||
session().user(),
|
||||
Notify::PeerUpdate::Flag::PhotoChanged
|
||||
) | rpl::start_with_next([=] {
|
||||
[[maybe_unused]] const auto image = session().user()->currentUserpic(
|
||||
_selfUserpicView);
|
||||
}, lifetime());
|
||||
|
||||
_ptsWaiter.setRequesting(true);
|
||||
updateScrollColors();
|
||||
setupConnectingWidget();
|
||||
@ -3821,7 +3830,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||
}
|
||||
item->updateSentContent({
|
||||
sent.text,
|
||||
Api::EntitiesFromMTP(list.value_or_empty())
|
||||
Api::EntitiesFromMTP(&session(), list.value_or_empty())
|
||||
}, d.vmedia());
|
||||
item->contributeToSlowmode(d.vdate().v);
|
||||
if (!wasAlready) {
|
||||
@ -4330,7 +4339,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
const auto &d = update.c_updateServiceNotification();
|
||||
const auto text = TextWithEntities {
|
||||
qs(d.vmessage()),
|
||||
Api::EntitiesFromMTP(d.ventities().v)
|
||||
Api::EntitiesFromMTP(&session(), d.ventities().v)
|
||||
};
|
||||
if (IsForceLogoutNotification(d)) {
|
||||
Core::App().forceLogOut(text);
|
||||
@ -4604,9 +4613,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||
const auto &data = update.c_updateDraftMessage();
|
||||
const auto peerId = peerFromMTP(data.vpeer());
|
||||
data.vdraft().match([&](const MTPDdraftMessage &data) {
|
||||
Data::applyPeerCloudDraft(peerId, data);
|
||||
Data::ApplyPeerCloudDraft(&session(), peerId, data);
|
||||
}, [&](const MTPDdraftMessageEmpty &data) {
|
||||
Data::clearPeerCloudDraft(
|
||||
Data::ClearPeerCloudDraft(
|
||||
&session(),
|
||||
peerId,
|
||||
data.vdate().value_or_empty());
|
||||
});
|
||||
|
@ -38,6 +38,7 @@ struct PeerUpdate;
|
||||
|
||||
namespace Data {
|
||||
class WallPaper;
|
||||
class CloudImageView;
|
||||
} // namespace Data
|
||||
|
||||
namespace Dialogs {
|
||||
@ -107,7 +108,9 @@ class MainWidget
|
||||
public:
|
||||
using SectionShow = Window::SectionShow;
|
||||
|
||||
MainWidget(QWidget *parent, not_null<Window::SessionController*> controller);
|
||||
MainWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
|
||||
@ -463,6 +466,8 @@ private:
|
||||
int _thirdColumnWidth = 0;
|
||||
Ui::Animations::Simple _a_dialogsWidth;
|
||||
|
||||
std::shared_ptr<Data::CloudImageView> _selfUserpicView;
|
||||
|
||||
object_ptr<Ui::PlainShadow> _sideShadow;
|
||||
object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr };
|
||||
object_ptr<Ui::ResizeArea> _firstColumnResizeArea = { nullptr };
|
||||
|
@ -139,7 +139,7 @@ void MainWindow::createTrayIconMenu() {
|
||||
? tr::ktg_settings_disable_sound_from_tray(tr::now)
|
||||
: tr::ktg_settings_enable_sound_from_tray(tr::now);
|
||||
|
||||
if (Platform::IsLinux()) {
|
||||
if (Platform::IsLinux() && !Platform::IsWayland()) {
|
||||
trayIconMenu->addAction(tr::ktg_open_from_tray(tr::now), this, SLOT(showFromTray()));
|
||||
}
|
||||
trayIconMenu->addAction(tr::lng_minimize_to_tray(tr::now), this, SLOT(minimizeToTray()));
|
||||
@ -593,12 +593,12 @@ void MainWindow::updateTrayMenu(bool force) {
|
||||
if (!trayIconMenu || (Platform::IsWindows() && !force)) return;
|
||||
|
||||
auto actions = trayIconMenu->actions();
|
||||
if (Platform::IsLinux()) {
|
||||
if (Platform::IsLinux() && !Platform::IsWayland()) {
|
||||
auto minimizeAction = actions.at(1);
|
||||
minimizeAction->setEnabled(isVisible());
|
||||
} else {
|
||||
updateIsActive(0);
|
||||
auto active = isActive();
|
||||
auto active = Platform::IsWayland() ? isVisible() : isActive();
|
||||
auto toggleAction = actions.at(0);
|
||||
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
|
||||
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(showFromTray()));
|
||||
@ -607,7 +607,7 @@ void MainWindow::updateTrayMenu(bool force) {
|
||||
? tr::lng_minimize_to_tray(tr::now)
|
||||
: tr::ktg_open_from_tray(tr::now));
|
||||
}
|
||||
auto notificationAction = actions.at(Platform::IsLinux() ? 2 : 1);
|
||||
auto notificationAction = actions.at(Platform::IsLinux() && !Platform::IsWayland() ? 2 : 1);
|
||||
auto notificationActionText = Global::DesktopNotify()
|
||||
? tr::lng_disable_notifications_from_tray(tr::now)
|
||||
: tr::lng_enable_notifications_from_tray(tr::now);
|
||||
@ -738,7 +738,7 @@ void MainWindow::handleTrayIconActication(
|
||||
updateTrayMenu(true);
|
||||
QTimer::singleShot(1, this, SLOT(psShowTrayMenu()));
|
||||
} else if (!skipTrayClick()) {
|
||||
if (isActive()) {
|
||||
if (Platform::IsWayland() ? isVisible() : isActive()) {
|
||||
minimizeToTray();
|
||||
} else {
|
||||
showFromTray(reason);
|
||||
|
@ -353,11 +353,11 @@ OverlayWidget::OverlayWidget()
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::MaximizeUsingFullscreenGeometryHint);
|
||||
#else // Q_OS_LINUX
|
||||
#else // Q_OS_UNIX && !Q_OS_MAC
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
#endif // Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
moveToScreen();
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
@ -1538,6 +1538,21 @@ Data::FileOrigin OverlayWidget::fileOrigin() const {
|
||||
return Data::FileOrigin();
|
||||
}
|
||||
|
||||
Data::FileOrigin OverlayWidget::fileOrigin(const Entity &entity) const {
|
||||
if (const auto item = entity.item) {
|
||||
return item->fullId();
|
||||
} else if (!entity.data.is<not_null<PhotoData*>>()) {
|
||||
return Data::FileOrigin();
|
||||
}
|
||||
const auto photo = entity.data.get_unchecked<not_null<PhotoData*>>();
|
||||
if (_user) {
|
||||
return Data::FileOriginUserPhoto(_user->bareId(), photo->id);
|
||||
} else if (_peer && _peer->userpicPhotoId() == photo->id) {
|
||||
return Data::FileOriginPeerPhoto(_peer->id);
|
||||
}
|
||||
return Data::FileOrigin();
|
||||
}
|
||||
|
||||
bool OverlayWidget::validSharedMedia() const {
|
||||
if (auto key = sharedMediaKey()) {
|
||||
if (!_sharedMedia) {
|
||||
@ -1883,8 +1898,6 @@ void OverlayWidget::showPhoto(not_null<PhotoData*> photo, HistoryItem *context)
|
||||
_firstOpenedPeerPhoto = false;
|
||||
assignMediaPointer(photo);
|
||||
|
||||
refreshMediaViewer();
|
||||
|
||||
displayPhoto(photo, context);
|
||||
preloadData(0);
|
||||
activateControls();
|
||||
@ -1897,8 +1910,6 @@ void OverlayWidget::showPhoto(not_null<PhotoData*> photo, not_null<PeerData*> co
|
||||
_firstOpenedPeerPhoto = true;
|
||||
assignMediaPointer(photo);
|
||||
|
||||
refreshMediaViewer();
|
||||
|
||||
displayPhoto(photo, nullptr);
|
||||
preloadData(0);
|
||||
activateControls();
|
||||
@ -2031,6 +2042,7 @@ void OverlayWidget::displayDocument(
|
||||
initThemePreview();
|
||||
} else {
|
||||
_documentMedia->automaticLoad(fileOrigin(), item);
|
||||
_document->saveFromDataSilent();
|
||||
auto &location = _document->location(true);
|
||||
if (location.accessEnable()) {
|
||||
const auto &path = location.name();
|
||||
@ -2144,11 +2156,11 @@ void OverlayWidget::displayFinished() {
|
||||
updateControls();
|
||||
if (isHidden()) {
|
||||
Ui::Platform::UpdateOverlayed(this);
|
||||
#ifdef Q_OS_LINUX
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
showFullScreen();
|
||||
#else // Q_OS_LINUX
|
||||
#else // Q_OS_UNIX && !Q_OS_MAC
|
||||
show();
|
||||
#endif // Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
Ui::Platform::ShowOverAll(this);
|
||||
activateWindow();
|
||||
QApplication::setActiveWindow(this);
|
||||
@ -3420,16 +3432,17 @@ OverlayWidget::Entity OverlayWidget::entityByIndex(int index) const {
|
||||
return { std::nullopt, nullptr };
|
||||
}
|
||||
|
||||
void OverlayWidget::setContext(base::optional_variant<
|
||||
void OverlayWidget::setContext(
|
||||
base::optional_variant<
|
||||
not_null<HistoryItem*>,
|
||||
not_null<PeerData*>> context) {
|
||||
if (auto item = base::get_if<not_null<HistoryItem*>>(&context)) {
|
||||
if (const auto item = base::get_if<not_null<HistoryItem*>>(&context)) {
|
||||
_msgid = (*item)->fullId();
|
||||
_canForwardItem = (*item)->allowsForward();
|
||||
_canDeleteItem = (*item)->canDelete();
|
||||
_history = (*item)->history();
|
||||
_peer = _history->peer;
|
||||
} else if (auto peer = base::get_if<not_null<PeerData*>>(&context)) {
|
||||
} else if (const auto peer = base::get_if<not_null<PeerData*>>(&context)) {
|
||||
_msgid = FullMsgId();
|
||||
_canForwardItem = _canDeleteItem = false;
|
||||
_history = (*peer)->owner().history(*peer);
|
||||
@ -3498,15 +3511,15 @@ void OverlayWidget::preloadData(int delta) {
|
||||
auto entity = entityByIndex(index);
|
||||
if (auto photo = base::get_if<not_null<PhotoData*>>(&entity.data)) {
|
||||
const auto [i, ok] = photos.emplace((*photo)->createMediaView());
|
||||
(*i)->wanted(Data::PhotoSize::Small, fileOrigin());
|
||||
(*photo)->load(fileOrigin(), LoadFromCloudOrLocal, true);
|
||||
(*i)->wanted(Data::PhotoSize::Small, fileOrigin(entity));
|
||||
(*photo)->load(fileOrigin(entity), LoadFromCloudOrLocal, true);
|
||||
} else if (auto document = base::get_if<not_null<DocumentData*>>(
|
||||
&entity.data)) {
|
||||
const auto [i, ok] = documents.emplace(
|
||||
(*document)->createMediaView());
|
||||
(*i)->thumbnailWanted(fileOrigin());
|
||||
(*i)->thumbnailWanted(fileOrigin(entity));
|
||||
if (!(*i)->canBePlayed()) {
|
||||
(*i)->automaticLoad(fileOrigin(), entity.item);
|
||||
(*i)->automaticLoad(fileOrigin(entity), entity.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +239,8 @@ private:
|
||||
bool validCollage() const;
|
||||
void validateCollage();
|
||||
|
||||
Data::FileOrigin fileOrigin() const;
|
||||
[[nodiscard]] Data::FileOrigin fileOrigin() const;
|
||||
[[nodiscard]] Data::FileOrigin fileOrigin(const Entity& entity) const;
|
||||
|
||||
void refreshFromLabel(HistoryItem *item);
|
||||
void refreshCaption(HistoryItem *item);
|
||||
|
@ -438,7 +438,8 @@ PipPanel::Position PipPanel::countPosition() const {
|
||||
const auto right = left + result.geometry.width();
|
||||
const auto top = result.geometry.y();
|
||||
const auto bottom = top + result.geometry.height();
|
||||
if (!_dragState || *_dragState != RectPart::Center) {
|
||||
if ((!_dragState || *_dragState != RectPart::Center)
|
||||
&& !Platform::IsWayland()) {
|
||||
if (left == available.x()) {
|
||||
result.attached |= RectPart::Left;
|
||||
} else if (right == available.x() + available.width()) {
|
||||
@ -514,6 +515,11 @@ void PipPanel::setPositionOnScreen(Position position, QRect available) {
|
||||
std::max(normalized.width(), minimalSize.width()),
|
||||
std::max(normalized.height(), minimalSize.height()));
|
||||
|
||||
// Apply maximal size.
|
||||
const auto maximalSize = (_ratio.width() > _ratio.height())
|
||||
? QSize(fit.width(), fit.width() * _ratio.height() / _ratio.width())
|
||||
: QSize(fit.height() * _ratio.width() / _ratio.height(), fit.height());
|
||||
|
||||
// Apply left-right screen borders.
|
||||
const auto skip = st::pipBorderSkip;
|
||||
const auto inner = screen.marginsRemoved({ skip, skip, skip, skip });
|
||||
@ -547,8 +553,10 @@ void PipPanel::setPositionOnScreen(Position position, QRect available) {
|
||||
geometry += _padding;
|
||||
|
||||
setGeometry(geometry);
|
||||
setMinimumSize(geometry.size());
|
||||
setMaximumSize(geometry.size());
|
||||
setMinimumSize(minimalSize);
|
||||
setMaximumSize(
|
||||
std::max(minimalSize.width(), maximalSize.width()),
|
||||
std::max(minimalSize.height(), maximalSize.height()));
|
||||
updateDecorations();
|
||||
update();
|
||||
}
|
||||
@ -671,6 +679,40 @@ void PipPanel::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (!_dragState
|
||||
&& (point - _pressPoint).manhattanLength() > distance
|
||||
&& !_dragDisabled) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
|
||||
if (Platform::IsWayland()) {
|
||||
switch (*_pressState) {
|
||||
case RectPart::Center:
|
||||
windowHandle()->startSystemMove();
|
||||
break;
|
||||
case RectPart::TopLeft:
|
||||
windowHandle()->startSystemResize(Qt::TopEdge | Qt::LeftEdge);
|
||||
break;
|
||||
case RectPart::TopRight:
|
||||
windowHandle()->startSystemResize(Qt::TopEdge | Qt::RightEdge);
|
||||
break;
|
||||
case RectPart::BottomRight:
|
||||
windowHandle()->startSystemResize(Qt::BottomEdge | Qt::RightEdge);
|
||||
break;
|
||||
case RectPart::BottomLeft:
|
||||
windowHandle()->startSystemResize(Qt::BottomEdge | Qt::LeftEdge);
|
||||
break;
|
||||
case RectPart::Left:
|
||||
windowHandle()->startSystemResize(Qt::LeftEdge);
|
||||
break;
|
||||
case RectPart::Top:
|
||||
windowHandle()->startSystemResize(Qt::TopEdge);
|
||||
break;
|
||||
case RectPart::Right:
|
||||
windowHandle()->startSystemResize(Qt::RightEdge);
|
||||
break;
|
||||
case RectPart::Bottom:
|
||||
windowHandle()->startSystemResize(Qt::BottomEdge);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
|
||||
_dragState = _pressState;
|
||||
updateDecorations();
|
||||
_dragStartGeometry = geometry().marginsRemoved(_padding);
|
||||
@ -722,8 +764,6 @@ void PipPanel::processDrag(QPoint point) {
|
||||
const auto newGeometry = valid.marginsAdded(_padding);
|
||||
_positionAnimation.stop();
|
||||
setGeometry(newGeometry);
|
||||
setMinimumSize(newGeometry.size());
|
||||
setMaximumSize(newGeometry.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,8 +850,6 @@ void PipPanel::updateDecorations() {
|
||||
_useTransparency = use;
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
|
||||
setGeometry(newGeometry);
|
||||
setMinimumSize(newGeometry.size());
|
||||
setMaximumSize(newGeometry.size());
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -72,10 +72,10 @@ bool GdkHelperLoadGtk3(QLibrary &lib) {
|
||||
|
||||
void GdkHelperLoad(QLibrary &lib) {
|
||||
gdk_helper_loaded = GtkLoaded::GtkNone;
|
||||
if (GdkHelperLoadGtk2(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk2;
|
||||
} else if (GdkHelperLoadGtk3(lib)) {
|
||||
if (GdkHelperLoadGtk3(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk3;
|
||||
} else if (GdkHelperLoadGtk2(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,24 +69,19 @@ void gtkMessageHandler(
|
||||
bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
|
||||
if (!load(lib_gtk, "gtk_settings_get_default", gtk_settings_get_default)) return false;
|
||||
if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false;
|
||||
if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false;
|
||||
|
||||
if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false;
|
||||
if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false;
|
||||
if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false;
|
||||
if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false;
|
||||
if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false;
|
||||
if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
|
||||
if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
|
||||
if (!load(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false;
|
||||
if (!load(lib_gtk, "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image)) return false;
|
||||
if (!load(lib_gtk, "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image)) return false;
|
||||
if (!load(lib_gtk, "gtk_selection_data_free", gtk_selection_data_free)) return false;
|
||||
if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false;
|
||||
if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false;
|
||||
if (!load(lib_gtk, "gtk_image_get_type", gtk_image_get_type)) return false;
|
||||
@ -122,22 +117,23 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
|
||||
if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
|
||||
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
|
||||
if (!load(lib_gtk, "g_signal_handler_disconnect", g_signal_handler_disconnect)) return false;
|
||||
|
||||
if (!load(lib_gtk, "g_object_get", g_object_get)) return false;
|
||||
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
|
||||
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
|
||||
if (!load(lib_gtk, "g_free", g_free)) return false;
|
||||
if (!load(lib_gtk, "g_list_foreach", g_list_foreach)) return false;
|
||||
if (!load(lib_gtk, "g_list_free", g_list_free)) return false;
|
||||
if (!load(lib_gtk, "g_list_free_full", g_list_free_full)) return false;
|
||||
|
||||
if (!load(lib_gtk, "g_error_free", g_error_free)) return false;
|
||||
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
|
||||
|
||||
if (!load(lib_gtk, "g_log_set_handler", g_log_set_handler)) return false;
|
||||
if (!load(lib_gtk, "g_log_default_handler", g_log_default_handler)) return false;
|
||||
|
||||
if (!load(lib_gtk, "gdk_atom_intern", gdk_atom_intern)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_has_alpha", gdk_pixbuf_get_has_alpha)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_pixels", gdk_pixbuf_get_pixels)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_width", gdk_pixbuf_get_width)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_height", gdk_pixbuf_get_height)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_rowstride", gdk_pixbuf_get_rowstride)) return false;
|
||||
|
||||
if (load(lib_gtk, "gdk_set_allowed_backends", gdk_set_allowed_backends)) {
|
||||
// We work only with X11 GDK backend.
|
||||
// Otherwise we get segfault in Ubuntu 17.04 in gtk_init_check() call.
|
||||
@ -178,23 +174,18 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
f_gtk_init_check gtk_init_check = nullptr;
|
||||
f_gtk_settings_get_default gtk_settings_get_default = nullptr;
|
||||
f_gtk_menu_new gtk_menu_new = nullptr;
|
||||
f_gtk_menu_get_type gtk_menu_get_type = nullptr;
|
||||
f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label = nullptr;
|
||||
f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr;
|
||||
f_gtk_menu_shell_append gtk_menu_shell_append = nullptr;
|
||||
f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr;
|
||||
f_gtk_widget_show gtk_widget_show = nullptr;
|
||||
f_gtk_widget_hide gtk_widget_hide = nullptr;
|
||||
f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr;
|
||||
f_gtk_widget_get_visible gtk_widget_get_visible = nullptr;
|
||||
f_gtk_widget_get_window gtk_widget_get_window = nullptr;
|
||||
f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr;
|
||||
f_gtk_widget_realize gtk_widget_realize = nullptr;
|
||||
f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr;
|
||||
f_gtk_widget_destroy gtk_widget_destroy = nullptr;
|
||||
f_gtk_clipboard_get gtk_clipboard_get = nullptr;
|
||||
f_gtk_clipboard_store gtk_clipboard_store = nullptr;
|
||||
f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents = nullptr;
|
||||
f_gtk_clipboard_wait_for_image gtk_clipboard_wait_for_image = nullptr;
|
||||
f_gtk_selection_data_targets_include_image gtk_selection_data_targets_include_image = nullptr;
|
||||
f_gtk_selection_data_free gtk_selection_data_free = nullptr;
|
||||
f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr;
|
||||
f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr;
|
||||
f_gtk_image_get_type gtk_image_get_type = nullptr;
|
||||
@ -232,32 +223,16 @@ f_gtk_dialog_run gtk_dialog_run = nullptr;
|
||||
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
||||
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
|
||||
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
||||
f_g_signal_handler_disconnect g_signal_handler_disconnect = nullptr;
|
||||
f_gdk_init_check gdk_init_check = nullptr;
|
||||
f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr;
|
||||
f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file = nullptr;
|
||||
f_gdk_atom_intern gdk_atom_intern = nullptr;
|
||||
f_gdk_pixbuf_new_from_file_at_size gdk_pixbuf_new_from_file_at_size = nullptr;
|
||||
f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf = nullptr;
|
||||
f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf = nullptr;
|
||||
f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file = nullptr;
|
||||
f_gtk_status_icon_set_from_file gtk_status_icon_set_from_file = nullptr;
|
||||
f_gtk_status_icon_set_title gtk_status_icon_set_title = nullptr;
|
||||
f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text = nullptr;
|
||||
f_gtk_status_icon_set_visible gtk_status_icon_set_visible = nullptr;
|
||||
f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded = nullptr;
|
||||
f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry = nullptr;
|
||||
f_gtk_status_icon_position_menu gtk_status_icon_position_menu = nullptr;
|
||||
f_gtk_menu_popup gtk_menu_popup = nullptr;
|
||||
f_gtk_get_current_event_time gtk_get_current_event_time = nullptr;
|
||||
f_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha = nullptr;
|
||||
f_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels = nullptr;
|
||||
f_gdk_pixbuf_get_width gdk_pixbuf_get_width = nullptr;
|
||||
f_gdk_pixbuf_get_height gdk_pixbuf_get_height = nullptr;
|
||||
f_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride = nullptr;
|
||||
f_g_object_get g_object_get = nullptr;
|
||||
f_g_object_ref_sink g_object_ref_sink = nullptr;
|
||||
f_g_object_unref g_object_unref = nullptr;
|
||||
f_g_idle_add g_idle_add = nullptr;
|
||||
f_g_free g_free = nullptr;
|
||||
f_g_list_foreach g_list_foreach = nullptr;
|
||||
f_g_list_free g_list_free = nullptr;
|
||||
f_g_list_free_full g_list_free_full = nullptr;
|
||||
f_g_error_free g_error_free = nullptr;
|
||||
f_g_slist_free g_slist_free = nullptr;
|
||||
f_g_log_set_handler g_log_set_handler = nullptr;
|
||||
f_g_log_default_handler g_log_default_handler = nullptr;
|
||||
@ -265,6 +240,10 @@ f_g_log_default_handler g_log_default_handler = nullptr;
|
||||
|
||||
void start() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (!UseGtkIntegration()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(("Loading libraries"));
|
||||
|
||||
bool gtkLoaded = false;
|
||||
@ -279,23 +258,7 @@ void start() {
|
||||
}
|
||||
|
||||
if (gtkLoaded) {
|
||||
load(lib_gtk, "gdk_init_check", gdk_init_check);
|
||||
load(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data);
|
||||
load(lib_gtk, "gdk_pixbuf_new_from_file", gdk_pixbuf_new_from_file);
|
||||
load(lib_gtk, "gdk_pixbuf_new_from_file_at_size", gdk_pixbuf_new_from_file_at_size);
|
||||
load(lib_gtk, "gtk_status_icon_new_from_pixbuf", gtk_status_icon_new_from_pixbuf);
|
||||
load(lib_gtk, "gtk_status_icon_set_from_pixbuf", gtk_status_icon_set_from_pixbuf);
|
||||
load(lib_gtk, "gtk_status_icon_new_from_file", gtk_status_icon_new_from_file);
|
||||
load(lib_gtk, "gtk_status_icon_set_from_file", gtk_status_icon_set_from_file);
|
||||
load(lib_gtk, "gtk_status_icon_set_title", gtk_status_icon_set_title);
|
||||
load(lib_gtk, "gtk_status_icon_set_tooltip_text", gtk_status_icon_set_tooltip_text);
|
||||
load(lib_gtk, "gtk_status_icon_set_visible", gtk_status_icon_set_visible);
|
||||
load(lib_gtk, "gtk_status_icon_is_embedded", gtk_status_icon_is_embedded);
|
||||
load(lib_gtk, "gtk_status_icon_get_geometry", gtk_status_icon_get_geometry);
|
||||
load(lib_gtk, "gtk_status_icon_position_menu", gtk_status_icon_position_menu);
|
||||
load(lib_gtk, "gtk_menu_popup", gtk_menu_popup);
|
||||
load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time);
|
||||
load(lib_gtk, "g_idle_add", g_idle_add);
|
||||
|
||||
internal::GdkHelperLoad(lib_gtk);
|
||||
|
||||
|
@ -47,42 +47,15 @@ extern f_gtk_init_check gtk_init_check;
|
||||
typedef GtkSettings* (*f_gtk_settings_get_default)(void);
|
||||
extern f_gtk_settings_get_default gtk_settings_get_default;
|
||||
|
||||
typedef GtkWidget* (*f_gtk_menu_new)(void);
|
||||
extern f_gtk_menu_new gtk_menu_new;
|
||||
|
||||
typedef GType (*f_gtk_menu_get_type)(void) G_GNUC_CONST;
|
||||
extern f_gtk_menu_get_type gtk_menu_get_type;
|
||||
|
||||
typedef GtkWidget* (*f_gtk_menu_item_new_with_label)(const gchar *label);
|
||||
extern f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label;
|
||||
|
||||
typedef void (*f_gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label);
|
||||
extern f_gtk_menu_item_set_label gtk_menu_item_set_label;
|
||||
|
||||
typedef void (*f_gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child);
|
||||
extern f_gtk_menu_shell_append gtk_menu_shell_append;
|
||||
|
||||
typedef GType (*f_gtk_menu_shell_get_type)(void) G_GNUC_CONST;
|
||||
extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type;
|
||||
|
||||
typedef void (*f_gtk_widget_show)(GtkWidget *widget);
|
||||
extern f_gtk_widget_show gtk_widget_show;
|
||||
|
||||
typedef void (*f_gtk_widget_hide)(GtkWidget *widget);
|
||||
extern f_gtk_widget_hide gtk_widget_hide;
|
||||
|
||||
typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget);
|
||||
extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel;
|
||||
|
||||
typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget);
|
||||
extern f_gtk_widget_get_visible gtk_widget_get_visible;
|
||||
|
||||
typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget);
|
||||
extern f_gtk_widget_get_window gtk_widget_get_window;
|
||||
|
||||
typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
|
||||
extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive;
|
||||
|
||||
typedef void (*f_gtk_widget_realize)(GtkWidget *widget);
|
||||
extern f_gtk_widget_realize gtk_widget_realize;
|
||||
|
||||
@ -98,6 +71,18 @@ extern f_gtk_clipboard_get gtk_clipboard_get;
|
||||
typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard);
|
||||
extern f_gtk_clipboard_store gtk_clipboard_store;
|
||||
|
||||
typedef GtkSelectionData* (*f_gtk_clipboard_wait_for_contents)(GtkClipboard *clipboard, GdkAtom target);
|
||||
extern f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents;
|
||||
|
||||
typedef GdkPixbuf* (*f_gtk_clipboard_wait_for_image)(GtkClipboard *clipboard);
|
||||
extern f_gtk_clipboard_wait_for_image gtk_clipboard_wait_for_image;
|
||||
|
||||
typedef gboolean (*f_gtk_selection_data_targets_include_image)(const GtkSelectionData *selection_data, gboolean writable);
|
||||
extern f_gtk_selection_data_targets_include_image gtk_selection_data_targets_include_image;
|
||||
|
||||
typedef void (*f_gtk_selection_data_free)(GtkSelectionData *data);
|
||||
extern f_gtk_selection_data_free gtk_selection_data_free;
|
||||
|
||||
typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED;
|
||||
extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new;
|
||||
|
||||
@ -190,16 +175,6 @@ inline Result *g_type_cic_helper(Object *instance, GType iface_type) {
|
||||
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
inline GtkMenu *gtk_menu_cast(Object *obj) {
|
||||
return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type());
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) {
|
||||
return g_type_cic_helper<GtkMenuShell, Object>(obj, gtk_menu_get_type());
|
||||
}
|
||||
|
||||
typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST;
|
||||
extern f_gtk_dialog_get_type gtk_dialog_get_type;
|
||||
|
||||
@ -273,84 +248,36 @@ inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *de
|
||||
return g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
typedef void (*f_g_signal_handler_disconnect)(gpointer instance, gulong handler_id);
|
||||
extern f_g_signal_handler_disconnect g_signal_handler_disconnect;
|
||||
|
||||
typedef gboolean (*f_gdk_init_check)(gint *argc, gchar ***argv);
|
||||
extern f_gdk_init_check gdk_init_check;
|
||||
|
||||
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data);
|
||||
extern f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data;
|
||||
|
||||
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_file)(const gchar *filename, GError **error);
|
||||
extern f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file;
|
||||
typedef GdkAtom (*f_gdk_atom_intern)(const gchar *atom_name, gboolean only_if_exists);
|
||||
extern f_gdk_atom_intern gdk_atom_intern;
|
||||
|
||||
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_file_at_size)(const gchar *filename, int width, int height, GError **error);
|
||||
extern f_gdk_pixbuf_new_from_file_at_size gdk_pixbuf_new_from_file_at_size;
|
||||
|
||||
typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf);
|
||||
extern f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf;
|
||||
typedef gboolean (*f_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha;
|
||||
|
||||
typedef void (*f_gtk_status_icon_set_from_pixbuf)(GtkStatusIcon *status_icon, GdkPixbuf *pixbuf);
|
||||
extern f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf;
|
||||
typedef guchar* (*f_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels;
|
||||
|
||||
typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_file)(const gchar *filename);
|
||||
extern f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file;
|
||||
typedef int (*f_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_width gdk_pixbuf_get_width;
|
||||
|
||||
typedef void (*f_gtk_status_icon_set_from_file)(GtkStatusIcon *status_icon, const gchar *filename);
|
||||
extern f_gtk_status_icon_set_from_file gtk_status_icon_set_from_file;
|
||||
typedef int (*f_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_height gdk_pixbuf_get_height;
|
||||
|
||||
typedef void (*f_gtk_status_icon_set_title)(GtkStatusIcon *status_icon, const gchar *title);
|
||||
extern f_gtk_status_icon_set_title gtk_status_icon_set_title;
|
||||
|
||||
typedef void (*f_gtk_status_icon_set_tooltip_text)(GtkStatusIcon *status_icon, const gchar *title);
|
||||
extern f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text;
|
||||
|
||||
typedef void (*f_gtk_status_icon_set_visible)(GtkStatusIcon *status_icon, gboolean visible);
|
||||
extern f_gtk_status_icon_set_visible gtk_status_icon_set_visible;
|
||||
|
||||
typedef gboolean (*f_gtk_status_icon_is_embedded)(GtkStatusIcon *status_icon);
|
||||
extern f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded;
|
||||
|
||||
typedef gboolean (*f_gtk_status_icon_get_geometry)(GtkStatusIcon *status_icon, GdkScreen **screen, GdkRectangle *area, GtkOrientation *orientation);
|
||||
extern f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry;
|
||||
|
||||
typedef void (*f_gtk_status_icon_position_menu)(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data);
|
||||
extern f_gtk_status_icon_position_menu gtk_status_icon_position_menu;
|
||||
|
||||
typedef void (*f_gtk_menu_popup)(GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time);
|
||||
extern f_gtk_menu_popup gtk_menu_popup;
|
||||
|
||||
typedef guint32 (*f_gtk_get_current_event_time)(void);
|
||||
extern f_gtk_get_current_event_time gtk_get_current_event_time;
|
||||
typedef int (*f_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride;
|
||||
|
||||
typedef void (*f_g_object_get)(gpointer object, const gchar *first_property_name, ...) G_GNUC_NULL_TERMINATED;
|
||||
extern f_g_object_get g_object_get;
|
||||
|
||||
typedef gpointer (*f_g_object_ref_sink)(gpointer object);
|
||||
extern f_g_object_ref_sink g_object_ref_sink;
|
||||
|
||||
typedef void (*f_g_object_unref)(gpointer object);
|
||||
extern f_g_object_unref g_object_unref;
|
||||
|
||||
typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data);
|
||||
extern f_g_idle_add g_idle_add;
|
||||
|
||||
typedef void (*f_g_free)(gpointer mem);
|
||||
extern f_g_free g_free;
|
||||
|
||||
typedef void (*f_g_list_foreach)(GList *list, GFunc func, gpointer user_data);
|
||||
extern f_g_list_foreach g_list_foreach;
|
||||
|
||||
typedef void (*f_g_list_free)(GList *list);
|
||||
extern f_g_list_free g_list_free;
|
||||
|
||||
typedef void (*f_g_list_free_full)(GList *list, GDestroyNotify free_func);
|
||||
extern f_g_list_free_full g_list_free_full;
|
||||
|
||||
typedef void (*f_g_error_free)(GError *error);
|
||||
extern f_g_error_free g_error_free;
|
||||
|
||||
typedef void (*f_g_slist_free)(GSList *list);
|
||||
extern f_g_slist_free g_slist_free;
|
||||
|
||||
|
@ -443,6 +443,11 @@ void ForceDisabled(QAction *action, bool disabled) {
|
||||
|
||||
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||
: Window::MainWindow(controller) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (Libs::gtk_clipboard_get != nullptr) {
|
||||
_gtkClipboard = Libs::gtk_clipboard_get(Libs::gdk_atom_intern("CLIPBOARD", true));
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::initHook() {
|
||||
|
@ -18,6 +18,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include <dbusmenuexporter.h>
|
||||
#endif
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
typedef struct _GtkClipboard GtkClipboard;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
@ -70,6 +75,12 @@ public slots:
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
GtkClipboard *gtkClipboard() {
|
||||
return _gtkClipboard;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
protected:
|
||||
void initHook() override;
|
||||
void unreadCounterChangedHook() override;
|
||||
@ -133,6 +144,10 @@ private:
|
||||
void attachToSNITrayIcon();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
GtkClipboard *_gtkClipboard = nullptr;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
};
|
||||
|
||||
} // namespace Platform
|
||||
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "platform/linux/specific_linux.h"
|
||||
#include "history/history.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@ -70,7 +71,7 @@ void GetSupported() {
|
||||
}
|
||||
Checked = true;
|
||||
|
||||
if (Global::NativeNotifications()) {
|
||||
if (Global::NativeNotifications() && !Platform::IsWayland()) {
|
||||
ComputeSupported(true);
|
||||
} else {
|
||||
ComputeSupported();
|
||||
@ -474,7 +475,8 @@ std::unique_ptr<Window::Notifications::Manager> Create(
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
GetSupported();
|
||||
|
||||
if (Global::NativeNotifications() && Supported()) {
|
||||
if ((Global::NativeNotifications() && Supported())
|
||||
|| Platform::IsWayland()) {
|
||||
return std::make_unique<Manager>(system);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
@ -488,6 +490,10 @@ Manager::Private::Private(not_null<Manager*> manager, Type type)
|
||||
, _manager(manager) {
|
||||
qDBusRegisterMetaType<NotificationData::ImageData>();
|
||||
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto serverInformation = GetServerInformation();
|
||||
const auto capabilities = GetCapabilities();
|
||||
|
||||
@ -520,6 +526,8 @@ void Manager::Private::showNotification(
|
||||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto notification = std::make_shared<NotificationData>(
|
||||
_manager,
|
||||
title,
|
||||
@ -558,6 +566,8 @@ void Manager::Private::showNotification(
|
||||
}
|
||||
|
||||
void Manager::Private::clearAll() {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto temp = base::take(_notifications);
|
||||
for_const (auto ¬ifications, temp) {
|
||||
for_const (auto notification, notifications) {
|
||||
@ -567,6 +577,8 @@ void Manager::Private::clearAll() {
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto i = _notifications.find(history->peer->id);
|
||||
if (i != _notifications.cend()) {
|
||||
auto temp = base::take(i.value());
|
||||
@ -579,6 +591,8 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
}
|
||||
|
||||
void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto i = _notifications.find(peerId);
|
||||
if (i != _notifications.cend()) {
|
||||
i.value().remove(msgId);
|
||||
|
@ -55,6 +55,8 @@ constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
|
||||
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
|
||||
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
|
||||
|
||||
QStringList PlatformThemes;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
void PortalAutostart(bool autostart, bool silent = false) {
|
||||
QVariantMap options;
|
||||
@ -295,14 +297,22 @@ bool IsStaticBinary() {
|
||||
#endif // !DESKTOP_APP_USE_PACKAGED
|
||||
}
|
||||
|
||||
bool UseGtkIntegration() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
static const auto Result = !qEnvironmentVariableIsSet(
|
||||
"TDESKTOP_DISABLE_GTK_INTEGRATION");
|
||||
|
||||
return Result;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsGtkIntegrationForced() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
static const auto Result = [&] {
|
||||
const auto platformThemes = QString::fromUtf8(qgetenv("QT_QPA_PLATFORMTHEME"))
|
||||
.split(':', QString::SkipEmptyParts);
|
||||
|
||||
return platformThemes.contains(qstr("gtk3"), Qt::CaseInsensitive)
|
||||
|| platformThemes.contains(qstr("gtk2"), Qt::CaseInsensitive);
|
||||
return PlatformThemes.contains(qstr("gtk3"), Qt::CaseInsensitive)
|
||||
|| PlatformThemes.contains(qstr("gtk2"), Qt::CaseInsensitive);
|
||||
}();
|
||||
|
||||
return Result;
|
||||
@ -346,7 +356,6 @@ bool UseXDGDesktopPortal() {
|
||||
|
||||
return (
|
||||
DesktopEnvironment::IsKDE()
|
||||
|| InSnap()
|
||||
|| envVar
|
||||
) && portalPresent;
|
||||
}();
|
||||
@ -510,6 +519,43 @@ QString GetIconName() {
|
||||
return Result;
|
||||
}
|
||||
|
||||
QImage GetImageFromClipboard() {
|
||||
QImage data;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (!App::wnd()->gtkClipboard()) {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto gsel = Libs::gtk_clipboard_wait_for_contents(
|
||||
App::wnd()->gtkClipboard(),
|
||||
Libs::gdk_atom_intern("TARGETS", true));
|
||||
|
||||
if (gsel) {
|
||||
if (Libs::gtk_selection_data_targets_include_image(gsel, false)) {
|
||||
auto img = Libs::gtk_clipboard_wait_for_image(App::wnd()->gtkClipboard());
|
||||
|
||||
if (img) {
|
||||
data = QImage(
|
||||
Libs::gdk_pixbuf_get_pixels(img),
|
||||
Libs::gdk_pixbuf_get_width(img),
|
||||
Libs::gdk_pixbuf_get_height(img),
|
||||
Libs::gdk_pixbuf_get_rowstride(img),
|
||||
Libs::gdk_pixbuf_get_has_alpha(img)
|
||||
? QImage::Format_RGBA8888
|
||||
: QImage::Format_RGB888).copy();
|
||||
|
||||
Libs::g_object_unref(img);
|
||||
}
|
||||
}
|
||||
|
||||
Libs::gtk_selection_data_free(gsel);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::optional<crl::time> LastUserInputTime() {
|
||||
// TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland
|
||||
// an example: https://stackoverflow.com/q/9049087
|
||||
@ -697,6 +743,9 @@ int psFixPrevious() {
|
||||
namespace Platform {
|
||||
|
||||
void start() {
|
||||
PlatformThemes = QString::fromUtf8(qgetenv("QT_QPA_PLATFORMTHEME"))
|
||||
.split(':', QString::SkipEmptyParts);
|
||||
|
||||
LOG(("Launcher filename: %1").arg(GetLauncherFilename()));
|
||||
|
||||
#ifdef TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||
@ -706,6 +755,16 @@ void start() {
|
||||
qputenv("PULSE_PROP_application.name", AppName.utf8());
|
||||
qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1());
|
||||
|
||||
// if gtk integration and qgtk3/qgtk2 platformtheme (or qgtk2 style)
|
||||
// is used at the same time, the app will crash
|
||||
if (UseGtkIntegration()
|
||||
&& !IsStaticBinary()
|
||||
&& !qEnvironmentVariableIsSet(
|
||||
"TDESKTOP_I_KNOW_ABOUT_GTK_INCOMPATIBILITY")) {
|
||||
qunsetenv("QT_QPA_PLATFORMTHEME");
|
||||
qunsetenv("QT_STYLE_OVERRIDE");
|
||||
}
|
||||
|
||||
if(IsStaticBinary()
|
||||
|| InAppImage()
|
||||
|| InFlatpak()
|
||||
|
@ -24,6 +24,7 @@ bool InFlatpak();
|
||||
bool InSnap();
|
||||
bool InAppImage();
|
||||
bool IsStaticBinary();
|
||||
bool UseGtkIntegration();
|
||||
bool IsGtkIntegrationForced();
|
||||
bool UseGtkFileDialog();
|
||||
bool IsQtPluginsBundled();
|
||||
@ -34,10 +35,8 @@ bool CanOpenDirectoryWithPortal();
|
||||
|
||||
QString ProcessNameByPID(const QString &pid);
|
||||
QString RealExecutablePath(int argc, char *argv[]);
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString AppRuntimeDirectory();
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
QString GetLauncherBasename();
|
||||
QString GetLauncherFilename();
|
||||
|
@ -16,10 +16,6 @@ class LocationPoint;
|
||||
|
||||
namespace Platform {
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
void RemoveQuarantine(const QString &path);
|
||||
|
||||
inline void FallbackFontConfigCheckBegin() {
|
||||
@ -28,6 +24,10 @@ inline void FallbackFontConfigCheckBegin() {
|
||||
inline void FallbackFontConfigCheckEnd() {
|
||||
}
|
||||
|
||||
inline QImage GetImageFromClipboard() {
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
inline void start() {
|
||||
|
@ -19,7 +19,9 @@ void DeInit();
|
||||
|
||||
// Platform dependent implementations.
|
||||
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#if defined Q_OS_WINRT || defined Q_OS_WIN
|
||||
#include "platform/win/audio_win.h"
|
||||
#else // Q_OS_WINRT || Q_OS_WIN
|
||||
namespace Platform {
|
||||
namespace Audio {
|
||||
|
||||
@ -31,6 +33,4 @@ inline void DeInit() {
|
||||
|
||||
} // namespace Audio
|
||||
} // namespace Platform
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#include "platform/win/audio_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_WINRT || Q_OS_WIN
|
||||
|
@ -46,8 +46,8 @@ bool Get(
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/file_utilities_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/file_utilities_linux.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/file_utilities_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
|
||||
|
@ -23,8 +23,8 @@ namespace Platform {
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/launcher_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/launcher_linux.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/launcher_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
|
||||
|
@ -19,8 +19,8 @@ class MainWindow;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/main_window_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/main_window_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/main_window_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@ -27,8 +27,8 @@ namespace Notifications {
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/notifications_manager_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/notifications_manager_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@ -28,6 +28,8 @@ enum class SystemSettingsType {
|
||||
|
||||
void SetWatchingMediaKeys(bool watching);
|
||||
void SetApplicationIcon(const QIcon &icon);
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
void RegisterCustomScheme(bool force = false);
|
||||
PermissionStatus GetPermissionStatus(PermissionType type);
|
||||
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback);
|
||||
@ -41,6 +43,7 @@ bool OpenSystemSettings(SystemSettingsType type);
|
||||
|
||||
void IgnoreApplicationActivationRightNow();
|
||||
bool AutostartSupported();
|
||||
QImage GetImageFromClipboard();
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
@ -52,8 +55,8 @@ void finish();
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/specific_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/specific_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/specific_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@ -26,7 +26,7 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe
|
||||
#include "platform/mac/window_title_mac.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC
|
||||
#include "platform/win/window_title_win.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_LINUX // Q_OS_MAC || Q_OS_WIN
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_UNIX // Q_OS_MAC || Q_OS_WIN
|
||||
|
||||
namespace Platform {
|
||||
|
||||
@ -44,4 +44,4 @@ inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palet
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_LINUX
|
||||
#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_UNIX
|
||||
|
@ -19,10 +19,6 @@ namespace Platform {
|
||||
inline void SetWatchingMediaKeys(bool watching) {
|
||||
}
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
inline void IgnoreApplicationActivationRightNow() {
|
||||
}
|
||||
|
||||
@ -32,6 +28,10 @@ inline void FallbackFontConfigCheckBegin() {
|
||||
inline void FallbackFontConfigCheckEnd() {
|
||||
}
|
||||
|
||||
inline QImage GetImageFromClipboard() {
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
void start();
|
||||
|
@ -20,7 +20,7 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
|
||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
||||
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)
|
||||
Q_IMPORT_PLUGIN(QGenericEnginePlugin)
|
||||
#elif defined Q_OS_LINUX // Q_OS_WIN | Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_WIN | Q_OS_MAC
|
||||
Q_IMPORT_PLUGIN(ShmServerBufferPlugin)
|
||||
Q_IMPORT_PLUGIN(DmaBufServerBufferPlugin)
|
||||
Q_IMPORT_PLUGIN(DrmEglServerBufferPlugin)
|
||||
@ -44,10 +44,10 @@ Q_IMPORT_PLUGIN(QNetworkManagerEnginePlugin)
|
||||
Q_IMPORT_PLUGIN(QIbusPlatformInputContextPlugin)
|
||||
Q_IMPORT_PLUGIN(QXdgDesktopPortalThemePlugin)
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#endif // Q_OS_WIN | Q_OS_MAC | Q_OS_LINUX
|
||||
#endif // Q_OS_WIN | Q_OS_MAC | Q_OS_UNIX
|
||||
#endif // !DESKTOP_APP_USE_PACKAGED
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
#if !defined DESKTOP_APP_USE_PACKAGED || defined DESKTOP_APP_USE_PACKAGED_LAZY
|
||||
Q_IMPORT_PLUGIN(QWaylandMaterialDecorationPlugin)
|
||||
Q_IMPORT_PLUGIN(NimfInputContextPlugin)
|
||||
@ -69,4 +69,4 @@ Q_IMPORT_PLUGIN(Qt5CTStylePlugin)
|
||||
Q_IMPORT_PLUGIN(LXQtPlatformThemePlugin)
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#endif // DESKTOP_APP_USE_PACKAGED_LAZY_PLATFORMTHEMES
|
||||
#endif // Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
|
@ -499,11 +499,11 @@ void NotificationsCount::SampleWidget::destroyDelayed() {
|
||||
_deleted = true;
|
||||
|
||||
// Ubuntu has a lag if deleteLater() called immediately.
|
||||
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||
QTimer::singleShot(1000, [this] { delete this; });
|
||||
#else // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#else // Q_OS_UNIX && !Q_OS_MAC
|
||||
deleteLater();
|
||||
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||
#endif // Q_OS_UNIX && !Q_OS_MAC
|
||||
}
|
||||
|
||||
void SetupAdvancedNotifications(
|
||||
@ -633,7 +633,7 @@ void SetupNotificationsContent(
|
||||
return QString();
|
||||
} else if (Platform::IsWindows()) {
|
||||
return tr::lng_settings_use_windows(tr::now);
|
||||
} else if (Platform::IsLinux()) {
|
||||
} else if (Platform::IsLinux() && !Platform::IsWayland()) {
|
||||
return tr::lng_settings_use_native_notifications(tr::now);
|
||||
}
|
||||
return QString();
|
||||
@ -651,6 +651,9 @@ void SetupNotificationsContent(
|
||||
}();
|
||||
|
||||
const auto advancedSlide = !Platform::IsMac10_8OrGreater()
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
&& !Platform::IsWayland()
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
? container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
|
@ -79,9 +79,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
// Fix Google Breakpad build for Mac App Store and Linux version
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#ifdef Q_OS_UNIX
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX
|
||||
#endif // Q_OS_UNIX
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "mtproto/facade.h"
|
||||
#include "lottie/lottie_animation.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "boxes/send_files_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@ -129,6 +130,7 @@ MTPInputSingleMedia PrepareAlbumItemMedia(
|
||||
auto caption = item->originalText();
|
||||
TextUtilities::Trim(caption);
|
||||
auto sentEntities = Api::EntitiesToMTP(
|
||||
&item->history()->session(),
|
||||
caption.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
const auto flags = !sentEntities.v.isEmpty()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user