mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-21 14:05:06 +01:00
update to 11.4.2 (5469)
This commit is contained in:
parent
9b78d437de
commit
fb2e545101
295 changed files with 18975 additions and 3863 deletions
|
@ -210,7 +210,7 @@ apply plugin: 'com.google.gms.google-services'
|
|||
task checkVisibility {
|
||||
doFirst {
|
||||
def isPrivateBuild = project.gradle.startParameter.taskNames.find {
|
||||
it.contains("HA_private") || it.contains("Debug") || it.contains("Release")
|
||||
it.contains("HA_private") || it.contains("HA_hardcore") || it.contains("Debug") || it.contains("Release")
|
||||
}
|
||||
def isPublicAllowed = !project.hasProperty("IS_PRIVATE") || !project.property("IS_PRIVATE").toBoolean()
|
||||
if (!isPrivateBuild && !isPublicAllowed) {
|
||||
|
|
|
@ -13,6 +13,7 @@ ${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libavresample.a,
|
|||
${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libavutil.a,
|
||||
${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libswresample.a,
|
||||
${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libvpx.a,
|
||||
${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libdav1d.a,
|
||||
${CMAKE_HOME_DIRECTORY}/boringssl/lib/libssl_${ANDROID_ABI}.a,
|
||||
${CMAKE_HOME_DIRECTORY}/boringssl/lib/libcrypto_${ANDROID_ABI}.a")
|
||||
|
||||
|
@ -49,6 +50,8 @@ set_target_properties(ssl PROPERTIES IMPORTED_LOCATION ${CMAKE_HOME_DIRECTORY}/b
|
|||
add_library(libvpx STATIC IMPORTED)
|
||||
set_target_properties(libvpx PROPERTIES IMPORTED_LOCATION ${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libvpx.a)
|
||||
|
||||
add_library(libdav1d STATIC IMPORTED)
|
||||
set_target_properties(libdav1d PROPERTIES IMPORTED_LOCATION ${CMAKE_HOME_DIRECTORY}/ffmpeg/${ANDROID_ABI}/libdav1d.a)
|
||||
|
||||
#tgnet
|
||||
#add_library(mozjpeg STATIC
|
||||
|
@ -641,6 +644,7 @@ target_link_libraries(${NATIVE_LIB}
|
|||
avresample
|
||||
swresample
|
||||
libvpx
|
||||
libdav1d
|
||||
avutil
|
||||
ssl
|
||||
crypto
|
||||
|
|
|
@ -85,6 +85,10 @@ jint getCurrentTime(JNIEnv *env, jclass c, jint instanceNum) {
|
|||
return ConnectionsManager::getInstance(instanceNum).getCurrentTime();
|
||||
}
|
||||
|
||||
jint getCurrentPingTime(JNIEnv *env, jclass c, jint instanceNum) {
|
||||
return ConnectionsManager::getInstance(instanceNum).getCurrentPingTime();
|
||||
}
|
||||
|
||||
jint getCurrentDatacenterId(JNIEnv *env, jclass c, jint instanceNum) {
|
||||
return ConnectionsManager::getInstance(instanceNum).getCurrentDatacenterId();
|
||||
}
|
||||
|
@ -486,6 +490,7 @@ static const char *ConnectionsManagerClassPathName = "org/telegram/tgnet/Connect
|
|||
static JNINativeMethod ConnectionsManagerMethods[] = {
|
||||
{"native_getCurrentTimeMillis", "(I)J", (void *) getCurrentTimeMillis},
|
||||
{"native_getCurrentTime", "(I)I", (void *) getCurrentTime},
|
||||
{"native_getCurrentPingTime", "(I)I", (void *) getCurrentPingTime},
|
||||
{"native_getCurrentDatacenterId", "(I)I", (void *) getCurrentDatacenterId},
|
||||
{"native_isTestBackend", "(I)I", (void *) isTestBackend},
|
||||
{"native_getTimeDifference", "(I)I", (void *) getTimeDifference},
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
TMessagesProj/jni/ffmpeg/arm64-v8a/libdav1d.a
Normal file
BIN
TMessagesProj/jni/ffmpeg/arm64-v8a/libdav1d.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
TMessagesProj/jni/ffmpeg/armeabi-v7a/libdav1d.a
Normal file
BIN
TMessagesProj/jni/ffmpeg/armeabi-v7a/libdav1d.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@
|
|||
# ffmpeg 4.4.3
|
||||
# lib vpx 1.10.9
|
||||
# NDK for compile libvpx. Last successful build with 21.1.6352462
|
||||
# and dav1d. Last successful build with
|
||||
# NDK r10e for compile ffmpeg
|
||||
#
|
||||
# 1) download ffmpeg
|
||||
|
@ -12,8 +13,18 @@
|
|||
# 3) download lib vpx
|
||||
# 4) copy libvpx to vpx-android folder and rename as libvpx
|
||||
# 5) copy build_ffmpeg foleder in ffmepg directory
|
||||
# 6) run build_ffmpeg.sh
|
||||
# 7) see compiled library in build_ffmpeg/adnroid folder
|
||||
# 6) download dav1d into android-dav1d/dav1d folder
|
||||
# 7.1) in ffmpeg fix typos in 3 files, replacing 'int B0' into 'int b0'
|
||||
# 7.2) install python3.9 and replace python in vpx-android/_settings.sh
|
||||
# 7.3) (macos) replace HOST_NUM_CORES with $(sysctl -n hw.physicalcpu)
|
||||
# 7.4) (macos) press allow and open for each executable in system preferences
|
||||
# 8) patch ffmpeg/configure to take dav1d as an external lib from folder:
|
||||
# enabled libdav1d && {
|
||||
# require_pkg_config libdav1d "libdav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version ||
|
||||
# check_lib libdav1d "dav1d/dav1d.h" "DAV1D_VERSION" "-ldav1d $libm_extralibs $pthreads_extralibs"
|
||||
# }
|
||||
# 9) run build_ffmpeg.sh
|
||||
# 10) see compiled library in build_ffmpeg/android folder
|
||||
|
||||
NDK="/opt/android/ndk/android-ndk-r21e"
|
||||
NDK_r10e="/opt/android/ndk/android-ndk-r10e"
|
||||
|
@ -24,6 +35,11 @@ export ANDROID_NDK=$NDK
|
|||
sh build-vpx.sh
|
||||
cd ..
|
||||
|
||||
#build dav1d
|
||||
cd ./dav1d-android
|
||||
export ANDROID_NDK=$NDK
|
||||
./build_dav1d.sh
|
||||
cd ..
|
||||
|
||||
NDK=$NDK_r10e
|
||||
|
||||
|
@ -37,7 +53,7 @@ echo "Configuring..."
|
|||
|
||||
INCLUDES=" -I${PREFIX}/include"
|
||||
LIBS=" -L${PREFIX}/lib"
|
||||
|
||||
|
||||
./configure \
|
||||
--cc=$CC \
|
||||
--nm=$NM \
|
||||
|
@ -80,6 +96,10 @@ LIBS=" -L${PREFIX}/lib"
|
|||
--enable-muxer=matroska \
|
||||
--enable-bsf=vp9_superframe \
|
||||
--enable-bsf=vp9_raw_reorder \
|
||||
\
|
||||
--enable-libdav1d \
|
||||
--enable-decoder=libdav1d \
|
||||
--enable-decoder=av1 \
|
||||
--enable-runtime-cpudetect \
|
||||
--enable-pthreads \
|
||||
--enable-avresample \
|
||||
|
@ -106,7 +126,7 @@ $ADDITIONAL_CONFIGURE_FLAG
|
|||
|
||||
#echo "continue?"
|
||||
#read
|
||||
make -j8 install
|
||||
make -j${HOST_NUM_CORES} install
|
||||
|
||||
}
|
||||
|
||||
|
|
87
TMessagesProj/jni/ffmpeg/build_ffmpeg/dav1d-android/build_dav1d.sh
Executable file
87
TMessagesProj/jni/ffmpeg/build_ffmpeg/dav1d-android/build_dav1d.sh
Executable file
|
@ -0,0 +1,87 @@
|
|||
#!/bin/bash
|
||||
|
||||
PREFIX="$(pwd)/../android"
|
||||
mkdir -p "$PREFIX"
|
||||
echo "Building dav1d into $PREFIX"
|
||||
|
||||
pushd dav1d
|
||||
|
||||
meson setup builddir-arm64 \
|
||||
--prefix "$PREFIX/arm64-v8a" \
|
||||
--libdir="lib" \
|
||||
--includedir="include" \
|
||||
--buildtype=release -Denable_tests=false -Denable_tools=false -Ddefault_library=static \
|
||||
--cross-file <(echo "
|
||||
[binaries]
|
||||
c = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang'
|
||||
ar = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ar'
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'arm64'
|
||||
endian = 'little'
|
||||
")
|
||||
ninja -C builddir-arm64
|
||||
ninja -C builddir-arm64 install
|
||||
|
||||
meson setup builddir-armv7 \
|
||||
--prefix "$PREFIX/armeabi-v7a" \
|
||||
--libdir="lib" \
|
||||
--includedir="include" \
|
||||
--buildtype=release -Denable_tests=false -Denable_tools=false -Ddefault_library=static \
|
||||
--cross-file <(echo "
|
||||
[binaries]
|
||||
c = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi21-clang'
|
||||
ar = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar'
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'arm'
|
||||
cpu = 'armv7'
|
||||
endian = 'little'
|
||||
") \
|
||||
-Dc_args="-DDAV1D_NO_GETAUXVAL"
|
||||
ninja -C builddir-armv7
|
||||
ninja -C builddir-armv7 install
|
||||
|
||||
meson setup builddir-x86 \
|
||||
--prefix "$PREFIX/x86" \
|
||||
--libdir="lib" \
|
||||
--includedir="include" \
|
||||
--buildtype=release -Denable_tests=false -Denable_tools=false -Ddefault_library=static \
|
||||
--cross-file <(echo "
|
||||
[binaries]
|
||||
c = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-android21-clang'
|
||||
ar = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-android-ar'
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'x86'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
")
|
||||
ninja -C builddir-x86
|
||||
ninja -C builddir-x86 install
|
||||
|
||||
meson setup builddir-x86_64 \
|
||||
--prefix "$PREFIX/x86_64" \
|
||||
--libdir="lib" \
|
||||
--includedir="include" \
|
||||
--buildtype=release -Denable_tests=false -Denable_tools=false -Ddefault_library=static \
|
||||
--cross-file <(echo "
|
||||
[binaries]
|
||||
c = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android21-clang'
|
||||
ar = '${ANDROID_NDK}/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android-ar'
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
")
|
||||
ninja -C builddir-x86_64
|
||||
ninja -C builddir-x86_64 install
|
||||
|
||||
popd
|
||||
|
94
TMessagesProj/jni/ffmpeg/include/dav1d/common.h
Normal file
94
TMessagesProj/jni/ffmpeg/include/dav1d/common.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_H
|
||||
#define DAV1D_COMMON_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DAV1D_API
|
||||
#if defined _WIN32
|
||||
#if defined DAV1D_BUILDING_DLL
|
||||
#define DAV1D_API __declspec(dllexport)
|
||||
#else
|
||||
#define DAV1D_API
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define DAV1D_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define DAV1D_API
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if EPERM > 0
|
||||
#define DAV1D_ERR(e) (-(e)) ///< Negate POSIX error code.
|
||||
#else
|
||||
#define DAV1D_ERR(e) (e)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A reference-counted object wrapper for a user-configurable pointer.
|
||||
*/
|
||||
typedef struct Dav1dUserData {
|
||||
const uint8_t *data; ///< data pointer
|
||||
struct Dav1dRef *ref; ///< allocation origin
|
||||
} Dav1dUserData;
|
||||
|
||||
/**
|
||||
* Input packet metadata which are copied from the input data used to
|
||||
* decode each image into the matching structure of the output image
|
||||
* returned back to the user. Since these are metadata fields, they
|
||||
* can be used for other purposes than the documented ones, they will
|
||||
* still be passed from input data to output picture without being
|
||||
* used internally.
|
||||
*/
|
||||
typedef struct Dav1dDataProps {
|
||||
int64_t timestamp; ///< container timestamp of input data, INT64_MIN if unknown (default)
|
||||
int64_t duration; ///< container duration of input data, 0 if unknown (default)
|
||||
int64_t offset; ///< stream offset of input data, -1 if unknown (default)
|
||||
size_t size; ///< packet size, default Dav1dData.sz
|
||||
struct Dav1dUserData user_data; ///< user-configurable data, default NULL members
|
||||
} Dav1dDataProps;
|
||||
|
||||
/**
|
||||
* Release reference to a Dav1dDataProps.
|
||||
*/
|
||||
DAV1D_API void dav1d_data_props_unref(Dav1dDataProps *props);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_COMMON_H */
|
117
TMessagesProj/jni/ffmpeg/include/dav1d/data.h
Normal file
117
TMessagesProj/jni/ffmpeg/include/dav1d/data.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_DATA_H
|
||||
#define DAV1D_DATA_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Dav1dData {
|
||||
const uint8_t *data; ///< data pointer
|
||||
size_t sz; ///< data size
|
||||
struct Dav1dRef *ref; ///< allocation origin
|
||||
Dav1dDataProps m; ///< user provided metadata passed to the output picture
|
||||
} Dav1dData;
|
||||
|
||||
/**
|
||||
* Allocate data.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param sz Size of the data that should be allocated.
|
||||
*
|
||||
* @return Pointer to the allocated buffer on success. NULL on error.
|
||||
*/
|
||||
DAV1D_API uint8_t * dav1d_data_create(Dav1dData *data, size_t sz);
|
||||
|
||||
/**
|
||||
* Wrap an existing data array.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param buf The data to be wrapped.
|
||||
* @param sz Size of the data.
|
||||
* @param free_callback Function to be called when we release our last
|
||||
* reference to this data. In this callback, $buf will be
|
||||
* the $buf argument to this function, and $cookie will
|
||||
* be the $cookie input argument to this function.
|
||||
* @param cookie Opaque parameter passed to free_callback().
|
||||
*
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_data_wrap(Dav1dData *data, const uint8_t *buf, size_t sz,
|
||||
void (*free_callback)(const uint8_t *buf, void *cookie),
|
||||
void *cookie);
|
||||
|
||||
/**
|
||||
* Wrap a user-provided data pointer into a reference counted object.
|
||||
*
|
||||
* data->m.user_data field will initialized to wrap the provided $user_data
|
||||
* pointer.
|
||||
*
|
||||
* $free_callback will be called on the same thread that released the last
|
||||
* reference. If frame threading is used, make sure $free_callback is
|
||||
* thread-safe.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param user_data The user data to be wrapped.
|
||||
* @param free_callback Function to be called when we release our last
|
||||
* reference to this data. In this callback, $user_data
|
||||
* will be the $user_data argument to this function, and
|
||||
* $cookie will be the $cookie input argument to this
|
||||
* function.
|
||||
* @param cookie Opaque parameter passed to $free_callback.
|
||||
*
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_data_wrap_user_data(Dav1dData *data,
|
||||
const uint8_t *user_data,
|
||||
void (*free_callback)(const uint8_t *user_data,
|
||||
void *cookie),
|
||||
void *cookie);
|
||||
|
||||
/**
|
||||
* Free the data reference.
|
||||
*
|
||||
* The reference count for data->m.user_data will be decremented (if it has been
|
||||
* initialized with dav1d_data_wrap_user_data). The $data object will be memset
|
||||
* to 0.
|
||||
*
|
||||
* @param data Input context.
|
||||
*/
|
||||
DAV1D_API void dav1d_data_unref(Dav1dData *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_DATA_H */
|
329
TMessagesProj/jni/ffmpeg/include/dav1d/dav1d.h
Normal file
329
TMessagesProj/jni/ffmpeg/include/dav1d/dav1d.h
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright © 2018-2021, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_H
|
||||
#define DAV1D_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "picture.h"
|
||||
#include "data.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Dav1dContext Dav1dContext;
|
||||
typedef struct Dav1dRef Dav1dRef;
|
||||
|
||||
#define DAV1D_MAX_THREADS 256
|
||||
#define DAV1D_MAX_FRAME_DELAY 256
|
||||
|
||||
typedef struct Dav1dLogger {
|
||||
void *cookie; ///< Custom data to pass to the callback.
|
||||
/**
|
||||
* Logger callback. May be NULL to disable logging.
|
||||
*
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
* @param format The vprintf compatible format string.
|
||||
* @param ap List of arguments referenced by the format string.
|
||||
*/
|
||||
void (*callback)(void *cookie, const char *format, va_list ap);
|
||||
} Dav1dLogger;
|
||||
|
||||
enum Dav1dInloopFilterType {
|
||||
DAV1D_INLOOPFILTER_NONE = 0,
|
||||
DAV1D_INLOOPFILTER_DEBLOCK = 1 << 0,
|
||||
DAV1D_INLOOPFILTER_CDEF = 1 << 1,
|
||||
DAV1D_INLOOPFILTER_RESTORATION = 1 << 2,
|
||||
DAV1D_INLOOPFILTER_ALL = DAV1D_INLOOPFILTER_DEBLOCK |
|
||||
DAV1D_INLOOPFILTER_CDEF |
|
||||
DAV1D_INLOOPFILTER_RESTORATION,
|
||||
};
|
||||
|
||||
enum Dav1dDecodeFrameType {
|
||||
DAV1D_DECODEFRAMETYPE_ALL = 0, ///< decode and return all frames
|
||||
DAV1D_DECODEFRAMETYPE_REFERENCE = 1,///< decode and return frames referenced by other frames only
|
||||
DAV1D_DECODEFRAMETYPE_INTRA = 2, ///< decode and return intra frames only (includes keyframes)
|
||||
DAV1D_DECODEFRAMETYPE_KEY = 3, ///< decode and return keyframes only
|
||||
};
|
||||
|
||||
typedef struct Dav1dSettings {
|
||||
int n_threads; ///< number of threads (0 = number of logical cores in host system, default 0)
|
||||
int max_frame_delay; ///< Set to 1 for low-latency decoding (0 = ceil(sqrt(n_threads)), default 0)
|
||||
int apply_grain; ///< whether to apply film grain on output frames (default 1)
|
||||
int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31, default 0)
|
||||
int all_layers; ///< output all spatial layers of a scalable AV1 biststream (default 1)
|
||||
unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited, default 0)
|
||||
Dav1dPicAllocator allocator; ///< Picture allocator callback.
|
||||
Dav1dLogger logger; ///< Logger callback.
|
||||
int strict_std_compliance; ///< whether to abort decoding on standard compliance violations
|
||||
///< that don't affect actual bitstream decoding (e.g. inconsistent
|
||||
///< or invalid metadata, default 0)
|
||||
int output_invisible_frames; ///< output invisibly coded frames (in coding order) in addition
|
||||
///< to all visible frames. Because of show-existing-frame, this
|
||||
///< means some frames may appear twice (once when coded,
|
||||
///< once when shown, default 0)
|
||||
enum Dav1dInloopFilterType inloop_filters; ///< postfilters to enable during decoding (default
|
||||
///< DAV1D_INLOOPFILTER_ALL)
|
||||
enum Dav1dDecodeFrameType decode_frame_type; ///< frame types to decode (default
|
||||
///< DAV1D_DECODEFRAMETYPE_ALL)
|
||||
uint8_t reserved[16]; ///< reserved for future use
|
||||
} Dav1dSettings;
|
||||
|
||||
/**
|
||||
* Get library version.
|
||||
*/
|
||||
DAV1D_API const char *dav1d_version(void);
|
||||
|
||||
/**
|
||||
* Get library API version.
|
||||
*
|
||||
* @return A value in the format 0x00XXYYZZ, where XX is the major version,
|
||||
* YY the minor version, and ZZ the patch version.
|
||||
* @see DAV1D_API_MAJOR, DAV1D_API_MINOR, DAV1D_API_PATCH
|
||||
*/
|
||||
DAV1D_API unsigned dav1d_version_api(void);
|
||||
|
||||
/**
|
||||
* Initialize settings to default values.
|
||||
*
|
||||
* @param s Input settings context.
|
||||
*/
|
||||
DAV1D_API void dav1d_default_settings(Dav1dSettings *s);
|
||||
|
||||
/**
|
||||
* Allocate and open a decoder instance.
|
||||
*
|
||||
* @param c_out The decoder instance to open. *c_out will be set to the
|
||||
* allocated context.
|
||||
* @param s Input settings context.
|
||||
*
|
||||
* @note The context must be freed using dav1d_close() when decoding is
|
||||
* finished.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_open(Dav1dContext **c_out, const Dav1dSettings *s);
|
||||
|
||||
/**
|
||||
* Parse a Sequence Header OBU from bitstream data.
|
||||
*
|
||||
* @param out Output Sequence Header.
|
||||
* @param buf The data to be parser.
|
||||
* @param sz Size of the data.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and out is filled with the parsed Sequence Header
|
||||
* OBU parameters.
|
||||
* DAV1D_ERR(ENOENT): No Sequence Header OBUs were found in the buffer.
|
||||
* Other negative DAV1D_ERR codes: Invalid data in the buffer, invalid passed-in
|
||||
* arguments, and other errors during parsing.
|
||||
*
|
||||
* @note It is safe to feed this function data containing other OBUs than a
|
||||
* Sequence Header, as they will simply be ignored. If there is more than
|
||||
* one Sequence Header OBU present, only the last will be returned.
|
||||
*/
|
||||
DAV1D_API int dav1d_parse_sequence_header(Dav1dSequenceHeader *out,
|
||||
const uint8_t *buf, const size_t sz);
|
||||
|
||||
/**
|
||||
* Feed bitstream data to the decoder, in the form of one or multiple AV1
|
||||
* Open Bitstream Units (OBUs).
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param in Input bitstream data. On success, ownership of the reference is
|
||||
* passed to the library.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and the data was consumed.
|
||||
* DAV1D_ERR(EAGAIN): The data can't be consumed. dav1d_get_picture() should
|
||||
* be called to get one or more frames before the function
|
||||
* can consume new data.
|
||||
* Other negative DAV1D_ERR codes: Error during decoding or because of invalid
|
||||
* passed-in arguments. The reference remains
|
||||
* owned by the caller.
|
||||
*/
|
||||
DAV1D_API int dav1d_send_data(Dav1dContext *c, Dav1dData *in);
|
||||
|
||||
/**
|
||||
* Return a decoded picture.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output frame. The caller assumes ownership of the returned
|
||||
* reference.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and a frame is returned.
|
||||
* DAV1D_ERR(EAGAIN): Not enough data to output a frame. dav1d_send_data()
|
||||
* should be called with new input.
|
||||
* Other negative DAV1D_ERR codes: Error during decoding or because of invalid
|
||||
* passed-in arguments.
|
||||
*
|
||||
* @note To drain buffered frames from the decoder (i.e. on end of stream),
|
||||
* call this function until it returns DAV1D_ERR(EAGAIN).
|
||||
*
|
||||
* @code{.c}
|
||||
* Dav1dData data = { 0 };
|
||||
* Dav1dPicture p = { 0 };
|
||||
* int res;
|
||||
*
|
||||
* read_data(&data);
|
||||
* do {
|
||||
* res = dav1d_send_data(c, &data);
|
||||
* // Keep going even if the function can't consume the current data
|
||||
* packet. It eventually will after one or more frames have been
|
||||
* returned in this loop.
|
||||
* if (res < 0 && res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* res = dav1d_get_picture(c, &p);
|
||||
* if (res < 0) {
|
||||
* if (res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* } else
|
||||
* output_and_unref_picture(&p);
|
||||
* // Stay in the loop as long as there's data to consume.
|
||||
* } while (data.sz || read_data(&data) == SUCCESS);
|
||||
*
|
||||
* // Handle EOS by draining all buffered frames.
|
||||
* do {
|
||||
* res = dav1d_get_picture(c, &p);
|
||||
* if (res < 0) {
|
||||
* if (res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* } else
|
||||
* output_and_unref_picture(&p);
|
||||
* } while (res == 0);
|
||||
* @endcode
|
||||
*/
|
||||
DAV1D_API int dav1d_get_picture(Dav1dContext *c, Dav1dPicture *out);
|
||||
|
||||
/**
|
||||
* Apply film grain to a previously decoded picture. If the picture contains no
|
||||
* film grain metadata, then this function merely returns a new reference.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output frame. The caller assumes ownership of the returned
|
||||
* reference.
|
||||
* @param in Input frame. No ownership is transferred.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and a frame is returned.
|
||||
* Other negative DAV1D_ERR codes: Error due to lack of memory or because of
|
||||
* invalid passed-in arguments.
|
||||
*
|
||||
* @note If `Dav1dSettings.apply_grain` is true, film grain was already applied
|
||||
* by `dav1d_get_picture`, and so calling this function leads to double
|
||||
* application of film grain. Users should only call this when needed.
|
||||
*/
|
||||
DAV1D_API int dav1d_apply_grain(Dav1dContext *c, Dav1dPicture *out,
|
||||
const Dav1dPicture *in);
|
||||
|
||||
/**
|
||||
* Close a decoder instance and free all associated memory.
|
||||
*
|
||||
* @param c_out The decoder instance to close. *c_out will be set to NULL.
|
||||
*/
|
||||
DAV1D_API void dav1d_close(Dav1dContext **c_out);
|
||||
|
||||
/**
|
||||
* Flush all delayed frames in decoder and clear internal decoder state,
|
||||
* to be used when seeking.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
*
|
||||
* @note Decoding will start only after a valid sequence header OBU is
|
||||
* delivered to dav1d_send_data().
|
||||
*
|
||||
*/
|
||||
DAV1D_API void dav1d_flush(Dav1dContext *c);
|
||||
|
||||
enum Dav1dEventFlags {
|
||||
/**
|
||||
* The last returned picture contains a reference to a new Sequence Header,
|
||||
* either because it's the start of a new coded sequence, or the decoder was
|
||||
* flushed before it was generated.
|
||||
*/
|
||||
DAV1D_EVENT_FLAG_NEW_SEQUENCE = 1 << 0,
|
||||
/**
|
||||
* The last returned picture contains a reference to a Sequence Header with
|
||||
* new operating parameters information for the current coded sequence.
|
||||
*/
|
||||
DAV1D_EVENT_FLAG_NEW_OP_PARAMS_INFO = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch a combination of DAV1D_EVENT_FLAG_* event flags generated by the decoding
|
||||
* process.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param flags Where to write the flags.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*
|
||||
* @note Calling this function will clear all the event flags currently stored in
|
||||
* the decoder.
|
||||
*
|
||||
*/
|
||||
DAV1D_API int dav1d_get_event_flags(Dav1dContext *c, enum Dav1dEventFlags *flags);
|
||||
|
||||
/**
|
||||
* Retrieve the user-provided metadata associated with the input data packet
|
||||
* for the last decoding error reported to the user, i.e. a negative return
|
||||
* value (not EAGAIN) from dav1d_send_data() or dav1d_get_picture().
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output Dav1dDataProps. On success, the caller assumes ownership of
|
||||
* the returned reference.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_get_decode_error_data_props(Dav1dContext *c, Dav1dDataProps *out);
|
||||
|
||||
/**
|
||||
* Get the decoder delay, which is the number of internally buffered frames, not
|
||||
* including reference frames.
|
||||
* This value is guaranteed to be >= 1 and <= max_frame_delay.
|
||||
*
|
||||
* @param s Input settings context.
|
||||
*
|
||||
* @return Decoder frame delay on success, or < 0 (a negative DAV1D_ERR code) on
|
||||
* error.
|
||||
*
|
||||
* @note The returned delay is valid only for a Dav1dContext initialized with the
|
||||
* provided Dav1dSettings.
|
||||
*/
|
||||
DAV1D_API int dav1d_get_frame_delay(const Dav1dSettings *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_H */
|
444
TMessagesProj/jni/ffmpeg/include/dav1d/headers.h
Normal file
444
TMessagesProj/jni/ffmpeg/include/dav1d/headers.h
Normal file
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Copyright © 2018-2020, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_HEADERS_H
|
||||
#define DAV1D_HEADERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Constants from Section 3. "Symbols and abbreviated terms"
|
||||
#define DAV1D_MAX_CDEF_STRENGTHS 8
|
||||
#define DAV1D_MAX_OPERATING_POINTS 32
|
||||
#define DAV1D_MAX_TILE_COLS 64
|
||||
#define DAV1D_MAX_TILE_ROWS 64
|
||||
#define DAV1D_MAX_SEGMENTS 8
|
||||
#define DAV1D_NUM_REF_FRAMES 8
|
||||
#define DAV1D_PRIMARY_REF_NONE 7
|
||||
#define DAV1D_REFS_PER_FRAME 7
|
||||
#define DAV1D_TOTAL_REFS_PER_FRAME (DAV1D_REFS_PER_FRAME + 1)
|
||||
|
||||
enum Dav1dObuType {
|
||||
DAV1D_OBU_SEQ_HDR = 1,
|
||||
DAV1D_OBU_TD = 2,
|
||||
DAV1D_OBU_FRAME_HDR = 3,
|
||||
DAV1D_OBU_TILE_GRP = 4,
|
||||
DAV1D_OBU_METADATA = 5,
|
||||
DAV1D_OBU_FRAME = 6,
|
||||
DAV1D_OBU_REDUNDANT_FRAME_HDR = 7,
|
||||
DAV1D_OBU_PADDING = 15,
|
||||
};
|
||||
|
||||
enum Dav1dTxfmMode {
|
||||
DAV1D_TX_4X4_ONLY,
|
||||
DAV1D_TX_LARGEST,
|
||||
DAV1D_TX_SWITCHABLE,
|
||||
DAV1D_N_TX_MODES,
|
||||
};
|
||||
|
||||
enum Dav1dFilterMode {
|
||||
DAV1D_FILTER_8TAP_REGULAR,
|
||||
DAV1D_FILTER_8TAP_SMOOTH,
|
||||
DAV1D_FILTER_8TAP_SHARP,
|
||||
DAV1D_N_SWITCHABLE_FILTERS,
|
||||
DAV1D_FILTER_BILINEAR = DAV1D_N_SWITCHABLE_FILTERS,
|
||||
DAV1D_N_FILTERS,
|
||||
DAV1D_FILTER_SWITCHABLE = DAV1D_N_FILTERS,
|
||||
};
|
||||
|
||||
enum Dav1dAdaptiveBoolean {
|
||||
DAV1D_OFF = 0,
|
||||
DAV1D_ON = 1,
|
||||
DAV1D_ADAPTIVE = 2,
|
||||
};
|
||||
|
||||
enum Dav1dRestorationType {
|
||||
DAV1D_RESTORATION_NONE,
|
||||
DAV1D_RESTORATION_SWITCHABLE,
|
||||
DAV1D_RESTORATION_WIENER,
|
||||
DAV1D_RESTORATION_SGRPROJ,
|
||||
};
|
||||
|
||||
enum Dav1dWarpedMotionType {
|
||||
DAV1D_WM_TYPE_IDENTITY,
|
||||
DAV1D_WM_TYPE_TRANSLATION,
|
||||
DAV1D_WM_TYPE_ROT_ZOOM,
|
||||
DAV1D_WM_TYPE_AFFINE,
|
||||
};
|
||||
|
||||
typedef struct Dav1dWarpedMotionParams {
|
||||
enum Dav1dWarpedMotionType type;
|
||||
int32_t matrix[6];
|
||||
union {
|
||||
struct {
|
||||
int16_t alpha, beta, gamma, delta;
|
||||
} p;
|
||||
int16_t abcd[4];
|
||||
} u;
|
||||
} Dav1dWarpedMotionParams;
|
||||
|
||||
enum Dav1dPixelLayout {
|
||||
DAV1D_PIXEL_LAYOUT_I400, ///< monochrome
|
||||
DAV1D_PIXEL_LAYOUT_I420, ///< 4:2:0 planar
|
||||
DAV1D_PIXEL_LAYOUT_I422, ///< 4:2:2 planar
|
||||
DAV1D_PIXEL_LAYOUT_I444, ///< 4:4:4 planar
|
||||
};
|
||||
|
||||
enum Dav1dFrameType {
|
||||
DAV1D_FRAME_TYPE_KEY = 0, ///< Key Intra frame
|
||||
DAV1D_FRAME_TYPE_INTER = 1, ///< Inter frame
|
||||
DAV1D_FRAME_TYPE_INTRA = 2, ///< Non key Intra frame
|
||||
DAV1D_FRAME_TYPE_SWITCH = 3, ///< Switch Inter frame
|
||||
};
|
||||
|
||||
enum Dav1dColorPrimaries {
|
||||
DAV1D_COLOR_PRI_BT709 = 1,
|
||||
DAV1D_COLOR_PRI_UNKNOWN = 2,
|
||||
DAV1D_COLOR_PRI_BT470M = 4,
|
||||
DAV1D_COLOR_PRI_BT470BG = 5,
|
||||
DAV1D_COLOR_PRI_BT601 = 6,
|
||||
DAV1D_COLOR_PRI_SMPTE240 = 7,
|
||||
DAV1D_COLOR_PRI_FILM = 8,
|
||||
DAV1D_COLOR_PRI_BT2020 = 9,
|
||||
DAV1D_COLOR_PRI_XYZ = 10,
|
||||
DAV1D_COLOR_PRI_SMPTE431 = 11,
|
||||
DAV1D_COLOR_PRI_SMPTE432 = 12,
|
||||
DAV1D_COLOR_PRI_EBU3213 = 22,
|
||||
DAV1D_COLOR_PRI_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dTransferCharacteristics {
|
||||
DAV1D_TRC_BT709 = 1,
|
||||
DAV1D_TRC_UNKNOWN = 2,
|
||||
DAV1D_TRC_BT470M = 4,
|
||||
DAV1D_TRC_BT470BG = 5,
|
||||
DAV1D_TRC_BT601 = 6,
|
||||
DAV1D_TRC_SMPTE240 = 7,
|
||||
DAV1D_TRC_LINEAR = 8,
|
||||
DAV1D_TRC_LOG100 = 9, ///< logarithmic (100:1 range)
|
||||
DAV1D_TRC_LOG100_SQRT10 = 10, ///< lograithmic (100*sqrt(10):1 range)
|
||||
DAV1D_TRC_IEC61966 = 11,
|
||||
DAV1D_TRC_BT1361 = 12,
|
||||
DAV1D_TRC_SRGB = 13,
|
||||
DAV1D_TRC_BT2020_10BIT = 14,
|
||||
DAV1D_TRC_BT2020_12BIT = 15,
|
||||
DAV1D_TRC_SMPTE2084 = 16, ///< PQ
|
||||
DAV1D_TRC_SMPTE428 = 17,
|
||||
DAV1D_TRC_HLG = 18, ///< hybrid log/gamma (BT.2100 / ARIB STD-B67)
|
||||
DAV1D_TRC_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dMatrixCoefficients {
|
||||
DAV1D_MC_IDENTITY = 0,
|
||||
DAV1D_MC_BT709 = 1,
|
||||
DAV1D_MC_UNKNOWN = 2,
|
||||
DAV1D_MC_FCC = 4,
|
||||
DAV1D_MC_BT470BG = 5,
|
||||
DAV1D_MC_BT601 = 6,
|
||||
DAV1D_MC_SMPTE240 = 7,
|
||||
DAV1D_MC_SMPTE_YCGCO = 8,
|
||||
DAV1D_MC_BT2020_NCL = 9,
|
||||
DAV1D_MC_BT2020_CL = 10,
|
||||
DAV1D_MC_SMPTE2085 = 11,
|
||||
DAV1D_MC_CHROMAT_NCL = 12, ///< Chromaticity-derived
|
||||
DAV1D_MC_CHROMAT_CL = 13,
|
||||
DAV1D_MC_ICTCP = 14,
|
||||
DAV1D_MC_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dChromaSamplePosition {
|
||||
DAV1D_CHR_UNKNOWN = 0,
|
||||
DAV1D_CHR_VERTICAL = 1, ///< Horizontally co-located with luma(0, 0)
|
||||
///< sample, between two vertical samples
|
||||
DAV1D_CHR_COLOCATED = 2, ///< Co-located with luma(0, 0) sample
|
||||
};
|
||||
|
||||
typedef struct Dav1dContentLightLevel {
|
||||
uint16_t max_content_light_level;
|
||||
uint16_t max_frame_average_light_level;
|
||||
} Dav1dContentLightLevel;
|
||||
|
||||
typedef struct Dav1dMasteringDisplay {
|
||||
///< 0.16 fixed point
|
||||
uint16_t primaries[3][2];
|
||||
///< 0.16 fixed point
|
||||
uint16_t white_point[2];
|
||||
///< 24.8 fixed point
|
||||
uint32_t max_luminance;
|
||||
///< 18.14 fixed point
|
||||
uint32_t min_luminance;
|
||||
} Dav1dMasteringDisplay;
|
||||
|
||||
typedef struct Dav1dITUTT35 {
|
||||
uint8_t country_code;
|
||||
uint8_t country_code_extension_byte;
|
||||
size_t payload_size;
|
||||
uint8_t *payload;
|
||||
} Dav1dITUTT35;
|
||||
|
||||
typedef struct Dav1dSequenceHeader {
|
||||
/**
|
||||
* Stream profile, 0 for 8-10 bits/component 4:2:0 or monochrome;
|
||||
* 1 for 8-10 bits/component 4:4:4; 2 for 4:2:2 at any bits/component,
|
||||
* or 12 bits/component at any chroma subsampling.
|
||||
*/
|
||||
uint8_t profile;
|
||||
/**
|
||||
* Maximum dimensions for this stream. In non-scalable streams, these
|
||||
* are often the actual dimensions of the stream, although that is not
|
||||
* a normative requirement.
|
||||
*/
|
||||
int max_width, max_height;
|
||||
enum Dav1dPixelLayout layout; ///< format of the picture
|
||||
enum Dav1dColorPrimaries pri; ///< color primaries (av1)
|
||||
enum Dav1dTransferCharacteristics trc; ///< transfer characteristics (av1)
|
||||
enum Dav1dMatrixCoefficients mtrx; ///< matrix coefficients (av1)
|
||||
enum Dav1dChromaSamplePosition chr; ///< chroma sample position (av1)
|
||||
/**
|
||||
* 0, 1 and 2 mean 8, 10 or 12 bits/component, respectively. This is not
|
||||
* exactly the same as 'hbd' from the spec; the spec's hbd distinguishes
|
||||
* between 8 (0) and 10-12 (1) bits/component, and another element
|
||||
* (twelve_bit) to distinguish between 10 and 12 bits/component. To get
|
||||
* the spec's hbd, use !!our_hbd, and to get twelve_bit, use hbd == 2.
|
||||
*/
|
||||
uint8_t hbd;
|
||||
/**
|
||||
* Pixel data uses JPEG pixel range ([0,255] for 8bits) instead of
|
||||
* MPEG pixel range ([16,235] for 8bits luma, [16,240] for 8bits chroma).
|
||||
*/
|
||||
uint8_t color_range;
|
||||
|
||||
uint8_t num_operating_points;
|
||||
struct Dav1dSequenceHeaderOperatingPoint {
|
||||
uint8_t major_level, minor_level;
|
||||
uint8_t initial_display_delay;
|
||||
uint16_t idc;
|
||||
uint8_t tier;
|
||||
uint8_t decoder_model_param_present;
|
||||
uint8_t display_model_param_present;
|
||||
} operating_points[DAV1D_MAX_OPERATING_POINTS];
|
||||
|
||||
uint8_t still_picture;
|
||||
uint8_t reduced_still_picture_header;
|
||||
uint8_t timing_info_present;
|
||||
uint32_t num_units_in_tick;
|
||||
uint32_t time_scale;
|
||||
uint8_t equal_picture_interval;
|
||||
uint32_t num_ticks_per_picture;
|
||||
uint8_t decoder_model_info_present;
|
||||
uint8_t encoder_decoder_buffer_delay_length;
|
||||
uint32_t num_units_in_decoding_tick;
|
||||
uint8_t buffer_removal_delay_length;
|
||||
uint8_t frame_presentation_delay_length;
|
||||
uint8_t display_model_info_present;
|
||||
uint8_t width_n_bits, height_n_bits;
|
||||
uint8_t frame_id_numbers_present;
|
||||
uint8_t delta_frame_id_n_bits;
|
||||
uint8_t frame_id_n_bits;
|
||||
uint8_t sb128;
|
||||
uint8_t filter_intra;
|
||||
uint8_t intra_edge_filter;
|
||||
uint8_t inter_intra;
|
||||
uint8_t masked_compound;
|
||||
uint8_t warped_motion;
|
||||
uint8_t dual_filter;
|
||||
uint8_t order_hint;
|
||||
uint8_t jnt_comp;
|
||||
uint8_t ref_frame_mvs;
|
||||
enum Dav1dAdaptiveBoolean screen_content_tools;
|
||||
enum Dav1dAdaptiveBoolean force_integer_mv;
|
||||
uint8_t order_hint_n_bits;
|
||||
uint8_t super_res;
|
||||
uint8_t cdef;
|
||||
uint8_t restoration;
|
||||
uint8_t ss_hor, ss_ver, monochrome;
|
||||
uint8_t color_description_present;
|
||||
uint8_t separate_uv_delta_q;
|
||||
uint8_t film_grain_present;
|
||||
|
||||
// Dav1dSequenceHeaders of the same sequence are required to be
|
||||
// bit-identical until this offset. See 7.5 "Ordering of OBUs":
|
||||
// Within a particular coded video sequence, the contents of
|
||||
// sequence_header_obu must be bit-identical each time the
|
||||
// sequence header appears except for the contents of
|
||||
// operating_parameters_info.
|
||||
struct Dav1dSequenceHeaderOperatingParameterInfo {
|
||||
uint32_t decoder_buffer_delay;
|
||||
uint32_t encoder_buffer_delay;
|
||||
uint8_t low_delay_mode;
|
||||
} operating_parameter_info[DAV1D_MAX_OPERATING_POINTS];
|
||||
} Dav1dSequenceHeader;
|
||||
|
||||
typedef struct Dav1dSegmentationData {
|
||||
int16_t delta_q;
|
||||
int8_t delta_lf_y_v, delta_lf_y_h, delta_lf_u, delta_lf_v;
|
||||
int8_t ref;
|
||||
uint8_t skip;
|
||||
uint8_t globalmv;
|
||||
} Dav1dSegmentationData;
|
||||
|
||||
typedef struct Dav1dSegmentationDataSet {
|
||||
Dav1dSegmentationData d[DAV1D_MAX_SEGMENTS];
|
||||
uint8_t preskip;
|
||||
int8_t last_active_segid;
|
||||
} Dav1dSegmentationDataSet;
|
||||
|
||||
typedef struct Dav1dLoopfilterModeRefDeltas {
|
||||
int8_t mode_delta[2 /* is_zeromv */];
|
||||
int8_t ref_delta[DAV1D_TOTAL_REFS_PER_FRAME];
|
||||
} Dav1dLoopfilterModeRefDeltas;
|
||||
|
||||
typedef struct Dav1dFilmGrainData {
|
||||
unsigned seed;
|
||||
int num_y_points;
|
||||
uint8_t y_points[14][2 /* value, scaling */];
|
||||
int chroma_scaling_from_luma;
|
||||
int num_uv_points[2];
|
||||
uint8_t uv_points[2][10][2 /* value, scaling */];
|
||||
int scaling_shift;
|
||||
int ar_coeff_lag;
|
||||
int8_t ar_coeffs_y[24];
|
||||
int8_t ar_coeffs_uv[2][25 + 3 /* padding for alignment purposes */];
|
||||
uint64_t ar_coeff_shift;
|
||||
int grain_scale_shift;
|
||||
int uv_mult[2];
|
||||
int uv_luma_mult[2];
|
||||
int uv_offset[2];
|
||||
int overlap_flag;
|
||||
int clip_to_restricted_range;
|
||||
} Dav1dFilmGrainData;
|
||||
|
||||
typedef struct Dav1dFrameHeader {
|
||||
struct {
|
||||
Dav1dFilmGrainData data;
|
||||
uint8_t present, update;
|
||||
} film_grain; ///< film grain parameters
|
||||
enum Dav1dFrameType frame_type; ///< type of the picture
|
||||
int width[2 /* { coded_width, superresolution_upscaled_width } */], height;
|
||||
uint8_t frame_offset; ///< frame number
|
||||
uint8_t temporal_id; ///< temporal id of the frame for SVC
|
||||
uint8_t spatial_id; ///< spatial id of the frame for SVC
|
||||
|
||||
uint8_t show_existing_frame;
|
||||
uint8_t existing_frame_idx;
|
||||
uint32_t frame_id;
|
||||
uint32_t frame_presentation_delay;
|
||||
uint8_t show_frame;
|
||||
uint8_t showable_frame;
|
||||
uint8_t error_resilient_mode;
|
||||
uint8_t disable_cdf_update;
|
||||
uint8_t allow_screen_content_tools;
|
||||
uint8_t force_integer_mv;
|
||||
uint8_t frame_size_override;
|
||||
uint8_t primary_ref_frame;
|
||||
uint8_t buffer_removal_time_present;
|
||||
struct Dav1dFrameHeaderOperatingPoint {
|
||||
uint32_t buffer_removal_time;
|
||||
} operating_points[DAV1D_MAX_OPERATING_POINTS];
|
||||
uint8_t refresh_frame_flags;
|
||||
int render_width, render_height;
|
||||
struct {
|
||||
uint8_t width_scale_denominator;
|
||||
uint8_t enabled;
|
||||
} super_res;
|
||||
uint8_t have_render_size;
|
||||
uint8_t allow_intrabc;
|
||||
uint8_t frame_ref_short_signaling;
|
||||
int8_t refidx[DAV1D_REFS_PER_FRAME];
|
||||
uint8_t hp;
|
||||
enum Dav1dFilterMode subpel_filter_mode;
|
||||
uint8_t switchable_motion_mode;
|
||||
uint8_t use_ref_frame_mvs;
|
||||
uint8_t refresh_context;
|
||||
struct {
|
||||
uint8_t uniform;
|
||||
uint8_t n_bytes;
|
||||
uint8_t min_log2_cols, max_log2_cols, log2_cols, cols;
|
||||
uint8_t min_log2_rows, max_log2_rows, log2_rows, rows;
|
||||
uint16_t col_start_sb[DAV1D_MAX_TILE_COLS + 1];
|
||||
uint16_t row_start_sb[DAV1D_MAX_TILE_ROWS + 1];
|
||||
uint16_t update;
|
||||
} tiling;
|
||||
struct {
|
||||
uint8_t yac;
|
||||
int8_t ydc_delta;
|
||||
int8_t udc_delta, uac_delta, vdc_delta, vac_delta;
|
||||
uint8_t qm, qm_y, qm_u, qm_v;
|
||||
} quant;
|
||||
struct {
|
||||
uint8_t enabled, update_map, temporal, update_data;
|
||||
Dav1dSegmentationDataSet seg_data;
|
||||
uint8_t lossless[DAV1D_MAX_SEGMENTS], qidx[DAV1D_MAX_SEGMENTS];
|
||||
} segmentation;
|
||||
struct {
|
||||
struct {
|
||||
uint8_t present;
|
||||
uint8_t res_log2;
|
||||
} q;
|
||||
struct {
|
||||
uint8_t present;
|
||||
uint8_t res_log2;
|
||||
uint8_t multi;
|
||||
} lf;
|
||||
} delta;
|
||||
uint8_t all_lossless;
|
||||
struct {
|
||||
uint8_t level_y[2 /* dir */];
|
||||
uint8_t level_u, level_v;
|
||||
uint8_t mode_ref_delta_enabled;
|
||||
uint8_t mode_ref_delta_update;
|
||||
Dav1dLoopfilterModeRefDeltas mode_ref_deltas;
|
||||
uint8_t sharpness;
|
||||
} loopfilter;
|
||||
struct {
|
||||
uint8_t damping;
|
||||
uint8_t n_bits;
|
||||
uint8_t y_strength[DAV1D_MAX_CDEF_STRENGTHS];
|
||||
uint8_t uv_strength[DAV1D_MAX_CDEF_STRENGTHS];
|
||||
} cdef;
|
||||
struct {
|
||||
enum Dav1dRestorationType type[3 /* plane */];
|
||||
uint8_t unit_size[2 /* y, uv */];
|
||||
} restoration;
|
||||
enum Dav1dTxfmMode txfm_mode;
|
||||
uint8_t switchable_comp_refs;
|
||||
uint8_t skip_mode_allowed, skip_mode_enabled;
|
||||
int8_t skip_mode_refs[2];
|
||||
uint8_t warp_motion;
|
||||
uint8_t reduced_txtp_set;
|
||||
Dav1dWarpedMotionParams gmv[DAV1D_REFS_PER_FRAME];
|
||||
} Dav1dFrameHeader;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_HEADERS_H */
|
157
TMessagesProj/jni/ffmpeg/include/dav1d/picture.h
Normal file
157
TMessagesProj/jni/ffmpeg/include/dav1d/picture.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright © 2018-2020, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_PICTURE_H
|
||||
#define DAV1D_PICTURE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "headers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Number of bytes to align AND pad picture memory buffers by, so that SIMD
|
||||
* implementations can over-read by a few bytes, and use aligned read/write
|
||||
* instructions. */
|
||||
#define DAV1D_PICTURE_ALIGNMENT 64
|
||||
|
||||
typedef struct Dav1dPictureParameters {
|
||||
int w; ///< width (in pixels)
|
||||
int h; ///< height (in pixels)
|
||||
enum Dav1dPixelLayout layout; ///< format of the picture
|
||||
int bpc; ///< bits per pixel component (8 or 10)
|
||||
} Dav1dPictureParameters;
|
||||
|
||||
typedef struct Dav1dPicture {
|
||||
Dav1dSequenceHeader *seq_hdr;
|
||||
Dav1dFrameHeader *frame_hdr;
|
||||
|
||||
/**
|
||||
* Pointers to planar image data (Y is [0], U is [1], V is [2]). The data
|
||||
* should be bytes (for 8 bpc) or words (for 10 bpc). In case of words
|
||||
* containing 10 bpc image data, the pixels should be located in the LSB
|
||||
* bits, so that values range between [0, 1023]; the upper bits should be
|
||||
* zero'ed out.
|
||||
*/
|
||||
void *data[3];
|
||||
|
||||
/**
|
||||
* Number of bytes between 2 lines in data[] for luma [0] or chroma [1].
|
||||
*/
|
||||
ptrdiff_t stride[2];
|
||||
|
||||
Dav1dPictureParameters p;
|
||||
Dav1dDataProps m;
|
||||
|
||||
/**
|
||||
* High Dynamic Range Content Light Level metadata applying to this picture,
|
||||
* as defined in section 5.8.3 and 6.7.3
|
||||
*/
|
||||
Dav1dContentLightLevel *content_light;
|
||||
/**
|
||||
* High Dynamic Range Mastering Display Color Volume metadata applying to
|
||||
* this picture, as defined in section 5.8.4 and 6.7.4
|
||||
*/
|
||||
Dav1dMasteringDisplay *mastering_display;
|
||||
/**
|
||||
* Array of ITU-T T.35 metadata as defined in section 5.8.2 and 6.7.2
|
||||
*/
|
||||
Dav1dITUTT35 *itut_t35;
|
||||
|
||||
/**
|
||||
* Number of ITU-T T35 metadata entries in the array
|
||||
*/
|
||||
size_t n_itut_t35;
|
||||
|
||||
uintptr_t reserved[4]; ///< reserved for future use
|
||||
|
||||
struct Dav1dRef *frame_hdr_ref; ///< Dav1dFrameHeader allocation origin
|
||||
struct Dav1dRef *seq_hdr_ref; ///< Dav1dSequenceHeader allocation origin
|
||||
struct Dav1dRef *content_light_ref; ///< Dav1dContentLightLevel allocation origin
|
||||
struct Dav1dRef *mastering_display_ref; ///< Dav1dMasteringDisplay allocation origin
|
||||
struct Dav1dRef *itut_t35_ref; ///< Dav1dITUTT35 allocation origin
|
||||
uintptr_t reserved_ref[4]; ///< reserved for future use
|
||||
struct Dav1dRef *ref; ///< Frame data allocation origin
|
||||
|
||||
void *allocator_data; ///< pointer managed by the allocator
|
||||
} Dav1dPicture;
|
||||
|
||||
typedef struct Dav1dPicAllocator {
|
||||
void *cookie; ///< custom data to pass to the allocator callbacks.
|
||||
/**
|
||||
* Allocate the picture buffer based on the Dav1dPictureParameters.
|
||||
*
|
||||
* The data[0], data[1] and data[2] must be DAV1D_PICTURE_ALIGNMENT byte
|
||||
* aligned and with a pixel width/height multiple of 128 pixels. Any
|
||||
* allocated memory area should also be padded by DAV1D_PICTURE_ALIGNMENT
|
||||
* bytes.
|
||||
* data[1] and data[2] must share the same stride[1].
|
||||
*
|
||||
* This function will be called on the main thread (the thread which calls
|
||||
* dav1d_get_picture()).
|
||||
*
|
||||
* @param pic The picture to allocate the buffer for. The callback needs to
|
||||
* fill the picture data[0], data[1], data[2], stride[0] and
|
||||
* stride[1].
|
||||
* The allocator can fill the pic allocator_data pointer with
|
||||
* a custom pointer that will be passed to
|
||||
* release_picture_callback().
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
*
|
||||
* @note No fields other than data, stride and allocator_data must be filled
|
||||
* by this callback.
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
int (*alloc_picture_callback)(Dav1dPicture *pic, void *cookie);
|
||||
/**
|
||||
* Release the picture buffer.
|
||||
*
|
||||
* If frame threading is used, this function may be called by the main
|
||||
* thread (the thread which calls dav1d_get_picture()) or any of the frame
|
||||
* threads and thus must be thread-safe. If frame threading is not used,
|
||||
* this function will only be called on the main thread.
|
||||
*
|
||||
* @param pic The picture that was filled by alloc_picture_callback().
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
*/
|
||||
void (*release_picture_callback)(Dav1dPicture *pic, void *cookie);
|
||||
} Dav1dPicAllocator;
|
||||
|
||||
/**
|
||||
* Release reference to a picture.
|
||||
*/
|
||||
DAV1D_API void dav1d_picture_unref(Dav1dPicture *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_PICTURE_H */
|
50
TMessagesProj/jni/ffmpeg/include/dav1d/version.h
Normal file
50
TMessagesProj/jni/ffmpeg/include/dav1d/version.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2019-2024, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_VERSION_H
|
||||
#define DAV1D_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DAV1D_API_VERSION_MAJOR 7
|
||||
#define DAV1D_API_VERSION_MINOR 0
|
||||
#define DAV1D_API_VERSION_PATCH 0
|
||||
|
||||
/**
|
||||
* Extract version components from the value returned by
|
||||
* dav1d_version_int()
|
||||
*/
|
||||
#define DAV1D_API_MAJOR(v) (((v) >> 16) & 0xFF)
|
||||
#define DAV1D_API_MINOR(v) (((v) >> 8) & 0xFF)
|
||||
#define DAV1D_API_PATCH(v) (((v) >> 0) & 0xFF)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_VERSION_H */
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
TMessagesProj/jni/ffmpeg/x86/libdav1d.a
Normal file
BIN
TMessagesProj/jni/ffmpeg/x86/libdav1d.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
TMessagesProj/jni/ffmpeg/x86_64/libdav1d.a
Normal file
BIN
TMessagesProj/jni/ffmpeg/x86_64/libdav1d.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -44,53 +44,6 @@ jmethodID jclass_AnimatedFileDrawableStream_isCanceled;
|
|||
jmethodID jclass_AnimatedFileDrawableStream_isFinishedLoadingFile;
|
||||
jmethodID jclass_AnimatedFileDrawableStream_getFinishedFilePath;
|
||||
|
||||
typedef struct H2645NAL {
|
||||
uint8_t *rbsp_buffer;
|
||||
int size;
|
||||
const uint8_t *data;
|
||||
int size_bits;
|
||||
int raw_size;
|
||||
const uint8_t *raw_data;
|
||||
int type;
|
||||
int temporal_id;
|
||||
int nuh_layer_id;
|
||||
int skipped_bytes;
|
||||
int skipped_bytes_pos_size;
|
||||
int *skipped_bytes_pos;
|
||||
int ref_idc;
|
||||
GetBitContext gb;
|
||||
} H2645NAL;
|
||||
|
||||
typedef struct H2645RBSP {
|
||||
uint8_t *rbsp_buffer;
|
||||
AVBufferRef *rbsp_buffer_ref;
|
||||
int rbsp_buffer_alloc_size;
|
||||
int rbsp_buffer_size;
|
||||
} H2645RBSP;
|
||||
|
||||
typedef struct H2645Packet {
|
||||
H2645NAL *nals;
|
||||
H2645RBSP rbsp;
|
||||
int nb_nals;
|
||||
int nals_allocated;
|
||||
unsigned nal_buffer_size;
|
||||
} H2645Packet;
|
||||
|
||||
void ff_h2645_packet_uninit(H2645Packet *pkt) {
|
||||
int i;
|
||||
for (i = 0; i < pkt->nals_allocated; i++) {
|
||||
av_freep(&pkt->nals[i].skipped_bytes_pos);
|
||||
}
|
||||
av_freep(&pkt->nals);
|
||||
pkt->nals_allocated = pkt->nal_buffer_size = 0;
|
||||
if (pkt->rbsp.rbsp_buffer_ref) {
|
||||
av_buffer_unref(&pkt->rbsp.rbsp_buffer_ref);
|
||||
pkt->rbsp.rbsp_buffer = NULL;
|
||||
} else
|
||||
av_freep(&pkt->rbsp.rbsp_buffer);
|
||||
pkt->rbsp.rbsp_buffer_alloc_size = pkt->rbsp.rbsp_buffer_size = 0;
|
||||
}
|
||||
|
||||
typedef struct VideoInfo {
|
||||
|
||||
~VideoInfo() {
|
||||
|
@ -145,7 +98,6 @@ typedef struct VideoInfo {
|
|||
fd = -1;
|
||||
}
|
||||
|
||||
ff_h2645_packet_uninit(&h2645Packet);
|
||||
av_packet_unref(&orig_pkt);
|
||||
|
||||
video_stream_idx = -1;
|
||||
|
@ -171,8 +123,6 @@ typedef struct VideoInfo {
|
|||
|
||||
bool dropFrames = false;
|
||||
|
||||
H2645Packet h2645Packet = {nullptr};
|
||||
|
||||
int32_t dst_linesize[1];
|
||||
|
||||
struct SwsContext *sws_ctx = nullptr;
|
||||
|
@ -252,477 +202,28 @@ int open_codec_context(int *stream_idx, AVCodecContext **dec_ctx, AVFormatContex
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_MBPAIR_SIZE (256*1024)
|
||||
|
||||
int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645RBSP *rbsp, H2645NAL *nal)
|
||||
{
|
||||
int i, si, di;
|
||||
uint8_t *dst;
|
||||
|
||||
nal->skipped_bytes = 0;
|
||||
#define STARTCODE_TEST \
|
||||
if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \
|
||||
if (src[i + 2] != 3 && src[i + 2] != 0) { \
|
||||
/* startcode, so we must be past the end */ \
|
||||
length = i; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
for (i = 0; i + 1 < length; i += 2) {
|
||||
if (src[i])
|
||||
continue;
|
||||
if (i > 0 && src[i - 1] == 0)
|
||||
i--;
|
||||
STARTCODE_TEST;
|
||||
}
|
||||
|
||||
if (i > length)
|
||||
i = length;
|
||||
|
||||
nal->rbsp_buffer = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size];
|
||||
dst = nal->rbsp_buffer;
|
||||
|
||||
memcpy(dst, src, i);
|
||||
si = di = i;
|
||||
while (si + 2 < length) {
|
||||
if (src[si + 2] > 3) {
|
||||
dst[di++] = src[si++];
|
||||
dst[di++] = src[si++];
|
||||
} else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) {
|
||||
if (src[si + 2] == 3) {
|
||||
dst[di++] = 0;
|
||||
dst[di++] = 0;
|
||||
si += 3;
|
||||
|
||||
if (nal->skipped_bytes_pos) {
|
||||
nal->skipped_bytes++;
|
||||
if (nal->skipped_bytes_pos_size < nal->skipped_bytes) {
|
||||
nal->skipped_bytes_pos_size *= 2;
|
||||
av_reallocp_array(&nal->skipped_bytes_pos,
|
||||
nal->skipped_bytes_pos_size,
|
||||
sizeof(*nal->skipped_bytes_pos));
|
||||
if (!nal->skipped_bytes_pos) {
|
||||
nal->skipped_bytes_pos_size = 0;
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
if (nal->skipped_bytes_pos)
|
||||
nal->skipped_bytes_pos[nal->skipped_bytes-1] = di - 1;
|
||||
}
|
||||
continue;
|
||||
} else // next start code
|
||||
goto nsc;
|
||||
}
|
||||
|
||||
dst[di++] = src[si++];
|
||||
}
|
||||
while (si < length)
|
||||
dst[di++] = src[si++];
|
||||
|
||||
nsc:
|
||||
memset(dst + di, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
nal->data = dst;
|
||||
nal->size = di;
|
||||
nal->raw_data = src;
|
||||
nal->raw_size = si;
|
||||
rbsp->rbsp_buffer_size += si;
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
static inline int get_nalsize(int nal_length_size, const uint8_t *buf, int buf_size, int *buf_index) {
|
||||
int i, nalsize = 0;
|
||||
if (*buf_index >= buf_size - nal_length_size) {
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
for (i = 0; i < nal_length_size; i++)
|
||||
nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
|
||||
if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
return nalsize;
|
||||
}
|
||||
|
||||
static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc) {
|
||||
int i = 0;
|
||||
if (buf + 3 >= next_avc)
|
||||
return next_avc - buf;
|
||||
while (buf + i + 3 < next_avc) {
|
||||
if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return i + 3;
|
||||
}
|
||||
|
||||
static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) {
|
||||
int size = nal->size;
|
||||
int v;
|
||||
|
||||
while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)
|
||||
size--;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
v = nal->data[size - 1];
|
||||
|
||||
if (size > INT_MAX / 8)
|
||||
return AVERROR(ERANGE);
|
||||
size *= 8;
|
||||
|
||||
/* remove the stop bit and following trailing zeros,
|
||||
* or nothing for damaged bitstreams */
|
||||
if (v)
|
||||
size -= ff_ctz(v) + 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void alloc_rbsp_buffer(H2645RBSP *rbsp, unsigned int size) {
|
||||
int min_size = size;
|
||||
|
||||
if (size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
|
||||
goto fail;
|
||||
size += AV_INPUT_BUFFER_PADDING_SIZE;
|
||||
|
||||
if (rbsp->rbsp_buffer_alloc_size >= size &&
|
||||
(!rbsp->rbsp_buffer_ref || av_buffer_is_writable(rbsp->rbsp_buffer_ref))) {
|
||||
memset(rbsp->rbsp_buffer + min_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
size = FFMIN(size + size / 16 + 32, INT_MAX);
|
||||
|
||||
if (rbsp->rbsp_buffer_ref)
|
||||
av_buffer_unref(&rbsp->rbsp_buffer_ref);
|
||||
else
|
||||
av_free(rbsp->rbsp_buffer);
|
||||
|
||||
rbsp->rbsp_buffer = (uint8_t *) av_mallocz(size);
|
||||
if (!rbsp->rbsp_buffer)
|
||||
goto fail;
|
||||
rbsp->rbsp_buffer_alloc_size = size;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
rbsp->rbsp_buffer_alloc_size = 0;
|
||||
if (rbsp->rbsp_buffer_ref) {
|
||||
av_buffer_unref(&rbsp->rbsp_buffer_ref);
|
||||
rbsp->rbsp_buffer = NULL;
|
||||
} else
|
||||
av_freep(&rbsp->rbsp_buffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int h264_parse_nal_header(H2645NAL *nal) {
|
||||
GetBitContext *gb = &nal->gb;
|
||||
|
||||
if (get_bits1(gb) != 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
nal->ref_idc = get_bits(gb, 2);
|
||||
nal->type = get_bits(gb, 5);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, int is_nalff, int nal_length_size) {
|
||||
GetByteContext bc;
|
||||
int consumed, ret = 0;
|
||||
int next_avc = is_nalff ? 0 : length;
|
||||
int64_t padding = MAX_MBPAIR_SIZE;
|
||||
|
||||
bytestream2_init(&bc, buf, length);
|
||||
alloc_rbsp_buffer(&pkt->rbsp, length + padding);
|
||||
|
||||
if (!pkt->rbsp.rbsp_buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
pkt->rbsp.rbsp_buffer_size = 0;
|
||||
pkt->nb_nals = 0;
|
||||
while (bytestream2_get_bytes_left(&bc) >= 4) {
|
||||
H2645NAL *nal;
|
||||
int extract_length = 0;
|
||||
int skip_trailing_zeros = 1;
|
||||
|
||||
if (bytestream2_tell(&bc) == next_avc) {
|
||||
int i = 0;
|
||||
extract_length = get_nalsize(nal_length_size, bc.buffer, bytestream2_get_bytes_left(&bc), &i);
|
||||
if (extract_length < 0)
|
||||
return extract_length;
|
||||
|
||||
bytestream2_skip(&bc, nal_length_size);
|
||||
|
||||
next_avc = bytestream2_tell(&bc) + extract_length;
|
||||
} else {
|
||||
int buf_index;
|
||||
buf_index = find_next_start_code(bc.buffer, buf + next_avc);
|
||||
bytestream2_skip(&bc, buf_index);
|
||||
if (!bytestream2_get_bytes_left(&bc)) {
|
||||
if (pkt->nb_nals > 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
extract_length = FFMIN(bytestream2_get_bytes_left(&bc), next_avc - bytestream2_tell(&bc));
|
||||
if (bytestream2_tell(&bc) >= next_avc) {
|
||||
bytestream2_skip(&bc, next_avc - bytestream2_tell(&bc));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pkt->nals_allocated < pkt->nb_nals + 1) {
|
||||
int new_size = pkt->nals_allocated + 1;
|
||||
void *tmp;
|
||||
|
||||
if (new_size >= INT_MAX / sizeof(*pkt->nals))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
tmp = av_fast_realloc(pkt->nals, &pkt->nal_buffer_size, new_size * sizeof(*pkt->nals));
|
||||
if (!tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
pkt->nals = (H2645NAL *) tmp;
|
||||
memset(pkt->nals + pkt->nals_allocated, 0, sizeof(*pkt->nals));
|
||||
|
||||
nal = &pkt->nals[pkt->nb_nals];
|
||||
nal->skipped_bytes_pos_size = 1024;
|
||||
nal->skipped_bytes_pos = (int *) av_malloc_array(nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos));
|
||||
if (!nal->skipped_bytes_pos)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
pkt->nals_allocated = new_size;
|
||||
}
|
||||
nal = &pkt->nals[pkt->nb_nals];
|
||||
|
||||
consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, &pkt->rbsp, nal);
|
||||
if (consumed < 0)
|
||||
return consumed;
|
||||
|
||||
pkt->nb_nals++;
|
||||
|
||||
bytestream2_skip(&bc, consumed);
|
||||
|
||||
/* see commit 3566042a0 */
|
||||
if (bytestream2_get_bytes_left(&bc) >= 4 &&
|
||||
bytestream2_peek_be32(&bc) == 0x000001E0)
|
||||
skip_trailing_zeros = 0;
|
||||
|
||||
nal->size_bits = get_bit_length(nal, skip_trailing_zeros);
|
||||
|
||||
ret = init_get_bits(&nal->gb, nal->data, nal->size_bits);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = h264_parse_nal_header(nal);
|
||||
if (ret <= 0 || nal->size <= 0 || nal->size_bits <= 0) {
|
||||
pkt->nb_nals--;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_SPS_COUNT 32
|
||||
|
||||
const uint8_t ff_zigzag_direct[64] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
||||
|
||||
const uint8_t ff_zigzag_scan[16+1] = {
|
||||
0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
|
||||
1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
|
||||
1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
|
||||
3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
|
||||
};
|
||||
|
||||
static int decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size) {
|
||||
int i, last = 8, next = 8;
|
||||
const uint8_t *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct;
|
||||
if (!get_bits1(gb)) {
|
||||
|
||||
} else {
|
||||
for (i = 0; i < size; i++) {
|
||||
if (next) {
|
||||
int v = get_se_golomb(gb);
|
||||
if (v < -128 || v > 127) {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
next = (last + v) & 0xff;
|
||||
}
|
||||
if (!i && !next) { /* matrix not written, we use the preset one */
|
||||
break;
|
||||
}
|
||||
last = factors[scan[i]] = next ? next : last;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_scaling_matrices(GetBitContext *gb, int chroma_format_idc, uint8_t(*scaling_matrix4)[16], uint8_t(*scaling_matrix8)[64]) {
|
||||
int ret = 0;
|
||||
if (get_bits1(gb)) {
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[0], 16); // Intra, Y
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[1], 16); // Intra, Cr
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[2], 16); // Intra, Cb
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[3], 16); // Inter, Y
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[4], 16); // Inter, Cr
|
||||
ret |= decode_scaling_list(gb, scaling_matrix4[5], 16); // Inter, Cb
|
||||
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[0], 64); // Intra, Y
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[3], 64); // Inter, Y
|
||||
if (chroma_format_idc == 3) {
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[1], 64); // Intra, Cr
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[4], 64); // Inter, Cr
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[2], 64); // Intra, Cb
|
||||
ret |= decode_scaling_list(gb, scaling_matrix8[5], 64); // Inter, Cb
|
||||
}
|
||||
if (!ret)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ff_h264_decode_seq_parameter_set(GetBitContext *gb, int &width, int &height) {
|
||||
int profile_idc, level_idc, constraint_set_flags = 0;
|
||||
unsigned int sps_id;
|
||||
int i, log2_max_frame_num_minus4;
|
||||
int ret;
|
||||
|
||||
profile_idc = get_bits(gb, 8);
|
||||
constraint_set_flags |= get_bits1(gb) << 0;
|
||||
constraint_set_flags |= get_bits1(gb) << 1;
|
||||
constraint_set_flags |= get_bits1(gb) << 2;
|
||||
constraint_set_flags |= get_bits1(gb) << 3;
|
||||
constraint_set_flags |= get_bits1(gb) << 4;
|
||||
constraint_set_flags |= get_bits1(gb) << 5;
|
||||
skip_bits(gb, 2);
|
||||
level_idc = get_bits(gb, 8);
|
||||
sps_id = get_ue_golomb_31(gb);
|
||||
|
||||
if (sps_id >= MAX_SPS_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (profile_idc == 100 || // High profile
|
||||
profile_idc == 110 || // High10 profile
|
||||
profile_idc == 122 || // High422 profile
|
||||
profile_idc == 244 || // High444 Predictive profile
|
||||
profile_idc == 44 || // Cavlc444 profile
|
||||
profile_idc == 83 || // Scalable Constrained High profile (SVC)
|
||||
profile_idc == 86 || // Scalable High Intra profile (SVC)
|
||||
profile_idc == 118 || // Stereo High profile (MVC)
|
||||
profile_idc == 128 || // Multiview High profile (MVC)
|
||||
profile_idc == 138 || // Multiview Depth High profile (MVCD)
|
||||
profile_idc == 144) { // old High444 profile
|
||||
int chroma_format_idc = get_ue_golomb_31(gb);
|
||||
if (chroma_format_idc > 3U) {
|
||||
return false;
|
||||
} else if (chroma_format_idc == 3) {
|
||||
int residual_color_transform_flag = get_bits1(gb);
|
||||
if (residual_color_transform_flag) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int bit_depth_luma = get_ue_golomb(gb) + 8;
|
||||
int bit_depth_chroma = get_ue_golomb(gb) + 8;
|
||||
if (bit_depth_chroma != bit_depth_luma) {
|
||||
return false;
|
||||
}
|
||||
if (bit_depth_luma < 8 || bit_depth_luma > 14 || bit_depth_chroma < 8 || bit_depth_chroma > 14) {
|
||||
return false;
|
||||
}
|
||||
get_bits1(gb);
|
||||
uint8_t scaling_matrix4[6][16];
|
||||
uint8_t scaling_matrix8[6][64];
|
||||
ret = decode_scaling_matrices(gb, chroma_format_idc, scaling_matrix4, scaling_matrix8);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
get_ue_golomb(gb);
|
||||
|
||||
int poc_type = get_ue_golomb_31(gb);
|
||||
|
||||
if (poc_type == 0) {
|
||||
unsigned t = get_ue_golomb(gb);
|
||||
if (t > 12) {
|
||||
return false;
|
||||
}
|
||||
} else if (poc_type == 1) {
|
||||
get_bits1(gb);
|
||||
int offset_for_non_ref_pic = get_se_golomb_long(gb);
|
||||
int offset_for_top_to_bottom_field = get_se_golomb_long(gb);
|
||||
|
||||
if (offset_for_non_ref_pic == INT32_MIN || offset_for_top_to_bottom_field == INT32_MIN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int poc_cycle_length = get_ue_golomb(gb);
|
||||
|
||||
if ((unsigned) poc_cycle_length >= 256) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < poc_cycle_length; i++) {
|
||||
int offset_for_ref_frame = get_se_golomb_long(gb);
|
||||
if (offset_for_ref_frame == INT32_MIN) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (poc_type != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
get_ue_golomb_31(gb);
|
||||
get_bits1(gb);
|
||||
int mb_width = get_ue_golomb(gb) + 1;
|
||||
int mb_height = get_ue_golomb(gb) + 1;
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
width = mb_width;
|
||||
height = mb_height;
|
||||
}
|
||||
return mb_width != width || mb_height != height;
|
||||
}
|
||||
|
||||
int decode_packet(VideoInfo *info, int *got_frame) {
|
||||
int ret = 0;
|
||||
int decoded = info->pkt.size;
|
||||
*got_frame = 0;
|
||||
|
||||
if (info->pkt.stream_index == info->video_stream_idx) {
|
||||
if (info->video_stream->codecpar->codec_id == AV_CODEC_ID_H264 && decoded > 0) {
|
||||
ff_h2645_packet_split(&info->h2645Packet, info->pkt.data, info->pkt.size, 1, 4);
|
||||
for (int i = 0; i < info->h2645Packet.nb_nals; i++) {
|
||||
H2645NAL *nal = &info->h2645Packet.nals[i];
|
||||
switch (nal->type) {
|
||||
case 7: {
|
||||
GetBitContext tmp_gb = nal->gb;
|
||||
info->dropFrames = ff_h264_decode_seq_parameter_set(&tmp_gb, info->firstWidth, info->firstHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!info->dropFrames) {
|
||||
ret = avcodec_decode_video2(info->video_dec_ctx, info->frame, got_frame, &info->pkt);
|
||||
if (ret != 0) {
|
||||
while (decoded > 0) {
|
||||
ret = avcodec_send_packet(info->video_dec_ctx, &info->pkt);
|
||||
if (ret < 0 && ret != AVERROR(EAGAIN)) {
|
||||
return ret;
|
||||
}
|
||||
if (ret >= 0) {
|
||||
ret = avcodec_receive_frame(info->video_dec_ctx, info->frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
return 0;
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
*got_frame = 1;
|
||||
return info->pkt.size;
|
||||
}
|
||||
decoded = info->pkt.size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1106,7 +607,13 @@ extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDr
|
|||
info->seeking = true;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env, jclass clazz, jlong ptr, jlong ms, jboolean precise) {
|
||||
void push_time(JNIEnv *env, VideoInfo* info, jintArray data) {
|
||||
jint *dataArr = env->GetIntArrayElements(data, 0);
|
||||
dataArr[3] = (jint) (1000 * info->frame->best_effort_timestamp * av_q2d(info->video_stream->time_base));
|
||||
env->ReleaseIntArrayElements(data, dataArr, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env, jclass clazz, jlong ptr, jlong ms, jintArray data, jboolean precise) {
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -1120,6 +627,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDr
|
|||
} else {
|
||||
avcodec_flush_buffers(info->video_dec_ctx);
|
||||
if (!precise) {
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
int got_frame = 0;
|
||||
|
@ -1151,14 +659,17 @@ extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDr
|
|||
info->pkt.size = 0;
|
||||
ret = decode_packet(info, &got_frame);
|
||||
if (ret < 0) {
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
if (got_frame == 0) {
|
||||
av_seek_frame(info->fmt_ctx, info->video_stream_idx, 0, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
if (got_frame) {
|
||||
|
@ -1172,12 +683,14 @@ extern "C" JNIEXPORT void JNICALL Java_org_telegram_ui_Components_AnimatedFileDr
|
|||
}
|
||||
av_frame_unref(info->frame);
|
||||
if (finished) {
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tries--;
|
||||
}
|
||||
}
|
||||
push_time(env, info, data);
|
||||
}
|
||||
|
||||
uint32_t premultiply_channel_value(const uint32_t pixel, const uint8_t offset, const float normalizedAlpha) {
|
||||
|
@ -1186,6 +699,10 @@ uint32_t premultiply_channel_value(const uint32_t pixel, const uint8_t offset, c
|
|||
}
|
||||
|
||||
static inline void writeFrameToBitmap(JNIEnv *env, VideoInfo *info, jintArray data, jobject bitmap, jint stride) {
|
||||
if (env->IsSameObject(bitmap, NULL)) {
|
||||
push_time(env, info, data);
|
||||
return;
|
||||
}
|
||||
jint *dataArr = env->GetIntArrayElements(data, 0);
|
||||
int32_t wantedWidth;
|
||||
int32_t wantedHeight;
|
||||
|
|
|
@ -576,6 +576,10 @@ int32_t ConnectionsManager::getCurrentTime() {
|
|||
return (int32_t) (getCurrentTimeMillis() / 1000) + timeDifference;
|
||||
}
|
||||
|
||||
int32_t ConnectionsManager::getCurrentPingTime() {
|
||||
return (int32_t) currentPingTimeLive;
|
||||
}
|
||||
|
||||
uint32_t ConnectionsManager::getCurrentDatacenterId() {
|
||||
Datacenter *datacenter = getDatacenterWithId(DEFAULT_DATACENTER_ID);
|
||||
return datacenter != nullptr ? datacenter->getDatacenterId() : INT_MAX;
|
||||
|
@ -1159,6 +1163,8 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
|||
if (!registeredForInternalPush) {
|
||||
registerForInternalPushUpdates();
|
||||
}
|
||||
int32_t diff = getCurrentTimeMonotonicMillis() - sendingPushPingTime;
|
||||
currentPingTimeLive = (diff + currentPingTimeLive) / 2;
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received push ping", connection, instanceNum, datacenter->getDatacenterId(), connection->getConnectionType());
|
||||
sendingPushPing = false;
|
||||
} else {
|
||||
|
@ -1191,7 +1197,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
|||
}
|
||||
} else if (response->ping_id == lastPingId) {
|
||||
int32_t diff = (int32_t) (getCurrentTimeMonotonicMillis() / 1000) - pingTime;
|
||||
|
||||
currentPingTimeLive = ((getCurrentTimeMonotonicMillis() - pingTimeMs) + currentPingTimeLive) / 2;
|
||||
if (abs(diff) < 10) {
|
||||
currentPingTime = (diff + currentPingTime) / 2;
|
||||
if (messageId != 0) {
|
||||
|
@ -1755,9 +1761,11 @@ void ConnectionsManager::sendPing(Datacenter *datacenter, bool usePushConnection
|
|||
request->ping_id = ++lastPingId;
|
||||
if (usePushConnection) {
|
||||
request->disconnect_delay = 60 * 7;
|
||||
sendingPushPingTime = getCurrentTimeMonotonicMillis();
|
||||
} else {
|
||||
request->disconnect_delay = testBackend ? 10 : 35;
|
||||
pingTime = (int32_t) (getCurrentTimeMonotonicMillis() / 1000);
|
||||
pingTimeMs = getCurrentTimeMonotonicMillis();
|
||||
pingTime = (int32_t) (pingTimeMs / 1000);
|
||||
}
|
||||
|
||||
auto networkMessage = new NetworkMessage();
|
||||
|
@ -2533,12 +2541,12 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
|
|||
)) && !request->awaitingIntegrityCheck) {
|
||||
if (!forceThisRequest && request->connectionToken > 0) {
|
||||
if ((request->connectionType & ConnectionTypeGeneric || request->connectionType & ConnectionTypeTemp) && request->connectionToken == connection->getConnectionToken()) {
|
||||
if (LOGS_ENABLED) DEBUG_D("request token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
||||
// if (LOGS_ENABLED) DEBUG_D("request token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
||||
iter++;
|
||||
continue;
|
||||
} else {
|
||||
if (connection->getConnectionToken() != 0 && request->connectionToken == connection->getConnectionToken()) {
|
||||
if (LOGS_ENABLED) DEBUG_D("request download token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
||||
// if (LOGS_ENABLED) DEBUG_D("request download token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
||||
iter++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
int64_t getCurrentTimeMillis();
|
||||
int64_t getCurrentTimeMonotonicMillis();
|
||||
int32_t getCurrentTime();
|
||||
int32_t getCurrentPingTime();
|
||||
uint32_t getCurrentDatacenterId();
|
||||
bool isTestBackend();
|
||||
int32_t getTimeDifference();
|
||||
|
@ -142,6 +143,7 @@ private:
|
|||
std::map<uint32_t, Datacenter *> datacenters;
|
||||
std::map<int32_t, std::vector<std::int32_t>> quickAckIdToRequestIds;
|
||||
int32_t pingTime;
|
||||
int64_t pingTimeMs;
|
||||
bool testBackend = false;
|
||||
bool clientBlocked = true;
|
||||
std::string lastInitSystemLangcode = "";
|
||||
|
@ -150,9 +152,11 @@ private:
|
|||
uint32_t movingToDatacenterId = DEFAULT_DATACENTER_ID;
|
||||
int64_t pushSessionId = 0;
|
||||
int32_t currentPingTime = 0;
|
||||
int32_t currentPingTimeLive = 0;
|
||||
bool registeringForPush = false;
|
||||
int64_t lastPushPingTime = 0;
|
||||
int32_t nextPingTimeOffset = 60000 * 3;
|
||||
int64_t sendingPushPingTime = 0;
|
||||
bool sendingPushPing = false;
|
||||
bool sendingPing = false;
|
||||
bool updatingDcSettings = false;
|
||||
|
|
3
TMessagesProj/proguard-rules.pro
vendored
3
TMessagesProj/proguard-rules.pro
vendored
|
@ -24,6 +24,9 @@
|
|||
-keep class com.google.android.exoplayer2.metadata.flac.PictureFrame { *; }
|
||||
-keep class com.google.android.exoplayer2.decoder.SimpleDecoderOutputBuffer { *; }
|
||||
-keep class org.telegram.ui.Stories.recorder.FfmpegAudioWaveformLoader { *; }
|
||||
-keepclassmembers class ** {
|
||||
@android.webkit.JavascriptInterface <methods>;
|
||||
}
|
||||
|
||||
# https://developers.google.com/ml-kit/known-issues#android_issues
|
||||
-keep class com.google.mlkit.nl.languageid.internal.LanguageIdentificationJni { *; }
|
||||
|
|
|
@ -590,6 +590,8 @@ e <intent-filter>
|
|||
|
||||
<receiver android:name=".voip.VoIPActionsReceiver" android:exported="false"/>
|
||||
|
||||
<receiver android:name=".ShortcutResultReceiver" android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
|
|
@ -184,3 +184,4 @@ chat_outSentClock=-594761027
|
|||
chat_searchPanelText=-12609056
|
||||
table_background=-526345
|
||||
table_border=-2039584
|
||||
dialogTopBackground=-13473128
|
||||
|
|
|
@ -21,6 +21,8 @@ profile_actionPressedBackground=-11756844
|
|||
key_chat_messagePanelVoiceLock=-1
|
||||
chat_secretChatStatusText=-8812137
|
||||
switchTrack=-10652540
|
||||
gift_ribbon=-12492673
|
||||
gift_ribbon_soldout=-8500415
|
||||
chat_attachAudioBackground=-626837
|
||||
location_sendLocationBackground=-9919529
|
||||
actionBarDefaultSubmenuBackground=-14075831
|
||||
|
@ -124,6 +126,9 @@ chat_inReplyLine=-8796932
|
|||
chat_inQuote=-8796932
|
||||
chat_inAudioPerfomerSelectedText=-7490861
|
||||
dialogBackground=-14602949
|
||||
bot_loadingIcon=520093695
|
||||
gift_ribbon=-12492673
|
||||
gift_ribbon_soldout=-8500415
|
||||
dialogLineProgressBackground=-13548718
|
||||
chat_inReplyNameText=-8796932
|
||||
chat_outAudioPerfomerSelectedText=-4268038
|
||||
|
@ -447,3 +452,4 @@ iv_navigationBackground=-16777216
|
|||
table_background=177390847
|
||||
table_border=436207615
|
||||
dialogCardShadow=1073741824
|
||||
dialogTopBackground=-13473128
|
||||
|
|
Binary file not shown.
|
@ -127,6 +127,9 @@ chat_inReplyLine=-8796932
|
|||
chat_inQuote=-8796932
|
||||
chat_inAudioPerfomerSelectedText=-7490861
|
||||
dialogBackground=-14803426
|
||||
bot_loadingIcon=520093695
|
||||
gift_ribbon=-12492673
|
||||
gift_ribbon_soldout=-8500415
|
||||
dialogLineProgressBackground=-12303292
|
||||
chat_inReplyNameText=-8796932
|
||||
chat_outAudioPerfomerSelectedText=-7023626
|
||||
|
@ -472,3 +475,4 @@ iv_navigationBackground=-16777216
|
|||
table_background=177390847
|
||||
table_border=436207615
|
||||
dialogCardShadow=1073741824
|
||||
dialogTopBackground=-13473128
|
||||
|
|
|
@ -127,7 +127,7 @@ public final class Format implements Bundleable {
|
|||
* of format being constructed. See the {@link Format} Javadoc for information about which fields
|
||||
* should be set for different types of format.
|
||||
*/
|
||||
public static final class Builder {
|
||||
public static class Builder {
|
||||
|
||||
@Nullable private String id;
|
||||
@Nullable private String label;
|
||||
|
@ -138,6 +138,10 @@ public final class Format implements Bundleable {
|
|||
private int peakBitrate;
|
||||
@Nullable private String codecs;
|
||||
@Nullable private Metadata metadata;
|
||||
public boolean cached;
|
||||
public long documentId;
|
||||
public String documentFilename;
|
||||
public int currentAccount;
|
||||
|
||||
// Container specific.
|
||||
|
||||
|
@ -207,6 +211,7 @@ public final class Format implements Bundleable {
|
|||
tileCountVertical = NO_VALUE;
|
||||
// Provided by the source.
|
||||
cryptoType = C.CRYPTO_TYPE_NONE;
|
||||
cached = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,6 +259,10 @@ public final class Format implements Bundleable {
|
|||
this.tileCountVertical = format.tileCountVertical;
|
||||
// Provided by the source.
|
||||
this.cryptoType = format.cryptoType;
|
||||
this.cached = format.cached;
|
||||
this.documentId = format.documentId;
|
||||
this.currentAccount = format.currentAccount;
|
||||
this.documentFilename = format.documentFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,6 +290,46 @@ public final class Format implements Bundleable {
|
|||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setCached(boolean cached) {
|
||||
this.cached = cached;
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setDocumentId(String documentId) {
|
||||
try {
|
||||
this.documentId = Long.parseLong(documentId);
|
||||
} catch (Exception e) {}
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setDocumentId(long documentId) {
|
||||
this.documentId = documentId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setCurrentAccount(int currentAccount) {
|
||||
this.currentAccount = currentAccount;
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setCurrentAccount(String currentAccount) {
|
||||
try {
|
||||
this.currentAccount = Integer.parseInt(currentAccount);
|
||||
} catch (Exception e) {}
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setDocumentFilename(String filename) {
|
||||
this.documentFilename = filename;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link Format#label}. The default value is {@code null}.
|
||||
*
|
||||
|
@ -747,6 +796,11 @@ public final class Format implements Bundleable {
|
|||
/** Metadata, or null if unknown or not applicable. */
|
||||
@Nullable public final Metadata metadata;
|
||||
|
||||
public boolean cached;
|
||||
public long documentId;
|
||||
public int currentAccount;
|
||||
public String documentFilename;
|
||||
|
||||
// Container specific.
|
||||
|
||||
/** The mime type of the container, or null if unknown or not applicable. */
|
||||
|
@ -1030,6 +1084,10 @@ public final class Format implements Bundleable {
|
|||
bitrate = peakBitrate != NO_VALUE ? peakBitrate : averageBitrate;
|
||||
codecs = builder.codecs;
|
||||
metadata = builder.metadata;
|
||||
cached = builder.cached;
|
||||
documentId = builder.documentId;
|
||||
currentAccount = builder.currentAccount;
|
||||
documentFilename = builder.documentFilename;
|
||||
// Container specific.
|
||||
containerMimeType = builder.containerMimeType;
|
||||
// Sample specific.
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
/** An HLS {@link MediaChunk}. */
|
||||
/* package */ final class HlsMediaChunk extends MediaChunk {
|
||||
|
@ -482,6 +483,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
} finally {
|
||||
nextLoadPosition = (int) (input.getPosition() - dataSpec.position);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
DataSourceUtil.closeQuietly(dataSource);
|
||||
}
|
||||
|
|
|
@ -1557,6 +1557,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
sampleMimeType = sampleFormat.sampleMimeType;
|
||||
}
|
||||
|
||||
sampleFormat.cached = playlistFormat.cached;
|
||||
sampleFormat.documentId = playlistFormat.documentId;
|
||||
sampleFormat.currentAccount = playlistFormat.currentAccount;
|
||||
sampleFormat.documentFilename = playlistFormat.documentFilename;
|
||||
|
||||
Format.Builder formatBuilder =
|
||||
sampleFormat
|
||||
.buildUpon()
|
||||
|
@ -1567,7 +1572,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
.setRoleFlags(playlistFormat.roleFlags)
|
||||
.setAverageBitrate(propagateBitrates ? playlistFormat.averageBitrate : Format.NO_VALUE)
|
||||
.setPeakBitrate(propagateBitrates ? playlistFormat.peakBitrate : Format.NO_VALUE)
|
||||
.setCodecs(codecs);
|
||||
.setCodecs(codecs)
|
||||
.setCurrentAccount(playlistFormat.currentAccount)
|
||||
.setDocumentId(playlistFormat.documentId)
|
||||
.setCached(playlistFormat.cached)
|
||||
.setDocumentFilename(playlistFormat.documentFilename);
|
||||
|
||||
if (sampleTrackType == C.TRACK_TYPE_VIDEO) {
|
||||
formatBuilder
|
||||
|
|
|
@ -137,6 +137,11 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||
private static final Pattern REGEX_BANDWIDTH = Pattern.compile("[^-]BANDWIDTH=(\\d+)\\b");
|
||||
private static final Pattern REGEX_CHANNELS = Pattern.compile("CHANNELS=\"(.+?)\"");
|
||||
private static final Pattern REGEX_CODECS = Pattern.compile("CODECS=\"(.+?)\"");
|
||||
private static final Pattern REGEX_MIME = Pattern.compile("MIME=\"(.+?)\"");
|
||||
private static final Pattern REGEX_CACHED = Pattern.compile("CACHED=\"(.+?)\"");
|
||||
private static final Pattern REGEX_DOC_ID = Pattern.compile("DOCID=\"(.+?)\"");
|
||||
private static final Pattern REGEX_DOC_FILENAME = Pattern.compile("DOCFILENAME=\"(.+?)\"");
|
||||
private static final Pattern REGEX_ACCOUNT = Pattern.compile("ACCOUNT=\"(.+?)\"");
|
||||
private static final Pattern REGEX_RESOLUTION = Pattern.compile("RESOLUTION=(\\d+x\\d+)");
|
||||
private static final Pattern REGEX_FRAME_RATE = Pattern.compile("FRAME-RATE=([\\d\\.]+)\\b");
|
||||
private static final Pattern REGEX_TARGET_DURATION =
|
||||
|
@ -373,6 +378,11 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||
int peakBitrate = parseIntAttr(line, REGEX_BANDWIDTH);
|
||||
int averageBitrate = parseOptionalIntAttr(line, REGEX_AVERAGE_BANDWIDTH, -1);
|
||||
String codecs = parseOptionalStringAttr(line, REGEX_CODECS, variableDefinitions);
|
||||
String mime = parseOptionalStringAttr(line, REGEX_MIME, variableDefinitions);
|
||||
boolean cached = TextUtils.equals(parseOptionalStringAttr(line, REGEX_CACHED, variableDefinitions), "true");
|
||||
String documentId = parseOptionalStringAttr(line, REGEX_DOC_ID, variableDefinitions);
|
||||
String documentFilename = parseOptionalStringAttr(line, REGEX_DOC_FILENAME, variableDefinitions);
|
||||
String currentAccount = parseOptionalStringAttr(line, REGEX_ACCOUNT, variableDefinitions);
|
||||
String resolutionString =
|
||||
parseOptionalStringAttr(line, REGEX_RESOLUTION, variableDefinitions);
|
||||
int width;
|
||||
|
@ -420,12 +430,17 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||
.setId(variants.size())
|
||||
.setContainerMimeType(MimeTypes.APPLICATION_M3U8)
|
||||
.setCodecs(codecs)
|
||||
.setSampleMimeType(mime)
|
||||
.setAverageBitrate(averageBitrate)
|
||||
.setPeakBitrate(peakBitrate)
|
||||
.setWidth(width)
|
||||
.setHeight(height)
|
||||
.setFrameRate(frameRate)
|
||||
.setRoleFlags(roleFlags)
|
||||
.setCached(cached)
|
||||
.setDocumentId(documentId)
|
||||
.setDocumentFilename(documentFilename)
|
||||
.setCurrentAccount(currentAccount)
|
||||
.build();
|
||||
Variant variant =
|
||||
new Variant(
|
||||
|
|
|
@ -37,8 +37,11 @@ import com.google.common.collect.Multimap;
|
|||
import com.google.common.collect.MultimapBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
/**
|
||||
* A bandwidth based adaptive {@link ExoTrackSelection}, whose selected track is updated to be the
|
||||
|
@ -442,7 +445,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
// Make initial selection
|
||||
if (reason == C.SELECTION_REASON_UNKNOWN) {
|
||||
reason = C.SELECTION_REASON_INITIAL;
|
||||
selectedIndex = determineIdealSelectedIndex(nowMs, chunkDurationUs);
|
||||
selectedIndex = determineIdealSelectedIndex(0, nowMs, chunkDurationUs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -454,7 +457,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
previousSelectedIndex = formatIndexOfPreviousChunk;
|
||||
previousReason = Iterables.getLast(queue).trackSelectionReason;
|
||||
}
|
||||
int newSelectedIndex = determineIdealSelectedIndex(nowMs, chunkDurationUs);
|
||||
int newSelectedIndex = determineIdealSelectedIndex(1, nowMs, chunkDurationUs);
|
||||
if (!isBlacklisted(previousSelectedIndex, nowMs)) {
|
||||
// Revert back to the previous selection if conditions are not suitable for switching.
|
||||
Format currentFormat = getFormat(previousSelectedIndex);
|
||||
|
@ -469,7 +472,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
} else if (selectedFormat.bitrate < currentFormat.bitrate
|
||||
&& bufferedDurationUs >= maxDurationForQualityDecreaseUs) {
|
||||
// The selected track is a lower quality, but we have sufficient buffer to defer switching
|
||||
// down for now.
|
||||
// down for now. maxDurationForQualityDecreaseUs+ ")");
|
||||
newSelectedIndex = previousSelectedIndex;
|
||||
}
|
||||
}
|
||||
|
@ -516,7 +519,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
if (playoutBufferedDurationBeforeLastChunkUs < minDurationToRetainAfterDiscardUs) {
|
||||
return queueSize;
|
||||
}
|
||||
int idealSelectedIndex = determineIdealSelectedIndex(nowMs, getLastChunkDurationUs(queue));
|
||||
int idealSelectedIndex = determineIdealSelectedIndex(-1, nowMs, getLastChunkDurationUs(queue));
|
||||
Format idealFormat = getFormat(idealSelectedIndex);
|
||||
// If chunks contain video, discard from the first chunk after minDurationToRetainAfterDiscardUs
|
||||
// whose resolution and bitrate are both lower than the ideal track, and whose width and height
|
||||
|
@ -551,7 +554,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected boolean canSelectFormat(Format format, int trackBitrate, long effectiveBitrate) {
|
||||
return trackBitrate <= effectiveBitrate;
|
||||
return format.cached || trackBitrate <= effectiveBitrate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -586,19 +589,62 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
* @param chunkDurationUs The duration of a media chunk in microseconds, or {@link C#TIME_UNSET}
|
||||
* if unknown.
|
||||
*/
|
||||
private int determineIdealSelectedIndex(long nowMs, long chunkDurationUs) {
|
||||
long effectiveBitrate = getAllocatedBandwidth(chunkDurationUs);
|
||||
int lowestBitrateAllowedIndex = 0;
|
||||
private int determineIdealSelectedIndex(int type, long nowMs, long chunkDurationUs) {
|
||||
final long effectiveBitrate = getAllocatedBandwidth(chunkDurationUs);
|
||||
FileLog.d("debug_loading_player: determineIdealSelectedIndex: type="+type+" effectiveBitrate=" + effectiveBitrate);
|
||||
final HashMap<Integer, Integer> formatsByResolution = new HashMap<>();
|
||||
final ArrayList<Integer> formatIndices = new ArrayList<>();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (nowMs == Long.MIN_VALUE || !isBlacklisted(i, nowMs)) {
|
||||
Format format = getFormat(i);
|
||||
if (canSelectFormat(format, format.bitrate, effectiveBitrate)) {
|
||||
return i;
|
||||
} else {
|
||||
lowestBitrateAllowedIndex = i;
|
||||
if (nowMs != Long.MIN_VALUE && isBlacklisted(i, nowMs)) continue;
|
||||
final Format format = getFormat(i);
|
||||
final int resolution = Math.max(format.width, format.height);
|
||||
if (!formatsByResolution.containsKey(resolution)) {
|
||||
formatsByResolution.put(resolution, i);
|
||||
formatIndices.add(i);
|
||||
} else {
|
||||
final int existingFormatIndex = formatsByResolution.get(resolution);
|
||||
final Format existingFormat = getFormat(existingFormatIndex);
|
||||
if (existingFormat.cached && !format.cached) continue;
|
||||
if (
|
||||
!existingFormat.cached && format.cached ||
|
||||
format.bitrate < existingFormat.bitrate
|
||||
) {
|
||||
formatsByResolution.put(resolution, i);
|
||||
formatIndices.remove((Integer) existingFormatIndex);
|
||||
formatIndices.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == 0) {
|
||||
for (int i : formatIndices) {
|
||||
Format format = getFormat(i);
|
||||
if (format.cached) {
|
||||
FileLog.d("debug_loading_player: determineIdealSelectedIndex: initial setup, choose cached format#" + i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
int lowestBitrateAllowedIndex = 0;
|
||||
for (int i : formatIndices) {
|
||||
Format format = getFormat(i);
|
||||
FileLog.d("debug_loading_player: determineIdealSelectedIndex: format#" + i + " bitrate=" + format.bitrate + " " + format.width + "x" + format.height + " codecs="+format.codecs+" (cached=" + format.cached + ")");
|
||||
if (canSelectFormat(format, format.bitrate, effectiveBitrate)) {
|
||||
// if (!format.cached && type == 0) {
|
||||
// for (int j = i + 1; j < formatIndices.size(); ++j) {
|
||||
// int i2 = formatIndices.get(j);
|
||||
// if (getFormat(i2).cached) {
|
||||
// FileLog.d("debug_loading_player: determineIdealSelectedIndex: chose to start with lower but cached format#" + i);
|
||||
// return i2;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
FileLog.d("debug_loading_player: determineIdealSelectedIndex: selected format#" + i);
|
||||
return i;
|
||||
} else {
|
||||
lowestBitrateAllowedIndex = i;
|
||||
}
|
||||
}
|
||||
FileLog.d("debug_loading_player: determineIdealSelectedIndex: selected format#" + lowestBitrateAllowedIndex + " (lowest, nothing is fit)");
|
||||
return lowestBitrateAllowedIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public abstract class BaseDataSource implements DataSource {
|
||||
|
||||
private final boolean isNetwork;
|
||||
protected boolean isNetwork;
|
||||
private final ArrayList<TransferListener> listeners;
|
||||
|
||||
private int listenerCount;
|
||||
|
|
|
@ -17,6 +17,8 @@ package com.google.android.exoplayer2.upstream;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener.EventDispatcher;
|
||||
|
@ -28,6 +30,10 @@ import com.google.common.base.Ascii;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -405,6 +411,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
if (totalElapsedTimeMs >= ELAPSED_MILLIS_FOR_ESTIMATE
|
||||
|| totalBytesTransferred >= BYTES_TRANSFERRED_FOR_ESTIMATE) {
|
||||
bitrateEstimate = (long) slidingPercentile.getPercentile(0.5f);
|
||||
FileLog.d("debug_loading: bandwidth meter (onTransferEnd), bitrate estimate = " + bitrateEstimate);
|
||||
}
|
||||
maybeNotifyBandwidthSample(sampleElapsedTimeMs, sampleBytesTransferred, bitrateEstimate);
|
||||
sampleStartTimeMs = nowMs;
|
||||
|
@ -413,6 +420,26 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
streamCount--;
|
||||
}
|
||||
|
||||
public void onTransfer(long bytes, long duration) {
|
||||
long nowMs = clock.elapsedRealtime();
|
||||
int sampleElapsedTimeMs = (int) (nowMs - sampleStartTimeMs);
|
||||
totalElapsedTimeMs += sampleElapsedTimeMs;
|
||||
totalBytesTransferred += bytes;
|
||||
if (duration > 0 && bytes > 0) {
|
||||
FileLog.d("debug_loading: bandwidth meter on transfer " + AndroidUtilities.formatFileSize(bytes) + " per " +duration + "ms");
|
||||
float bitsPerSecond = (bytes * 8000f) / duration;
|
||||
slidingPercentile.addSample((int) Math.sqrt(bytes), bitsPerSecond);
|
||||
if (totalElapsedTimeMs >= ELAPSED_MILLIS_FOR_ESTIMATE
|
||||
|| totalBytesTransferred >= BYTES_TRANSFERRED_FOR_ESTIMATE) {
|
||||
bitrateEstimate = (long) slidingPercentile.getPercentile(0.5f);
|
||||
FileLog.d("debug_loading: bandwidth meter (onTransfer), bitrate estimate = " + bitrateEstimate);
|
||||
}
|
||||
maybeNotifyBandwidthSample((int) duration, bytes, bitrateEstimate);
|
||||
sampleStartTimeMs = nowMs;
|
||||
sampleBytesTransferred = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void onNetworkTypeChanged(@C.NetworkType int networkType) {
|
||||
if (this.networkType != C.NETWORK_TYPE_UNKNOWN && !resetOnNetworkTypeChange) {
|
||||
// Reset on network change disabled. Ignore all updates except the initial one.
|
||||
|
@ -469,7 +496,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
}
|
||||
|
||||
private static boolean isTransferAtFullNetworkSpeed(DataSpec dataSpec, boolean isNetwork) {
|
||||
return isNetwork && !dataSpec.isFlagSet(DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED);
|
||||
return isNetwork && (dataSpec == null || !dataSpec.isFlagSet(DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -666,21 +666,31 @@ public class AndroidUtilities {
|
|||
}
|
||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str);
|
||||
if (index >= 0) {
|
||||
spannableStringBuilder.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
ds.setColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
if (onClick != null) {
|
||||
spannableStringBuilder.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
ds.setColor(color);
|
||||
}
|
||||
}
|
||||
}, index, index + len, 0);
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
if (onClick != null) {
|
||||
onClick.run();
|
||||
}
|
||||
}
|
||||
}, index, index + len, 0);
|
||||
} else {
|
||||
spannableStringBuilder.setSpan(new CharacterStyle() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
ds.setUnderlineText(false);
|
||||
ds.setColor(color);
|
||||
}
|
||||
}, index, index + len, 0);
|
||||
}
|
||||
}
|
||||
return spannableStringBuilder;
|
||||
}
|
||||
|
@ -3202,8 +3212,36 @@ public class AndroidUtilities {
|
|||
return new SpannableStringBuilder(str);
|
||||
}
|
||||
|
||||
public static SpannableStringBuilder replaceTags(SpannableStringBuilder stringBuilder) {
|
||||
try {
|
||||
int start;
|
||||
int end;
|
||||
ArrayList<Integer> bolds = new ArrayList<>();
|
||||
while ((start = AndroidUtilities.charSequenceIndexOf(stringBuilder, "**")) != -1) {
|
||||
stringBuilder.replace(start, start + 2, "");
|
||||
end = AndroidUtilities.charSequenceIndexOf(stringBuilder, "**");
|
||||
if (end >= 0) {
|
||||
stringBuilder.replace(end, end + 2, "");
|
||||
bolds.add(start);
|
||||
bolds.add(end);
|
||||
}
|
||||
}
|
||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
|
||||
for (int a = 0; a < bolds.size() / 2; a++) {
|
||||
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
return spannableStringBuilder;
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
private static Pattern linksPattern;
|
||||
public static SpannableStringBuilder replaceLinks(String str, Theme.ResourcesProvider resourcesProvider) {
|
||||
return replaceLinks(str, resourcesProvider, null);
|
||||
}
|
||||
public static SpannableStringBuilder replaceLinks(String str, Theme.ResourcesProvider resourcesProvider, Runnable onLinkClick) {
|
||||
if (linksPattern == null) {
|
||||
linksPattern = Pattern.compile("\\[(.+?)\\]\\((.+?)\\)");
|
||||
}
|
||||
|
@ -3220,6 +3258,9 @@ public class AndroidUtilities {
|
|||
spannable.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
if (onLinkClick != null) {
|
||||
onLinkClick.run();
|
||||
}
|
||||
Browser.openUrl(ApplicationLoader.applicationContext, url);
|
||||
}
|
||||
@Override
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.telegram.ui.ActionBar.BaseFragment;
|
|||
import org.telegram.ui.Adapters.DrawerLayoutAdapter;
|
||||
import org.telegram.ui.Components.ForegroundDetector;
|
||||
import org.telegram.ui.Components.Premium.boosts.BoostRepository;
|
||||
import org.telegram.ui.IUpdateButton;
|
||||
import org.telegram.ui.IUpdateLayout;
|
||||
import org.telegram.ui.LauncherIconController;
|
||||
|
||||
|
@ -288,6 +289,7 @@ public class ApplicationLoader extends Application {
|
|||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
FileLog.d("device = manufacturer=" + Build.MANUFACTURER + ", device=" + Build.DEVICE + ", model=" + Build.MODEL + ", product=" + Build.PRODUCT);
|
||||
}
|
||||
if (applicationContext == null) {
|
||||
applicationContext = getApplicationContext();
|
||||
|
@ -616,6 +618,10 @@ public class ApplicationLoader extends Application {
|
|||
return null;
|
||||
}
|
||||
|
||||
public IUpdateButton takeUpdateButton(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TLRPC.Update parseTLUpdate(int constructor) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -130,9 +130,13 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
|||
if (isReady()) {
|
||||
return;
|
||||
}
|
||||
BillingUtilities.extractCurrencyExp(currencyExpMap);
|
||||
if (!BuildVars.useInvoiceBilling()) {
|
||||
billingClient.startConnection(this);
|
||||
try {
|
||||
BillingUtilities.extractCurrencyExp(currencyExpMap);
|
||||
if (!BuildVars.useInvoiceBilling()) {
|
||||
billingClient.startConnection(this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -285,6 +285,15 @@ public class BirthdayController {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isToday(long userId) {
|
||||
if (state != null && state.contains(userId))
|
||||
return true;
|
||||
final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(userId);
|
||||
if (userFull != null && isToday(userFull.birthday))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isToday(TLRPC.UserFull userFull) {
|
||||
if (userFull == null) return false;
|
||||
return isToday(userFull.birthday);
|
||||
|
|
|
@ -0,0 +1,473 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import static org.telegram.messenger.AndroidUtilities.dp;
|
||||
import static org.telegram.messenger.AndroidUtilities.dpf2;
|
||||
import static org.telegram.messenger.AndroidUtilities.lerp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.CornerPathEffect;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.RenderEffect;
|
||||
import android.graphics.RenderNode;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedFloat;
|
||||
import org.telegram.ui.Components.ButtonBounce;
|
||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||
import org.telegram.ui.Components.Text;
|
||||
import org.telegram.ui.GradientClip;
|
||||
|
||||
public class BotFullscreenButtons extends View {
|
||||
|
||||
private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint iconPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint iconStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Path backgroundPath = new Path();
|
||||
private final Paint downloadPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Path downloadPath = new Path();
|
||||
|
||||
private final RectF insets = new RectF();
|
||||
|
||||
private final RectF leftMenu = new RectF();
|
||||
private final ButtonBounce nullBounce = new ButtonBounce(null);
|
||||
private final RectF closeRect = new RectF();
|
||||
private final RectF closeRectArea = new RectF();
|
||||
private final ButtonBounce closeBounce = new ButtonBounce(this);
|
||||
private final RectF rightMenu = new RectF();
|
||||
private final RectF collapseRect = new RectF();
|
||||
private final RectF collapseClickRect = new RectF();
|
||||
private final ButtonBounce collapseBounce = new ButtonBounce(this);
|
||||
private final RectF menuRect = new RectF();
|
||||
private final RectF menuClickRect = new RectF();
|
||||
private final ButtonBounce menuBounce = new ButtonBounce(this);
|
||||
|
||||
private final long start;
|
||||
private boolean back;
|
||||
private final AnimatedFloat animatedBack = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||
private boolean preview = true;
|
||||
private final AnimatedFloat animatedPreview = new AnimatedFloat(this, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||
private boolean downloading = false;
|
||||
private final AnimatedFloat animatedDownloading = new AnimatedFloat(this, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||
|
||||
private final Text backText, closeText;
|
||||
private final GradientClip previewClip = new GradientClip();
|
||||
private Text previewText;
|
||||
private Drawable verifiedBackground;
|
||||
private Drawable verifiedForeground;
|
||||
|
||||
public BotFullscreenButtons(Context context) {
|
||||
super(context);
|
||||
this.start = System.currentTimeMillis();
|
||||
iconStrokePaint.setStyle(Paint.Style.STROKE);
|
||||
iconStrokePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
iconStrokePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
backText = new Text(LocaleController.getString(R.string.BotFullscreenBack), 13, AndroidUtilities.bold());
|
||||
closeText = new Text(LocaleController.getString(R.string.BotFullscreenClose), 13, AndroidUtilities.bold());
|
||||
|
||||
downloadPaint.setPathEffect(new CornerPathEffect(dp(1)));
|
||||
downloadPath.rewind();
|
||||
downloadPath.moveTo(-dpf2(1.33f), dpf2(0.16f));
|
||||
downloadPath.lineTo(-dpf2(1.33f), -dpf2(3.5f));
|
||||
downloadPath.lineTo(dpf2(1.33f), -dpf2(3.5f));
|
||||
downloadPath.lineTo(dpf2(1.33f), dpf2(0.16f));
|
||||
downloadPath.lineTo(dpf2(3.5f), dpf2(0.16f));
|
||||
downloadPath.lineTo(0, dpf2(3.5f));
|
||||
downloadPath.lineTo(-dpf2(3.5f), dpf2(0.16f));
|
||||
downloadPath.close();
|
||||
}
|
||||
|
||||
public void setInsets(RectF rect) {
|
||||
insets.set(rect);
|
||||
}
|
||||
|
||||
public void setInsets(Rect rect) {
|
||||
insets.set(rect);
|
||||
}
|
||||
|
||||
private RenderNode blurNode;
|
||||
|
||||
@Override
|
||||
protected void onDraw(@NonNull Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
iconPaint.setColor(0xFFFFFFFF);
|
||||
iconStrokePaint.setColor(0xFFFFFFFF);
|
||||
iconStrokePaint.setStrokeWidth(dp(2));
|
||||
|
||||
backgroundPath.rewind();
|
||||
|
||||
rightMenu.set(getWidth() - insets.right - dp(8 + 71.66f), insets.top + dp(8), getWidth() - insets.right - dp(8), insets.top + dp(8 + 30));
|
||||
collapseRect.set(rightMenu.left, rightMenu.top, rightMenu.centerX(), rightMenu.bottom);
|
||||
collapseClickRect.set(collapseRect.left - dp(8), collapseRect.top - dp(8), collapseRect.right, collapseRect.bottom + dp(8));
|
||||
menuRect.set(rightMenu.centerX(), rightMenu.top, rightMenu.right, rightMenu.bottom);
|
||||
menuClickRect.set(menuRect.left, menuRect.top - dp(8), menuRect.right + dp(8), menuRect.bottom + dp(8));
|
||||
backgroundPath.addRoundRect(rightMenu, dp(15), dp(15), Path.Direction.CW);
|
||||
|
||||
final float back = this.animatedBack.set(this.back);
|
||||
final float preview = this.animatedPreview.set(this.preview);
|
||||
final float previewWidth = Math.min(rightMenu.left - dp(18) - (insets.left + dp(8 + 30)), previewText == null ? 0 : previewText.getCurrentWidth() + dp(verifiedBackground != null ? 30 : 12));
|
||||
final float leftTextWidth = lerp(lerp(closeText.getCurrentWidth(), backText.getCurrentWidth(), back) + dp(12), previewWidth, preview);
|
||||
leftMenu.set(insets.left + dp(8), insets.top + dp(8), insets.left + dp(8 + 30) + leftTextWidth, insets.top + dp(8 + 30));
|
||||
closeRect.set(leftMenu.left, leftMenu.top, leftMenu.left + dp(30), leftMenu.bottom);
|
||||
closeRectArea.set(closeRect);
|
||||
closeRectArea.right = lerp(leftMenu.right, closeRect.left + dp(30), preview);
|
||||
closeRectArea.inset(-dp(8), -dp(8));
|
||||
backgroundPath.addRoundRect(leftMenu, dp(15), dp(15), Path.Direction.CW);
|
||||
|
||||
if (parentRenderNode != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && canvas.isHardwareAccelerated() && (webView == null || webView.getLayerType() == LAYER_TYPE_HARDWARE)) {
|
||||
if (blurNode == null) {
|
||||
blurNode = new RenderNode("bot_fullscreen_blur");
|
||||
blurNode.setRenderEffect(RenderEffect.createBlurEffect(dp(18), dp(18), Shader.TileMode.CLAMP));
|
||||
}
|
||||
RenderNode parentNode = (RenderNode) parentRenderNode;
|
||||
final int w = Math.max(1, parentNode.getWidth() - dp(16));
|
||||
final int h = Math.max(1, (int) Math.min(insets.top + dp(8 + 8 + 30), parentNode.getHeight()));
|
||||
|
||||
blurNode.setPosition(0, 0, w, h);
|
||||
final Canvas blurCanvas = blurNode.beginRecording();
|
||||
blurCanvas.translate(-dp(8), 0);
|
||||
blurCanvas.drawRenderNode(parentNode);
|
||||
blurNode.endRecording();
|
||||
canvas.save();
|
||||
canvas.clipPath(backgroundPath);
|
||||
canvas.save();
|
||||
canvas.translate(dp(8), 0);
|
||||
canvas.drawRenderNode(blurNode);
|
||||
canvas.restore();
|
||||
backgroundPaint.setColor(Theme.multAlpha(0xFF000000, .22f));
|
||||
canvas.drawPaint(backgroundPaint);
|
||||
canvas.restore();
|
||||
} else {
|
||||
backgroundPaint.setColor(Theme.multAlpha(0xFF000000, .35f));
|
||||
canvas.drawPath(backgroundPath, backgroundPaint);
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(closeRect.centerX(), closeRect.centerY());
|
||||
float s = closeBounce.getScale(0.1f);
|
||||
canvas.scale(s, s);
|
||||
canvas.translate(back * -dp(6.5f), 0);
|
||||
final float backR = lerp((float) dp(4.66f), (float) dp(5.5f), back);
|
||||
canvas.drawLine(lerp(-backR, 0, back), lerp(-backR, 0, back), +backR, +backR, iconStrokePaint);
|
||||
canvas.drawLine(lerp(-backR, 0, back), lerp(+backR, 0, back), +backR, -backR, iconStrokePaint);
|
||||
if (back > 0) {
|
||||
canvas.drawLine(0, 0, dp(11.6f) * back, 0, iconStrokePaint);
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
canvas.saveLayerAlpha(leftMenu.left + dp(30) - dp(10), leftMenu.top, leftMenu.right, leftMenu.bottom, 0xFF, Canvas.ALL_SAVE_FLAG);
|
||||
if (preview > 0 && previewText != null) {
|
||||
canvas.save();
|
||||
canvas.translate(leftMenu.left + dp(30) - previewWidth * (1.0f - preview), leftMenu.centerY());
|
||||
previewText.ellipsize(leftMenu.right - dp(verifiedBackground != null ? 30 : 12) - (leftMenu.left + dp(30)) + 2).draw(canvas, 0, 0, 0xFFFFFFFF, preview);
|
||||
canvas.translate(previewText.getWidth() + dp(5), 0);
|
||||
final int verifiedIconSize = dp(16);
|
||||
if (verifiedBackground != null) {
|
||||
verifiedBackground.setBounds(0, -verifiedIconSize / 2, verifiedIconSize, verifiedIconSize / 2);
|
||||
verifiedBackground.setAlpha((int) (0x4B * preview));
|
||||
verifiedBackground.draw(canvas);
|
||||
}
|
||||
if (verifiedForeground != null) {
|
||||
verifiedForeground.setBounds(0, -verifiedIconSize / 2, verifiedIconSize, verifiedIconSize / 2);
|
||||
verifiedForeground.setAlpha((int) (0xFF * preview));
|
||||
verifiedForeground.draw(canvas);
|
||||
}
|
||||
AndroidUtilities.rectTmp.set(leftMenu.left + dp(30) - dp(10), leftMenu.top, leftMenu.left + dp(30), leftMenu.bottom);
|
||||
previewClip.draw(canvas, AndroidUtilities.rectTmp, GradientClip.RIGHT, 1.0f);
|
||||
canvas.restore();
|
||||
}
|
||||
if (preview < 1) {
|
||||
canvas.save();
|
||||
s = closeBounce.getScale(0.1f);
|
||||
canvas.scale(s, s, closeRect.centerX(), closeRect.centerY());
|
||||
if ((1.0f - back) > 0) {
|
||||
closeText.draw(canvas, closeRect.left + dp(30) - dp(12) * back + dp(32) * preview, closeRect.centerY(), 0xFFFFFFFF, (1.0f - back) * (1.0f - preview));
|
||||
}
|
||||
if (back > 0) {
|
||||
backText.draw(canvas, closeRect.left + dp(30) + dp(12) * (1.0f - back) + dp(32) * preview, closeRect.centerY(), 0xFFFFFFFF, back * (1.0f - preview));
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(collapseRect.centerX() + dp(2), collapseRect.centerY());
|
||||
s = collapseBounce.getScale(0.1f);
|
||||
canvas.scale(s, s);
|
||||
final float collapseW = dp(6), collapseH = dp(3f);
|
||||
canvas.drawLine(-collapseW, -collapseH, 0, collapseH, iconStrokePaint);
|
||||
canvas.drawLine(0, collapseH, collapseW, -collapseH, iconStrokePaint);
|
||||
canvas.restore();
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(menuRect.centerX() + dp(1), menuRect.centerY());
|
||||
s = menuBounce.getScale(0.1f);
|
||||
canvas.scale(s, s);
|
||||
canvas.drawCircle(0, -dp(5), dp(1.66f), iconPaint);
|
||||
canvas.drawCircle(0, 0, dp(1.66f), iconPaint);
|
||||
canvas.drawCircle(0, +dp(5), dp(1.66f), iconPaint);
|
||||
final float downloadAlpha = this.animatedDownloading.set(downloading);
|
||||
if (downloadAlpha > 0) {
|
||||
canvas.translate(-dpf2(8.166f), dpf2(3.5f));
|
||||
s = .5f + .5f * downloadAlpha;
|
||||
canvas.scale(s, s);
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 0.4f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
final float t = ((System.currentTimeMillis() - start) % 450 / 450.0f);
|
||||
|
||||
float from = t, to = .5f + t;
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(-dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), from), dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), to));
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 1.0f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
canvas.restore();
|
||||
|
||||
if (to > 1) {
|
||||
from = 0;
|
||||
to = to - 1;
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(-dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), from), dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), to));
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 1.0f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
public void setDownloading(boolean downloading) {
|
||||
if (this.downloading == downloading) return;
|
||||
this.downloading = downloading;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setName(String name, boolean verified) {
|
||||
previewText = new Text(name, 13, AndroidUtilities.bold());
|
||||
if (!verified) {
|
||||
verifiedBackground = null;
|
||||
verifiedForeground = null;
|
||||
} else {
|
||||
verifiedBackground = getContext().getResources().getDrawable(R.drawable.verified_area).mutate();
|
||||
verifiedForeground = getContext().getResources().getDrawable(R.drawable.verified_check).mutate();
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable hidePreview = () -> setPreview(false, true);
|
||||
|
||||
public void setPreview(boolean preview, boolean animated) {
|
||||
AndroidUtilities.cancelRunOnUIThread(hidePreview);
|
||||
this.preview = preview;
|
||||
if (!animated) {
|
||||
this.animatedPreview.set(preview, true);
|
||||
}
|
||||
invalidate();
|
||||
if (preview) {
|
||||
AndroidUtilities.runOnUIThread(hidePreview, 2500);
|
||||
}
|
||||
}
|
||||
|
||||
public Runnable onCloseClickListener;
|
||||
public Runnable onCollapseClickListener;
|
||||
public Runnable onMenuClickListener;
|
||||
public Object parentRenderNode;
|
||||
public WebView webView;
|
||||
|
||||
public void setOnCloseClickListener(Runnable listener) {
|
||||
onCloseClickListener = listener;
|
||||
}
|
||||
public void setOnCollapseClickListener(Runnable listener) {
|
||||
onCollapseClickListener = listener;
|
||||
}
|
||||
public void setOnMenuClickListener(Runnable listener) {
|
||||
onMenuClickListener = listener;
|
||||
}
|
||||
|
||||
public void setParentRenderNode(Object renderNode) {
|
||||
parentRenderNode = renderNode;
|
||||
}
|
||||
public void setWebView(WebView webView) {
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
int pressed;
|
||||
private int getButton(MotionEvent e) {
|
||||
if (closeRectArea.contains(e.getX(), e.getY())) {
|
||||
return 1;
|
||||
} else if (collapseClickRect.contains(e.getX(), e.getY())) {
|
||||
return 2;
|
||||
} else if (menuClickRect.contains(e.getX(), e.getY())) {
|
||||
return 3;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private ButtonBounce getBounce(int button) {
|
||||
switch (button) {
|
||||
case 1: return closeBounce;
|
||||
case 2: return collapseBounce;
|
||||
case 3: return menuBounce;
|
||||
default: return nullBounce;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBack(boolean enable) {
|
||||
setBack(enable, true);
|
||||
}
|
||||
public void setBack(boolean enable, boolean animated) {
|
||||
this.back = enable;
|
||||
if (!animated) {
|
||||
this.animatedBack.set(enable);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
getBounce(pressed).setPressed(false);
|
||||
pressed = getButton(event);
|
||||
getBounce(pressed).setPressed(true);
|
||||
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (getButton(event) != pressed) {
|
||||
pressed = 0;
|
||||
getBounce(pressed).setPressed(false);
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (pressed == 1 && onCloseClickListener != null) {
|
||||
onCloseClickListener.run();
|
||||
} else if (pressed == 2 && onCollapseClickListener != null) {
|
||||
onCollapseClickListener.run();
|
||||
} else if (pressed == 3 && onMenuClickListener != null) {
|
||||
onMenuClickListener.run();
|
||||
}
|
||||
getBounce(pressed).setPressed(false);
|
||||
pressed = 0;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
getBounce(pressed).setPressed(false);
|
||||
pressed = 0;
|
||||
}
|
||||
return pressed != 0;
|
||||
}
|
||||
|
||||
public static class OptionsIcon extends Drawable {
|
||||
|
||||
private final long start;
|
||||
private final Drawable drawable;
|
||||
private final Paint downloadPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Path downloadPath = new Path();
|
||||
|
||||
private boolean downloading = false;
|
||||
private final AnimatedFloat animatedDownloading = new AnimatedFloat(this::invalidateSelf, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||
|
||||
public OptionsIcon(Context context) {
|
||||
start = System.currentTimeMillis();
|
||||
drawable = context.getResources().getDrawable(R.drawable.ic_ab_other).mutate();
|
||||
|
||||
downloadPaint.setPathEffect(new CornerPathEffect(dp(1)));
|
||||
downloadPath.rewind();
|
||||
downloadPath.moveTo(-dpf2(1.33f), dpf2(0.16f));
|
||||
downloadPath.lineTo(-dpf2(1.33f), -dpf2(3.5f));
|
||||
downloadPath.lineTo(dpf2(1.33f), -dpf2(3.5f));
|
||||
downloadPath.lineTo(dpf2(1.33f), dpf2(0.16f));
|
||||
downloadPath.lineTo(dpf2(3.5f), dpf2(0.16f));
|
||||
downloadPath.lineTo(0, dpf2(3.5f));
|
||||
downloadPath.lineTo(-dpf2(3.5f), dpf2(0.16f));
|
||||
downloadPath.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
drawable.setBounds(getBounds());
|
||||
drawable.draw(canvas);
|
||||
|
||||
final float downloadAlpha = this.animatedDownloading.set(downloading);
|
||||
if (downloadAlpha > 0) {
|
||||
canvas.save();
|
||||
canvas.translate(getBounds().centerX(), getBounds().centerY());
|
||||
|
||||
canvas.translate(-dpf2(8.166f), dpf2(5f));
|
||||
float s = .5f + .5f * downloadAlpha;
|
||||
canvas.scale(s, s);
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 0.4f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
final float t = ((System.currentTimeMillis() - start) % 450 / 450.0f);
|
||||
|
||||
float from = t, to = .5f + t;
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(-dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), from), dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), to));
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 1.0f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
canvas.restore();
|
||||
|
||||
if (to > 1) {
|
||||
from = 0;
|
||||
to = to - 1;
|
||||
|
||||
canvas.save();
|
||||
canvas.clipRect(-dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), from), dp(5), lerp(-dpf2(3.5f), dpf2(3.5f), to));
|
||||
downloadPaint.setColor(Theme.multAlpha(0xFFFFFFFF, 1.0f));
|
||||
canvas.drawPath(downloadPath, downloadPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDownloading(boolean downloading) {
|
||||
if (this.downloading == downloading) return;
|
||||
this.downloading = downloading;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
drawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
downloadPaint.setColorFilter(colorFilter);
|
||||
drawable.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSPARENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return drawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return drawable.getIntrinsicHeight();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,6 +84,7 @@ public class ContactsController extends BaseController {
|
|||
private ArrayList<TLRPC.PrivacyRule> addedByPhonePrivacyRules;
|
||||
private ArrayList<TLRPC.PrivacyRule> voiceMessagesRules;
|
||||
private ArrayList<TLRPC.PrivacyRule> birthdayPrivacyRules;
|
||||
private ArrayList<TLRPC.PrivacyRule> giftsPrivacyRules;
|
||||
private TLRPC.TL_globalPrivacySettings globalPrivacySettings;
|
||||
|
||||
public final static int PRIVACY_RULES_TYPE_LASTSEEN = 0;
|
||||
|
@ -98,8 +99,9 @@ public class ContactsController extends BaseController {
|
|||
public final static int PRIVACY_RULES_TYPE_BIO = 9;
|
||||
public final static int PRIVACY_RULES_TYPE_MESSAGES = 10;
|
||||
public final static int PRIVACY_RULES_TYPE_BIRTHDAY = 11;
|
||||
public final static int PRIVACY_RULES_TYPE_GIFTS = 12;
|
||||
|
||||
public final static int PRIVACY_RULES_TYPE_COUNT = 12;
|
||||
public final static int PRIVACY_RULES_TYPE_COUNT = 13;
|
||||
|
||||
private class MyContentObserver extends ContentObserver {
|
||||
|
||||
|
@ -331,6 +333,7 @@ public class ContactsController extends BaseController {
|
|||
profilePhotoPrivacyRules = null;
|
||||
bioPrivacyRules = null;
|
||||
birthdayPrivacyRules = null;
|
||||
giftsPrivacyRules = null;
|
||||
forwardsPrivacyRules = null;
|
||||
phonePrivacyRules = null;
|
||||
|
||||
|
@ -2690,6 +2693,9 @@ public class ContactsController extends BaseController {
|
|||
case PRIVACY_RULES_TYPE_BIRTHDAY:
|
||||
req.key = new TLRPC.TL_inputPrivacyKeyBirthday();
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_GIFTS:
|
||||
req.key = new TLRPC.TL_inputPrivacyKeyStarGiftsAutoSave();
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_ADDED_BY_PHONE:
|
||||
req.key = new TLRPC.TL_inputPrivacyKeyAddedByPhone();
|
||||
break;
|
||||
|
@ -2725,6 +2731,9 @@ public class ContactsController extends BaseController {
|
|||
case PRIVACY_RULES_TYPE_BIRTHDAY:
|
||||
birthdayPrivacyRules = rules.rules;
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_GIFTS:
|
||||
giftsPrivacyRules = rules.rules;
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_FORWARDS:
|
||||
forwardsPrivacyRules = rules.rules;
|
||||
break;
|
||||
|
@ -2789,6 +2798,8 @@ public class ContactsController extends BaseController {
|
|||
return bioPrivacyRules;
|
||||
case PRIVACY_RULES_TYPE_BIRTHDAY:
|
||||
return birthdayPrivacyRules;
|
||||
case PRIVACY_RULES_TYPE_GIFTS:
|
||||
return giftsPrivacyRules;
|
||||
case PRIVACY_RULES_TYPE_FORWARDS:
|
||||
return forwardsPrivacyRules;
|
||||
case PRIVACY_RULES_TYPE_PHONE:
|
||||
|
@ -2824,6 +2835,9 @@ public class ContactsController extends BaseController {
|
|||
case PRIVACY_RULES_TYPE_BIRTHDAY:
|
||||
birthdayPrivacyRules = rules;
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_GIFTS:
|
||||
giftsPrivacyRules = rules;
|
||||
break;
|
||||
case PRIVACY_RULES_TYPE_FORWARDS:
|
||||
forwardsPrivacyRules = rules;
|
||||
break;
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.telegram.ui.Components.AvatarDrawable;
|
|||
import org.telegram.ui.Components.BackupImageView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class DialogObject {
|
||||
|
||||
|
@ -161,13 +162,106 @@ public class DialogObject {
|
|||
|
||||
public static String getPublicUsername(TLObject dialog) {
|
||||
if (dialog instanceof TLRPC.Chat) {
|
||||
return ChatObject.getPublicUsername((TLRPC.Chat) dialog);
|
||||
TLRPC.Chat chat = (TLRPC.Chat) dialog;
|
||||
return getPublicUsername(chat.username, chat.usernames, false);
|
||||
} else if (dialog instanceof TLRPC.User) {
|
||||
return UserObject.getPublicUsername((TLRPC.User) dialog);
|
||||
TLRPC.User user = (TLRPC.User) dialog;
|
||||
return getPublicUsername(user.username, user.usernames, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPublicUsername(TLObject dialog, String query) {
|
||||
if (dialog instanceof TLRPC.Chat) {
|
||||
TLRPC.Chat chat = (TLRPC.Chat) dialog;
|
||||
return query == null ? getPublicUsername(chat.username, chat.usernames, false) : getSimilarPublicUsername(chat.username, chat.usernames, query);
|
||||
} else if (dialog instanceof TLRPC.User) {
|
||||
TLRPC.User user = (TLRPC.User) dialog;
|
||||
return query == null ? getPublicUsername(user.username, user.usernames, false) : getSimilarPublicUsername(user.username, user.usernames, query);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPublicUsername(String username, ArrayList<TLRPC.TL_username> usernames, boolean editable) {
|
||||
if (!TextUtils.isEmpty(username) && !editable) {
|
||||
return username;
|
||||
}
|
||||
if (usernames != null) {
|
||||
for (int i = 0; i < usernames.size(); ++i) {
|
||||
TLRPC.TL_username u = usernames.get(i);
|
||||
if (u != null && (u.active && !editable || u.editable) && !TextUtils.isEmpty(u.username)) {
|
||||
return u.username;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(username) && editable && (usernames == null || usernames.size() <= 0)) {
|
||||
return username;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getSimilarPublicUsername(String obj_username, ArrayList<TLRPC.TL_username> obj_usernames, String query) {
|
||||
double bestSimilarity = -1;
|
||||
String bestUsername = null;
|
||||
if (obj_usernames != null) {
|
||||
for (int i = 0; i < obj_usernames.size(); ++i) {
|
||||
TLRPC.TL_username u = obj_usernames.get(i);
|
||||
if (u != null && u.active && !TextUtils.isEmpty(u.username)) {
|
||||
double s = bestSimilarity < 0 ? 0 : similarity(u.username, query);
|
||||
if (s > bestSimilarity) {
|
||||
bestSimilarity = s;
|
||||
bestUsername = u.username;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(obj_username)) {
|
||||
double s = bestSimilarity < 0 ? 0 : similarity(obj_username, query);
|
||||
if (s > bestSimilarity) {
|
||||
bestSimilarity = s;
|
||||
bestUsername = obj_username;
|
||||
}
|
||||
}
|
||||
return bestUsername;
|
||||
}
|
||||
|
||||
public static double similarity(String s1, String s2) {
|
||||
String longer = s1, shorter = s2;
|
||||
if (s1.length() < s2.length()) { // longer should always have greater length
|
||||
longer = s2; shorter = s1;
|
||||
}
|
||||
int longerLength = longer.length();
|
||||
if (longerLength == 0) { return 1.0; }
|
||||
return (longerLength - editDistance(longer, shorter)) / (double) longerLength;
|
||||
}
|
||||
|
||||
public static int editDistance(String s1, String s2) {
|
||||
s1 = s1.toLowerCase();
|
||||
s2 = s2.toLowerCase();
|
||||
|
||||
int[] costs = new int[s2.length() + 1];
|
||||
for (int i = 0; i <= s1.length(); i++) {
|
||||
int lastValue = i;
|
||||
for (int j = 0; j <= s2.length(); j++) {
|
||||
if (i == 0)
|
||||
costs[j] = j;
|
||||
else {
|
||||
if (j > 0) {
|
||||
int newValue = costs[j - 1];
|
||||
if (s1.charAt(i - 1) != s2.charAt(j - 1))
|
||||
newValue = Math.min(Math.min(newValue, lastValue),
|
||||
costs[j]) + 1;
|
||||
costs[j - 1] = lastValue;
|
||||
lastValue = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i > 0)
|
||||
costs[s2.length()] = lastValue;
|
||||
}
|
||||
return costs[s2.length()];
|
||||
}
|
||||
|
||||
public static long getEmojiStatusDocumentId(TLRPC.EmojiStatus emojiStatus) {
|
||||
if (MessagesController.getInstance(UserConfig.selectedAccount).premiumFeaturesBlocked()) {
|
||||
return 0;
|
||||
|
|
|
@ -620,7 +620,7 @@ public class DownloadController extends BaseController implements NotificationCe
|
|||
}
|
||||
if (messageObject.isHiddenSensitive())
|
||||
return false;
|
||||
return canDownloadMedia(messageObject.messageOwner) == 1;
|
||||
return canDownloadMediaInternal(messageObject) == 1;
|
||||
}
|
||||
|
||||
public boolean canDownloadMedia(int type, long size) {
|
||||
|
@ -663,7 +663,97 @@ public class DownloadController extends BaseController implements NotificationCe
|
|||
}
|
||||
if (messageObject.isHiddenSensitive())
|
||||
return 0;
|
||||
return canDownloadMedia(messageObject.messageOwner);
|
||||
return canDownloadMediaInternal(messageObject);
|
||||
}
|
||||
|
||||
private int canDownloadMediaInternal(MessageObject message) {
|
||||
if (message == null || message.messageOwner == null) return 0;
|
||||
if (message.messageOwner.media instanceof TLRPC.TL_messageMediaStory) {
|
||||
return canPreloadStories() ? 2 : 0;
|
||||
}
|
||||
TLRPC.Message msg = message.messageOwner;
|
||||
int type;
|
||||
boolean isVideo;
|
||||
if ((isVideo = MessageObject.isVideoMessage(msg)) || MessageObject.isGifMessage(msg) || MessageObject.isRoundVideoMessage(msg) || MessageObject.isGameMessage(msg)) {
|
||||
type = AUTODOWNLOAD_TYPE_VIDEO;
|
||||
} else if (MessageObject.isVoiceMessage(msg)) {
|
||||
type = AUTODOWNLOAD_TYPE_AUDIO;
|
||||
} else if (MessageObject.isPhoto(msg) || MessageObject.isStickerMessage(msg) || MessageObject.isAnimatedStickerMessage(msg)) {
|
||||
type = AUTODOWNLOAD_TYPE_PHOTO;
|
||||
} else if (MessageObject.getDocument(msg) != null) {
|
||||
type = AUTODOWNLOAD_TYPE_DOCUMENT;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
int index;
|
||||
TLRPC.Peer peer = msg.peer_id;
|
||||
if (peer != null) {
|
||||
if (peer.user_id != 0) {
|
||||
if (getContactsController().contactsDict.containsKey(peer.user_id)) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = 1;
|
||||
}
|
||||
} else if (peer.chat_id != 0) {
|
||||
if (msg.from_id instanceof TLRPC.TL_peerUser && getContactsController().contactsDict.containsKey(msg.from_id.user_id)) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = 2;
|
||||
}
|
||||
} else {
|
||||
TLRPC.Chat chat = msg.peer_id.channel_id != 0 ? getMessagesController().getChat(msg.peer_id.channel_id) : null;
|
||||
if (ChatObject.isChannel(chat) && chat.megagroup) {
|
||||
if (msg.from_id instanceof TLRPC.TL_peerUser && getContactsController().contactsDict.containsKey(msg.from_id.user_id)) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = 2;
|
||||
}
|
||||
} else {
|
||||
index = 3;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index = 1;
|
||||
}
|
||||
Preset preset;
|
||||
int networkType = ApplicationLoader.getAutodownloadNetworkType();
|
||||
if (networkType == StatsController.TYPE_WIFI) {
|
||||
if (!wifiPreset.enabled) {
|
||||
return 0;
|
||||
}
|
||||
preset = getCurrentWiFiPreset();
|
||||
|
||||
} else if (networkType == StatsController.TYPE_ROAMING) {
|
||||
if (!roamingPreset.enabled) {
|
||||
return 0;
|
||||
}
|
||||
preset = getCurrentRoamingPreset();
|
||||
} else {
|
||||
if (!mobilePreset.enabled) {
|
||||
return 0;
|
||||
}
|
||||
preset = getCurrentMobilePreset();
|
||||
}
|
||||
int mask = preset.mask[index];
|
||||
long maxSize;
|
||||
if (type == AUTODOWNLOAD_TYPE_AUDIO) {
|
||||
maxSize = Math.max(512 * 1024, preset.sizes[typeToIndex(type)]);
|
||||
} else {
|
||||
maxSize = preset.sizes[typeToIndex(type)];
|
||||
}
|
||||
long size;
|
||||
if (message.highestQuality != null) {
|
||||
size = message.highestQuality.document.size;
|
||||
} else if (message.thumbQuality != null) {
|
||||
size = message.thumbQuality.document.size;
|
||||
} else {
|
||||
size = MessageObject.getMessageSize(msg);
|
||||
}
|
||||
if (isVideo && preset.preloadVideo && size > maxSize && maxSize > 2 * 1024 * 1024) {
|
||||
return (mask & type) != 0 ? 2 : 0;
|
||||
} else {
|
||||
return (type == AUTODOWNLOAD_TYPE_PHOTO || size != 0 && size <= maxSize) && (type == AUTODOWNLOAD_TYPE_AUDIO || (mask & type) != 0) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int canDownloadMedia(TLRPC.Message message) {
|
||||
|
|
|
@ -60,6 +60,9 @@ public class FileLoadOperation {
|
|||
if (stream != null && !streamListeners.contains(stream)) {
|
||||
streamListeners.add(stream);
|
||||
}
|
||||
if (!streamListeners.isEmpty()) {
|
||||
Utilities.stageQueue.cancelRunnable(cancelAfterNoStreamListeners);
|
||||
}
|
||||
if (stream != null && state != stateDownloading && state != stateIdle) {
|
||||
stream.newDataAvailable();
|
||||
}
|
||||
|
@ -195,6 +198,7 @@ public class FileLoadOperation {
|
|||
private boolean started;
|
||||
private int datacenterId;
|
||||
private int initialDatacenterId;
|
||||
private long documentId;
|
||||
protected TLRPC.InputFileLocation location;
|
||||
private TLRPC.InputWebFileLocation webLocation;
|
||||
private WebFile webFile;
|
||||
|
@ -338,7 +342,7 @@ public class FileLoadOperation {
|
|||
}
|
||||
} else {
|
||||
location = new TLRPC.TL_inputDocumentFileLocation();
|
||||
location.id = imageLocation.documentId;
|
||||
documentId = location.id = imageLocation.documentId;
|
||||
location.volume_id = imageLocation.location.volume_id;
|
||||
location.local_id = imageLocation.location.local_id;
|
||||
location.access_hash = imageLocation.access_hash;
|
||||
|
@ -415,7 +419,7 @@ public class FileLoadOperation {
|
|||
key = documentLocation.key;
|
||||
} else if (documentLocation instanceof TLRPC.TL_document) {
|
||||
location = new TLRPC.TL_inputDocumentFileLocation();
|
||||
location.id = documentLocation.id;
|
||||
documentId = location.id = documentLocation.id;
|
||||
location.access_hash = documentLocation.access_hash;
|
||||
location.file_reference = documentLocation.file_reference;
|
||||
location.thumb_size = "";
|
||||
|
@ -763,16 +767,31 @@ public class FileLoadOperation {
|
|||
return fileName;
|
||||
}
|
||||
|
||||
public long getDocumentId() {
|
||||
return documentId;
|
||||
}
|
||||
|
||||
protected void removeStreamListener(final FileLoadOperationStream operation) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (streamListeners == null) {
|
||||
return;
|
||||
}
|
||||
FileLog.e("FileLoadOperation " + getFileName() + " removing stream listener " + stream);
|
||||
FileLog.e("FileLoadOperation " + getFileName() + " removing stream listener " + operation);
|
||||
streamListeners.remove(operation);
|
||||
if (!isStory && streamListeners.isEmpty()) {
|
||||
Utilities.stageQueue.cancelRunnable(cancelAfterNoStreamListeners);
|
||||
Utilities.stageQueue.postRunnable(cancelAfterNoStreamListeners, 1200);
|
||||
} else if (!streamListeners.isEmpty()) {
|
||||
Utilities.stageQueue.cancelRunnable(cancelAfterNoStreamListeners);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final Runnable cancelAfterNoStreamListeners = () -> {
|
||||
pause();
|
||||
FileLoader.getInstance(currentAccount).cancelLoadFile(getFileName());
|
||||
};
|
||||
|
||||
private void copyNotLoadedRanges() {
|
||||
if (notLoadedBytesRanges == null) {
|
||||
return;
|
||||
|
@ -788,7 +807,7 @@ public class FileLoadOperation {
|
|||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (isStory) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("debug_loading:" + cacheFileFinal.getName() + " pause operation, clear requests");
|
||||
FileLog.d("debug_loading: " + cacheFileFinal.getName() + " pause operation, clear requests");
|
||||
}
|
||||
clearOperation(null, false, true);
|
||||
} else {
|
||||
|
@ -860,6 +879,9 @@ public class FileLoadOperation {
|
|||
streamListeners.add(stream);
|
||||
FileLog.e("FileLoadOperation " + getFileName() + " start, adding stream " + stream);
|
||||
}
|
||||
if (!streamListeners.isEmpty()) {
|
||||
Utilities.stageQueue.cancelRunnable(cancelAfterNoStreamListeners);
|
||||
}
|
||||
if (alreadyStarted) {
|
||||
if (preloadedBytesRanges != null && getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, streamStartOffset, 1) == 0) {
|
||||
if (preloadedBytesRanges.get(streamStartOffset) != null) {
|
||||
|
@ -1319,64 +1341,68 @@ public class FileLoadOperation {
|
|||
|
||||
private void cancel(boolean deleteFiles) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (state != stateFinished && state != stateFailed) {
|
||||
state = stateCancelling;
|
||||
cancelRequests(() -> {
|
||||
if (state == stateCancelling) {
|
||||
onFail(false, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (deleteFiles) {
|
||||
if (cacheFileFinal != null) {
|
||||
try {
|
||||
if (!cacheFileFinal.delete()) {
|
||||
cacheFileFinal.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFileTemp != null) {
|
||||
try {
|
||||
if (!cacheFileTemp.delete()) {
|
||||
cacheFileTemp.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFileParts != null) {
|
||||
try {
|
||||
if (!cacheFileParts.delete()) {
|
||||
cacheFileParts.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheIvTemp != null) {
|
||||
try {
|
||||
if (!cacheIvTemp.delete()) {
|
||||
cacheIvTemp.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFilePreload != null) {
|
||||
try {
|
||||
if (!cacheFilePreload.delete()) {
|
||||
cacheFilePreload.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
cancelOnStage(deleteFiles);
|
||||
});
|
||||
}
|
||||
|
||||
private void cancelOnStage(boolean deleteFiles) {
|
||||
if (state != stateFinished && state != stateFailed) {
|
||||
state = stateCancelling;
|
||||
cancelRequests(() -> {
|
||||
if (state == stateCancelling) {
|
||||
onFail(false, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (deleteFiles) {
|
||||
if (cacheFileFinal != null) {
|
||||
try {
|
||||
if (!cacheFileFinal.delete()) {
|
||||
cacheFileFinal.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFileTemp != null) {
|
||||
try {
|
||||
if (!cacheFileTemp.delete()) {
|
||||
cacheFileTemp.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFileParts != null) {
|
||||
try {
|
||||
if (!cacheFileParts.delete()) {
|
||||
cacheFileParts.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheIvTemp != null) {
|
||||
try {
|
||||
if (!cacheIvTemp.delete()) {
|
||||
cacheIvTemp.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (cacheFilePreload != null) {
|
||||
try {
|
||||
if (!cacheFilePreload.delete()) {
|
||||
cacheFilePreload.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelRequests(Runnable fullyCancelled) {
|
||||
FileLog.d("cancelRequests" + (fullyCancelled != null ? " with callback" : ""));
|
||||
if (requestInfos != null) {
|
||||
|
|
|
@ -623,6 +623,28 @@ public class FileLoader extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void cancel(FileLoadOperation operation) {
|
||||
if (operation == null) return;
|
||||
final String fileName = operation.getFileName();
|
||||
LoadOperationUIObject uiObject = loadOperationPathsUI.remove(fileName);
|
||||
Runnable runnable = uiObject != null ? uiObject.loadInternalRunnable : null;
|
||||
boolean removed = uiObject != null;
|
||||
if (runnable != null) {
|
||||
fileLoaderQueue.cancelRunnable(runnable);
|
||||
}
|
||||
fileLoaderQueue.postRunnable(() -> {
|
||||
FileLoadOperation operation2 = loadOperationPaths.remove(fileName);
|
||||
if (operation2 != null) {
|
||||
operation2.getQueue().cancel(operation2);
|
||||
}
|
||||
});
|
||||
if (removed) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void changePriority(int priority, final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, final TLRPC.FileLocation location, final String locationExt, String name) {
|
||||
if (location == null && document == null && webDocument == null && secureDocument == null && TextUtils.isEmpty(name)) {
|
||||
return;
|
||||
|
|
|
@ -171,12 +171,10 @@ public class FilePathDatabase {
|
|||
}
|
||||
return path;
|
||||
}
|
||||
if (dispatchQueue != null && dispatchQueue.getHandler() != null && Thread.currentThread() == dispatchQueue.getHandler().getLooper().getThread()) {
|
||||
useQueue = false;
|
||||
}
|
||||
if (useQueue) {
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
||||
if (dispatchQueue != null && dispatchQueue.getHandler() != null && Thread.currentThread() == dispatchQueue.getHandler().getLooper().getThread()) {
|
||||
throw new RuntimeException("Error, lead to infinity loop");
|
||||
}
|
||||
}
|
||||
|
||||
CountDownLatch syncLatch = new CountDownLatch(1);
|
||||
String[] res = new String[1];
|
||||
|
|
|
@ -52,7 +52,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
private static final ConcurrentHashMap<Long, Integer> priorityMap = new ConcurrentHashMap<>();
|
||||
|
||||
public FileStreamLoadOperation() {
|
||||
super(/* isNetwork= */ false);
|
||||
super(/* isNetwork= */ true);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
@ -113,6 +113,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
file = new RandomAccessFile(currentFile, "r");
|
||||
file.seek(currentOffset);
|
||||
if (loadOperation.isFinished()) {
|
||||
super.isNetwork = false;
|
||||
bytesRemaining = currentFile.length() - currentOffset;
|
||||
if (requestedLength != C.LENGTH_UNSET) {
|
||||
bytesRemaining = Math.min(bytesRemaining, requestedLength - bytesTransferred);
|
||||
|
@ -122,7 +123,8 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
}
|
||||
}
|
||||
}
|
||||
// FileLog.e("FileStreamLoadOperation " + document.id + " open operation=" + loadOperation + " currentFile=" + currentFile + " file=" + file + " bytesRemaining=" + bytesRemaining + " me=" + this);
|
||||
FileLog.e("FileStreamLoadOperation " + document.id + " open operation=" + loadOperation + " currentFile=" + currentFile + " file=" + file + " bytesRemaining=" + bytesRemaining + " me=" + this);
|
||||
FileLog.e("FileStreamLoadOperation " + document.id + " " + MessageObject.getVideoWidth(document) + "x" + MessageObject.getVideoWidth(document) + " mime_type="+document.mime_type+" codec="+MessageObject.getVideoCodec(document)+" size="+ document.size);
|
||||
return bytesRemaining;
|
||||
}
|
||||
|
||||
|
@ -185,13 +187,22 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
file = new RandomAccessFile(currentFile, "r");
|
||||
file.seek(currentOffset);
|
||||
if (loadOperation.isFinished()) {
|
||||
super.isNetwork = false;
|
||||
bytesRemaining = currentFile.length() - currentOffset;
|
||||
if (requestedLength != C.LENGTH_UNSET) {
|
||||
bytesRemaining = Math.min(bytesRemaining, requestedLength - bytesTransferred);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
||||
if (loadOperation.isFinished() && !currentFile.exists()) {
|
||||
FileLoader.getInstance(currentAccount).cancelLoadFile(loadOperation.getFileName());
|
||||
FileLoadOperation newLoadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, null, parentObject, currentOffset, false, getCurrentPriority());
|
||||
if (this.loadOperation != newLoadOperation) {
|
||||
// FileLog.e("FileStreamLoadOperation " + document.id + " read: changed operation!");
|
||||
this.loadOperation.removeStreamListener(this);
|
||||
this.loadOperation = newLoadOperation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -223,7 +234,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
// FileLog.e("FileStreamLoadOperation " + document.id + " close me=" + this);
|
||||
FileLog.e("FileStreamLoadOperation " + document.id + " close me=" + this);
|
||||
if (loadOperation != null) {
|
||||
loadOperation.removeStreamListener(this);
|
||||
}
|
||||
|
@ -273,15 +284,16 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
return Uri.fromFile(file);
|
||||
}
|
||||
try {
|
||||
String params = "?account=" + currentAccount +
|
||||
"&id=" + document.id +
|
||||
"&hash=" + document.access_hash +
|
||||
"&dc=" + document.dc_id +
|
||||
"&size=" + document.size +
|
||||
"&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") +
|
||||
"&rid=" + FileLoader.getInstance(currentAccount).getFileReference(parent) +
|
||||
"&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") +
|
||||
"&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]);
|
||||
String params =
|
||||
"?account=" + currentAccount +
|
||||
"&id=" + document.id +
|
||||
"&hash=" + document.access_hash +
|
||||
"&dc=" + document.dc_id +
|
||||
"&size=" + document.size +
|
||||
"&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") +
|
||||
"&rid=" + FileLoader.getInstance(currentAccount).getFileReference(parent) +
|
||||
"&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") +
|
||||
"&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]);
|
||||
return Uri.parse("tg://" + attachFileName + params);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
FileLog.e(e);
|
||||
|
|
|
@ -40,8 +40,9 @@ public class HashtagSearchController {
|
|||
|
||||
public final int currentAccount;
|
||||
|
||||
private final SearchResult myMessagesSearch = new SearchResult();
|
||||
private final SearchResult channelPostsSearch = new SearchResult();
|
||||
private final SearchResult myMessagesSearch;
|
||||
private final SearchResult channelPostsSearch;
|
||||
private final SearchResult localPostsSearch;
|
||||
private final SharedPreferences historyPreferences;
|
||||
|
||||
public final ArrayList<String> history = new ArrayList<>();
|
||||
|
@ -49,6 +50,9 @@ public class HashtagSearchController {
|
|||
|
||||
private HashtagSearchController(int currentAccount) {
|
||||
this.currentAccount = currentAccount;
|
||||
myMessagesSearch = new SearchResult(currentAccount);
|
||||
channelPostsSearch = new SearchResult(currentAccount);
|
||||
localPostsSearch = new SearchResult(currentAccount);
|
||||
|
||||
historyPreferences = ApplicationLoader.applicationContext.getSharedPreferences("hashtag_search_history" + currentAccount, Activity.MODE_PRIVATE);
|
||||
loadHistoryFromPref();
|
||||
|
@ -110,11 +114,13 @@ public class HashtagSearchController {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
private SearchResult getSearchResult(int searchType) {
|
||||
public SearchResult getSearchResult(int searchType) {
|
||||
if (searchType == ChatActivity.SEARCH_MY_MESSAGES) {
|
||||
return myMessagesSearch;
|
||||
} else if (searchType == ChatActivity.SEARCH_PUBLIC_POSTS) {
|
||||
return channelPostsSearch;
|
||||
} else if (searchType == ChatActivity.SEARCH_CHANNEL_POSTS) {
|
||||
return localPostsSearch;
|
||||
}
|
||||
throw new RuntimeException("Unknown search type");
|
||||
}
|
||||
|
@ -131,25 +137,63 @@ public class HashtagSearchController {
|
|||
return getSearchResult(searchType).endReached;
|
||||
}
|
||||
|
||||
public void searchHashtag(String hashtag, int guid, int searchType, int loadIndex) {
|
||||
public void searchHashtag(String _query, int guid, int searchType, int loadIndex) {
|
||||
SearchResult search = getSearchResult(searchType);
|
||||
if (search.lastHashtag == null && hashtag == null) {
|
||||
if (search.lastHashtag == null && _query == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hashtag != null && hashtag.isEmpty()) {
|
||||
if (_query != null && _query.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hashtag == null) {
|
||||
hashtag = search.lastHashtag;
|
||||
} else if (!TextUtils.equals(hashtag, search.lastHashtag)) {
|
||||
if (_query == null) {
|
||||
_query = search.lastHashtag;
|
||||
} else if (!TextUtils.equals(_query, search.lastHashtag)) {
|
||||
search.clear();
|
||||
} else if (search.loading) {
|
||||
return;
|
||||
}
|
||||
search.lastHashtag = hashtag;
|
||||
search.lastHashtag = _query;
|
||||
final String query = _query;
|
||||
|
||||
final String query = hashtag;
|
||||
int limit = 30;
|
||||
String _username = null;
|
||||
int atIndex = _query.indexOf('@');
|
||||
if (atIndex >= 0) {
|
||||
_username = _query.substring(atIndex + 1);
|
||||
_query = _query.substring(0, atIndex);
|
||||
}
|
||||
final String hashtag = _query;
|
||||
final String username = _username;
|
||||
search.loading = true;
|
||||
|
||||
final int[] reqId = new int[1];
|
||||
TLObject chat = null;
|
||||
if (!TextUtils.isEmpty(username)) {
|
||||
chat = MessagesController.getInstance(currentAccount).getUserOrChat(username);
|
||||
if (chat == null) {
|
||||
reqId[0] = search.reqId = MessagesController.getInstance(currentAccount).getUserNameResolver().resolve(username, resolvedChatId -> {
|
||||
if (!TextUtils.equals(search.lastHashtag, query)) return;
|
||||
final TLObject resolvedChat = MessagesController.getInstance(currentAccount).getUserOrChat(username);
|
||||
if (resolvedChat == null) {
|
||||
if (reqId[0] == search.reqId) {
|
||||
search.reqId = -1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
search.loading = false;
|
||||
search.endReached = true;
|
||||
search.count = 0;
|
||||
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.hashtagSearchUpdated, guid, search.count, search.endReached, search.getMask(), search.selectedIndex, 0);
|
||||
return;
|
||||
}
|
||||
searchHashtag(query, guid, searchType, loadIndex);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int limit = 21;
|
||||
TLObject request;
|
||||
if (searchType == ChatActivity.SEARCH_MY_MESSAGES) {
|
||||
TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal();
|
||||
|
@ -164,18 +208,30 @@ public class HashtagSearchController {
|
|||
}
|
||||
request = req;
|
||||
} else {
|
||||
TLRPC.TL_channels_searchPosts req = new TLRPC.TL_channels_searchPosts();
|
||||
req.limit = limit;
|
||||
req.hashtag = query;
|
||||
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
|
||||
if (search.lastOffsetPeer != null) {
|
||||
req.offset_rate = search.lastOffsetRate;
|
||||
req.offset_id = search.lastOffsetId;
|
||||
req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(search.lastOffsetPeer);
|
||||
if (chat != null) {
|
||||
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
|
||||
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
|
||||
req.peer = MessagesController.getInputPeer(chat);
|
||||
req.q = hashtag;
|
||||
req.limit = limit;
|
||||
if (search.lastOffsetId != 0) {
|
||||
req.offset_id = search.lastOffsetId;
|
||||
}
|
||||
request = req;
|
||||
} else {
|
||||
TLRPC.TL_channels_searchPosts req = new TLRPC.TL_channels_searchPosts();
|
||||
req.limit = limit;
|
||||
req.hashtag = query;
|
||||
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
|
||||
if (search.lastOffsetPeer != null) {
|
||||
req.offset_rate = search.lastOffsetRate;
|
||||
req.offset_id = search.lastOffsetId;
|
||||
req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(search.lastOffsetPeer);
|
||||
}
|
||||
request = req;
|
||||
}
|
||||
request = req;
|
||||
}
|
||||
ConnectionsManager.getInstance(currentAccount).sendRequest(request, (res, err) -> {
|
||||
reqId[0] = search.reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (res, err) -> {
|
||||
if (res instanceof TLRPC.messages_Messages) {
|
||||
TLRPC.messages_Messages messages = (TLRPC.messages_Messages) res;
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
|
@ -184,11 +240,17 @@ public class HashtagSearchController {
|
|||
if (obj.hasValidGroupId()) {
|
||||
obj.isPrimaryGroupMessage = true;
|
||||
}
|
||||
obj.setQuery(query);
|
||||
obj.setQuery(query, false);
|
||||
messageObjects.add(obj);
|
||||
}
|
||||
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (reqId[0] == search.reqId) {
|
||||
search.reqId = -1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
search.loading = false;
|
||||
search.lastOffsetRate = messages.next_rate;
|
||||
|
||||
for (MessageObject msg : messageObjects) {
|
||||
|
@ -205,7 +267,7 @@ public class HashtagSearchController {
|
|||
|
||||
if (!messages.messages.isEmpty()) {
|
||||
TLRPC.Message lastMsg = messages.messages.get(messages.messages.size() - 1);
|
||||
search.lastOffsetId = lastMsg.id;
|
||||
search.lastOffsetId = lastMsg.realId;
|
||||
search.lastOffsetPeer = lastMsg.peer_id;
|
||||
}
|
||||
|
||||
|
@ -268,18 +330,25 @@ public class HashtagSearchController {
|
|||
}
|
||||
}
|
||||
|
||||
private static class SearchResult {
|
||||
ArrayList<MessageObject> messages = new ArrayList<>();
|
||||
HashMap<MessageCompositeID, Integer> generatedIds = new HashMap<>();
|
||||
public static class SearchResult {
|
||||
public final ArrayList<MessageObject> messages = new ArrayList<>();
|
||||
public final HashMap<MessageCompositeID, Integer> generatedIds = new HashMap<>();
|
||||
|
||||
int lastOffsetRate;
|
||||
int lastOffsetId;
|
||||
TLRPC.Peer lastOffsetPeer;
|
||||
int lastGeneratedId = Integer.MAX_VALUE;
|
||||
String lastHashtag;
|
||||
int selectedIndex;
|
||||
int count;
|
||||
boolean endReached;
|
||||
private final int currentAccount;
|
||||
public SearchResult(int account) {
|
||||
this.currentAccount = account;
|
||||
}
|
||||
|
||||
public int reqId = -1;
|
||||
public boolean loading;
|
||||
public int lastOffsetRate;
|
||||
public int lastOffsetId;
|
||||
public TLRPC.Peer lastOffsetPeer;
|
||||
public int lastGeneratedId = Integer.MAX_VALUE;
|
||||
public String lastHashtag;
|
||||
public int selectedIndex;
|
||||
public int count;
|
||||
public boolean endReached;
|
||||
|
||||
int getMask() {
|
||||
int mask = 0;
|
||||
|
@ -293,6 +362,10 @@ public class HashtagSearchController {
|
|||
}
|
||||
|
||||
void clear() {
|
||||
if (reqId >= 0) {
|
||||
ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true);
|
||||
reqId = -1;
|
||||
}
|
||||
messages.clear();
|
||||
generatedIds.clear();
|
||||
lastOffsetRate = 0;
|
||||
|
|
|
@ -222,6 +222,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
|
||||
private int currentAccount;
|
||||
private View parentView;
|
||||
private Runnable parentRunnable;
|
||||
|
||||
private int param;
|
||||
private Object currentParentObject;
|
||||
|
|
|
@ -2095,6 +2095,56 @@ public class LocaleController {
|
|||
return "LOC_ERR";
|
||||
}
|
||||
|
||||
public static String formatPmEditedDate(long date) {
|
||||
try {
|
||||
date *= 1000;
|
||||
Calendar rightNow = Calendar.getInstance();
|
||||
int day = rightNow.get(Calendar.DAY_OF_YEAR);
|
||||
int year = rightNow.get(Calendar.YEAR);
|
||||
rightNow.setTimeInMillis(date);
|
||||
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
|
||||
int dateYear = rightNow.get(Calendar.YEAR);
|
||||
|
||||
if (dateDay == day && year == dateYear) {
|
||||
return LocaleController.formatString(R.string.PmEditedTodayAt, getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else if (dateDay + 1 == day && year == dateYear) {
|
||||
return LocaleController.formatString(R.string.PmEditedYesterdayAt, getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
|
||||
return LocaleController.formatString(R.string.PmEditedDateTimeAt, getInstance().getFormatterDayMonth().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else {
|
||||
return LocaleController.formatString(R.string.PmEditedDateTimeAt, getInstance().getFormatterYear().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return "LOC_ERR";
|
||||
}
|
||||
|
||||
public static String formatPmFwdDate(long date) {
|
||||
try {
|
||||
date *= 1000;
|
||||
Calendar rightNow = Calendar.getInstance();
|
||||
int day = rightNow.get(Calendar.DAY_OF_YEAR);
|
||||
int year = rightNow.get(Calendar.YEAR);
|
||||
rightNow.setTimeInMillis(date);
|
||||
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
|
||||
int dateYear = rightNow.get(Calendar.YEAR);
|
||||
|
||||
if (dateDay == day && year == dateYear) {
|
||||
return LocaleController.formatString(R.string.PmFwdOriginalTodayAt, getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else if (dateDay + 1 == day && year == dateYear) {
|
||||
return LocaleController.formatString(R.string.PmFwdOriginalYesterdayAt, getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
|
||||
return LocaleController.formatString(R.string.PmFwdOriginalDateTimeAt, getInstance().getFormatterDayMonth().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
|
||||
} else {
|
||||
return LocaleController.formatString(R.string.PmFwdOriginalDateTimeAt, getInstance().getFormatterYear().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return "LOC_ERR";
|
||||
}
|
||||
|
||||
public static String formatShortDate(long date) {
|
||||
try {
|
||||
date *= 1000;
|
||||
|
|
|
@ -2968,7 +2968,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
}
|
||||
} else if (videoPlayer.isPlaying() && playbackState == ExoPlayer.STATE_ENDED) {
|
||||
if (playingMessageObject.isVideo() && !destroyAtEnd && (playCount == null || playCount[0] < 4)) {
|
||||
if (playingMessageObject != null && playingMessageObject.isVideo() && !destroyAtEnd && (playCount == null || playCount[0] < 4)) {
|
||||
videoPlayer.seekTo(0);
|
||||
if (playCount != null) {
|
||||
playCount[0]++;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -1279,6 +1280,32 @@ public class MediaDataController extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
public static String inputSetKey(TLRPC.InputStickerSet i) {
|
||||
if (i instanceof TLRPC.TL_inputStickerSetID)
|
||||
return "id" + i.id + "access_hash" + i.access_hash;
|
||||
if (i instanceof TLRPC.TL_inputStickerSetShortName)
|
||||
return "short" + i.short_name;
|
||||
if (i instanceof TLRPC.TL_inputStickerSetEmpty)
|
||||
return "empty";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetAnimatedEmoji)
|
||||
return "animatedEmoji";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetEmojiGenericAnimations)
|
||||
return "emojiGenericAnimations";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetEmojiChannelDefaultStatuses)
|
||||
return "emojiChannelDefaultStatuses";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetDice)
|
||||
return "dice" + ((TLRPC.TL_inputStickerSetDice) i).emoticon;
|
||||
if (i instanceof TLRPC.TL_inputStickerSetPremiumGifts)
|
||||
return "premiumGifts";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetEmojiDefaultTopicIcons)
|
||||
return "defaultTopicIcons";
|
||||
if (i instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses)
|
||||
return "emojiDefaultStatuses";
|
||||
return "null";
|
||||
}
|
||||
|
||||
private final HashSet<String> loadingStickerSetsKeys = new HashSet<>();
|
||||
|
||||
public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputStickerSet, boolean cacheOnly) {
|
||||
return getStickerSet(inputStickerSet, null, cacheOnly, null);
|
||||
}
|
||||
|
@ -1311,11 +1338,15 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
return cacheSet;
|
||||
}
|
||||
final String key = inputSetKey(inputStickerSet);
|
||||
if (onResponse == null && loadingStickerSetsKeys.contains(key)) return null;
|
||||
loadingStickerSetsKeys.add(key);
|
||||
if (inputStickerSet instanceof TLRPC.TL_inputStickerSetID) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
TLRPC.TL_messages_stickerSet cachedSet = getCachedStickerSetInternal(inputStickerSet.id, hash);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (cachedSet != null) {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
if (onResponse != null) {
|
||||
onResponse.run(cachedSet);
|
||||
}
|
||||
|
@ -1324,8 +1355,9 @@ public class MediaDataController extends BaseController {
|
|||
stickerSetsByName.put(cachedSet.set.short_name.toLowerCase(), cachedSet);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, cachedSet.set.id, cachedSet);
|
||||
} else {
|
||||
} else if (!cacheOnly) {
|
||||
fetchStickerSetInternal(inputStickerSet, (ok, set) -> {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
if (onResponse != null) {
|
||||
onResponse.run(set);
|
||||
}
|
||||
|
@ -1336,6 +1368,8 @@ public class MediaDataController extends BaseController {
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, set.set.id, set);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1344,6 +1378,7 @@ public class MediaDataController extends BaseController {
|
|||
TLRPC.TL_messages_stickerSet cachedSet = getCachedStickerSetInternal(inputStickerSet.short_name.toLowerCase(), hash);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (cachedSet != null) {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
if (onResponse != null) {
|
||||
onResponse.run(cachedSet);
|
||||
}
|
||||
|
@ -1352,8 +1387,9 @@ public class MediaDataController extends BaseController {
|
|||
stickerSetsByName.put(cachedSet.set.short_name.toLowerCase(), cachedSet);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, cachedSet.set.id, cachedSet);
|
||||
} else {
|
||||
} else if (!cacheOnly) {
|
||||
fetchStickerSetInternal(inputStickerSet, (ok, set) -> {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
if (onResponse != null) {
|
||||
onResponse.run(set);
|
||||
}
|
||||
|
@ -1364,11 +1400,14 @@ public class MediaDataController extends BaseController {
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, set.set.id, set);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (!cacheOnly) {
|
||||
fetchStickerSetInternal(inputStickerSet, (ok, set) -> {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
if (onResponse != null) {
|
||||
onResponse.run(set);
|
||||
}
|
||||
|
@ -1387,6 +1426,8 @@ public class MediaDataController extends BaseController {
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, set.set.id, set);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
loadingStickerSetsKeys.remove(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1527,26 +1568,27 @@ public class MediaDataController extends BaseController {
|
|||
return set;
|
||||
}
|
||||
|
||||
private final HashMap<TLRPC.InputStickerSet, ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>>> loadingStickerSets = new HashMap<>();
|
||||
private final HashMap<String, ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>>> loadingStickerSets = new HashMap<>();
|
||||
|
||||
private void fetchStickerSetInternal(TLRPC.InputStickerSet inputStickerSet, Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet> onDone) {
|
||||
if (onDone == null) {
|
||||
return;
|
||||
}
|
||||
ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>> loading = loadingStickerSets.get(inputStickerSet);
|
||||
final String key = inputSetKey(inputStickerSet);
|
||||
ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>> loading = loadingStickerSets.get(key);
|
||||
if (loading != null && loading.size() > 0) {
|
||||
loading.add(onDone);
|
||||
return;
|
||||
}
|
||||
if (loading == null) {
|
||||
loadingStickerSets.put(inputStickerSet, loading = new ArrayList<>());
|
||||
loadingStickerSets.put(key, loading = new ArrayList<>());
|
||||
}
|
||||
loading.add(onDone);
|
||||
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
|
||||
req.stickerset = inputStickerSet;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>> loadingCallbacks = loadingStickerSets.get(inputStickerSet);
|
||||
ArrayList<Utilities.Callback2<Boolean, TLRPC.TL_messages_stickerSet>> loadingCallbacks = loadingStickerSets.get(key);
|
||||
if (loadingCallbacks != null) {
|
||||
for (int i = 0; i < loadingCallbacks.size(); ++i) {
|
||||
if (response != null) {
|
||||
|
@ -1556,7 +1598,7 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
}
|
||||
loadingStickerSets.remove(inputStickerSet);
|
||||
loadingStickerSets.remove(key);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -3786,6 +3828,7 @@ public class MediaDataController extends BaseController {
|
|||
searchServerResultMessagesMap[1].clear();
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid);
|
||||
}
|
||||
final boolean isHashtag = query != null && (query.trim().startsWith("#") || query.trim().startsWith("$"));
|
||||
if (messagesSearchEndReached[0] && !messagesSearchEndReached[1] && mergeDialogId != 0) {
|
||||
queryWithDialog = mergeDialogId;
|
||||
}
|
||||
|
@ -3921,7 +3964,7 @@ public class MediaDataController extends BaseController {
|
|||
if (messageObject.hasValidGroupId()) {
|
||||
messageObject.isPrimaryGroupMessage = true;
|
||||
}
|
||||
messageObject.setQuery(finalQuery);
|
||||
messageObject.setQuery(finalQuery, !isHashtag);
|
||||
messageObjects.add(messageObject);
|
||||
}
|
||||
}
|
||||
|
@ -5452,6 +5495,7 @@ public class MediaDataController extends BaseController {
|
|||
|
||||
public static int SHORTCUT_TYPE_USER_OR_CHAT = 0;
|
||||
public static int SHORTCUT_TYPE_ATTACHED_BOT = 1;
|
||||
|
||||
private Intent createIntrnalShortcutIntent(long dialogId) {
|
||||
Intent shortcutIntent = new Intent(ApplicationLoader.applicationContext, OpenChatReceiver.class);
|
||||
|
||||
|
@ -5491,10 +5535,18 @@ public class MediaDataController extends BaseController {
|
|||
return shortcutIntent;
|
||||
}
|
||||
|
||||
public final HashMap<String, Utilities.Callback<Boolean>> shortcutCallbacks = new HashMap<>();
|
||||
|
||||
public void installShortcut(long dialogId, int type) {
|
||||
installShortcut(dialogId, type, null);
|
||||
}
|
||||
public void installShortcut(long dialogId, int type, Utilities.Callback<Boolean> callback) {
|
||||
try {
|
||||
Intent shortcutIntent = type == SHORTCUT_TYPE_USER_OR_CHAT ? createIntrnalShortcutIntent(dialogId) : createIntrnalAttachedBotShortcutIntent(dialogId);
|
||||
if (shortcutIntent == null) {
|
||||
if (callback != null) {
|
||||
callback.run(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
TLRPC.User user = null;
|
||||
|
@ -5503,6 +5555,9 @@ public class MediaDataController extends BaseController {
|
|||
int encryptedChatId = DialogObject.getEncryptedChatId(dialogId);
|
||||
TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(encryptedChatId);
|
||||
if (encryptedChat == null) {
|
||||
if (callback != null) {
|
||||
callback.run(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
user = getMessagesController().getUser(encryptedChat.user_id);
|
||||
|
@ -5511,9 +5566,15 @@ public class MediaDataController extends BaseController {
|
|||
} else if (DialogObject.isChatDialog(dialogId)) {
|
||||
chat = getMessagesController().getChat(-dialogId);
|
||||
} else {
|
||||
if (callback != null) {
|
||||
callback.run(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (user == null && chat == null) {
|
||||
if (callback != null) {
|
||||
callback.run(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5602,9 +5663,9 @@ public class MediaDataController extends BaseController {
|
|||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
String idPrefix = type == SHORTCUT_TYPE_USER_OR_CHAT ? "sdid_" : "bdid_";
|
||||
ShortcutInfoCompat.Builder pinShortcutInfo =
|
||||
new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, idPrefix + dialogId)
|
||||
.setShortLabel(name)
|
||||
.setIntent(shortcutIntent);
|
||||
new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, idPrefix + dialogId)
|
||||
.setShortLabel(name)
|
||||
.setIntent(shortcutIntent);
|
||||
|
||||
if (bitmap != null) {
|
||||
pinShortcutInfo.setIcon(IconCompat.createWithBitmap(bitmap));
|
||||
|
@ -5624,7 +5685,21 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
ShortcutManagerCompat.requestPinShortcut(ApplicationLoader.applicationContext, pinShortcutInfo.build(), null);
|
||||
PendingIntent callbackIntent = null;
|
||||
if (callback != null) {
|
||||
byte[] bytes = new byte[16];
|
||||
Utilities.fastRandom.nextBytes(bytes);
|
||||
final String req_id = Utilities.bytesToHex(bytes);
|
||||
|
||||
final Intent intent = new Intent(ApplicationLoader.applicationContext, ShortcutResultReceiver.class);
|
||||
intent.putExtra("account", currentAccount);
|
||||
intent.putExtra("req_id", req_id);
|
||||
callbackIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
shortcutCallbacks.put(req_id, callback);
|
||||
}
|
||||
|
||||
ShortcutManagerCompat.requestPinShortcut(ApplicationLoader.applicationContext, pinShortcutInfo.build(), callbackIntent == null ? null : callbackIntent.getIntentSender());
|
||||
} else {
|
||||
Intent addIntent = new Intent();
|
||||
if (bitmap != null) {
|
||||
|
@ -5736,12 +5811,7 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
|
||||
public boolean canCreateAttachedMenuBotShortcut(long botId) {
|
||||
for (int i = 0; i < attachMenuBots.bots.size(); i++) {
|
||||
if (attachMenuBots.bots.get(i).bot_id == botId) {
|
||||
return attachMenuBots.bots.get(i).show_in_side_menu && !isShortcutAdded(botId, MediaDataController.SHORTCUT_TYPE_ATTACHED_BOT);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
//---------------- SEARCH END ----------------
|
||||
|
||||
|
@ -7668,10 +7738,14 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
threads.put(threadId, replyToMessage);
|
||||
|
||||
SerializedData serializedData = new SerializedData(replyToMessage.getObjectSize());
|
||||
replyToMessage.serializeToStream(serializedData);
|
||||
editor.putString(threadId == 0 ? ("r_" + dialogId) : ("rt_" + dialogId + "_" + threadId), Utilities.bytesToHex(serializedData.toByteArray()));
|
||||
serializedData.cleanup();
|
||||
try {
|
||||
SerializedData serializedData = new SerializedData(replyToMessage.getObjectSize());
|
||||
replyToMessage.serializeToStream(serializedData);
|
||||
editor.putString(threadId == 0 ? ("r_" + dialogId) : ("rt_" + dialogId + "_" + threadId), Utilities.bytesToHex(serializedData.toByteArray()));
|
||||
serializedData.cleanup();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
editor.commit();
|
||||
if (fromServer && (threadId == 0 || getMessagesController().isForum(dialogId))) {
|
||||
|
|
|
@ -73,12 +73,12 @@ public class MessageCustomParamsHelper {
|
|||
|
||||
private Params_v1(TLRPC.Message message) {
|
||||
this.message = message;
|
||||
flags += message.voiceTranscription != null ? 1 : 0;
|
||||
flags += message.voiceTranscriptionForce ? 2 : 0;
|
||||
flags |= message.voiceTranscription != null ? 1 : 0;
|
||||
flags |= message.voiceTranscriptionForce ? 2 : 0;
|
||||
|
||||
flags += message.originalLanguage != null ? 4 : 0;
|
||||
flags += message.translatedToLanguage != null ? 8 : 0;
|
||||
flags += message.translatedText != null ? 16 : 0;
|
||||
flags |= message.originalLanguage != null ? 4 : 0;
|
||||
flags |= message.translatedToLanguage != null ? 8 : 0;
|
||||
flags |= message.translatedText != null ? 16 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -196,6 +196,7 @@ public class MessageObject {
|
|||
public int audioPlayerDuration;
|
||||
public double attributeDuration;
|
||||
public boolean isDateObject;
|
||||
public boolean isVideoConversionObject;
|
||||
public TLObject photoThumbsObject;
|
||||
public TLObject photoThumbsObject2;
|
||||
public ArrayList<TLRPC.PhotoSize> photoThumbs;
|
||||
|
@ -310,6 +311,7 @@ public class MessageObject {
|
|||
public CharSequence vCardData;
|
||||
|
||||
public ArrayList<String> highlightedWords;
|
||||
public boolean messageTrimmedToHighlightCut = true;
|
||||
public CharSequence messageTrimmedToHighlight;
|
||||
public int parentWidth;
|
||||
|
||||
|
@ -476,6 +478,45 @@ public class MessageObject {
|
|||
return 0;
|
||||
}
|
||||
|
||||
public static int getVideoWidth(TLRPC.Document document) {
|
||||
if (document == null) {
|
||||
return 0;
|
||||
}
|
||||
for (int a = 0, size = document.attributes.size(); a < size; a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
||||
return attribute.w;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getVideoHeight(TLRPC.Document document) {
|
||||
if (document == null) {
|
||||
return 0;
|
||||
}
|
||||
for (int a = 0, size = document.attributes.size(); a < size; a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
||||
return attribute.h;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static String getVideoCodec(TLRPC.Document document) {
|
||||
if (document == null) {
|
||||
return null;
|
||||
}
|
||||
for (int a = 0, size = document.attributes.size(); a < size; a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
||||
return ((TLRPC.TL_documentAttributeVideo) attribute).video_codec;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isWallpaperAction() {
|
||||
return type == TYPE_ACTION_WALLPAPER || (messageOwner != null && messageOwner.action instanceof TLRPC.TL_messageActionSetSameChatWallPaper);
|
||||
}
|
||||
|
@ -2624,19 +2665,30 @@ public class MessageObject {
|
|||
if (getMedia(newMessage) != null && !(getMedia(newMessage) instanceof TLRPC.TL_messageMediaEmpty) && !(getMedia(newMessage) instanceof TLRPC.TL_messageMediaWebPage)/* && TextUtils.isEmpty(newMessage.message)*/) {
|
||||
boolean changedCaption;
|
||||
boolean changedMedia;
|
||||
boolean addedMedia = false;
|
||||
if (!TextUtils.equals(newMessage.message, oldMessage.message)) {
|
||||
changedCaption = true;
|
||||
} else {
|
||||
changedCaption = false;
|
||||
}
|
||||
if (getMedia(newMessage).getClass() != oldMessage.media.getClass() ||
|
||||
getMedia(newMessage).photo != null && oldMessage.media.photo != null && getMedia(newMessage).photo.id != oldMessage.media.photo.id ||
|
||||
getMedia(newMessage).document != null && oldMessage.media.document != null && getMedia(newMessage).document.id != oldMessage.media.document.id) {
|
||||
TLRPC.MessageMedia newMedia = getMedia(newMessage);
|
||||
TLRPC.MessageMedia oldMedia = getMedia(oldMessage);
|
||||
if (oldMedia == null) {
|
||||
addedMedia = true;
|
||||
changedMedia = false;
|
||||
} else if (
|
||||
newMedia.getClass() != oldMedia.getClass() ||
|
||||
newMedia.photo != null && oldMedia.photo != null && newMedia.photo.id != oldMedia.photo.id ||
|
||||
newMedia.document != null && oldMedia.document != null && getMedia(newMessage).document.id != oldMedia.document.id) {
|
||||
addedMedia = false;
|
||||
changedMedia = true;
|
||||
} else {
|
||||
addedMedia = false;
|
||||
changedMedia = false;
|
||||
}
|
||||
if (changedMedia && changedCaption) {
|
||||
if (addedMedia) {
|
||||
messageText = replaceWithLink(getString(R.string.EventLogAddedMedia), "un1", fromUser);
|
||||
} else if (changedMedia && changedCaption) {
|
||||
messageText = replaceWithLink(getString(R.string.EventLogEditedMediaCaption), "un1", fromUser);
|
||||
} else if (changedCaption) {
|
||||
messageText = replaceWithLink(getString(R.string.EventLogEditedCaption), "un1", fromUser);
|
||||
|
@ -5843,6 +5895,9 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public String getFileName() {
|
||||
if (getDocument() != null) {
|
||||
return getFileName(getDocument());
|
||||
}
|
||||
return getFileName(messageOwner);
|
||||
}
|
||||
|
||||
|
@ -6160,7 +6215,7 @@ public class MessageObject {
|
|||
matcher = instagramUrlPattern.matcher(charSequence);
|
||||
} else {
|
||||
if (urlPattern == null) {
|
||||
urlPattern = Pattern.compile("(^|\\s)/[a-zA-Z@\\d_]{1,255}|(^|\\s|\\()@[a-zA-Z\\d_]{1,32}|(^|\\s|\\()#[^0-9][\\w.]+|(^|\\s)\\$[A-Z]{3,8}([ ,.]|$)");
|
||||
urlPattern = Pattern.compile("(^|\\s)/[a-zA-Z@\\d_]{1,255}|(^|\\s|\\()@[a-zA-Z\\d_]{1,32}|(^|\\s|\\()#[^0-9][\\w.]+(@[^0-9][\\w.]+)?|(^|\\s|\\()\\$[^0-9][\\w.]+(@[^0-9][\\w.]+)?|(^|\\s)\\$[A-Z]{3,8}([ ,.]|$)");
|
||||
}
|
||||
matcher = urlPattern.matcher(charSequence);
|
||||
}
|
||||
|
@ -6314,7 +6369,7 @@ public class MessageObject {
|
|||
// only set in searching with tags
|
||||
public boolean isPrimaryGroupMessage;
|
||||
public boolean hasValidGroupId() {
|
||||
return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || sendPreview && (type == TYPE_VIDEO || type == TYPE_PHOTO) || isMusic() || isDocument());
|
||||
return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || type == TYPE_VIDEO || type == TYPE_PHOTO || isMusic() || isDocument());
|
||||
}
|
||||
|
||||
public long getGroupIdForUse() {
|
||||
|
@ -7868,7 +7923,7 @@ public class MessageObject {
|
|||
return isOutOwnerCached;
|
||||
}
|
||||
long selfUserId = UserConfig.getInstance(currentAccount).getClientUserId();
|
||||
if ((isSaved || getDialogId() == selfUserId)) {
|
||||
if (isSaved || getDialogId() == selfUserId) {
|
||||
if (messageOwner.fwd_from != null) {
|
||||
return isOutOwnerCached = messageOwner.fwd_from.from_id != null && messageOwner.fwd_from.from_id.user_id == selfUserId || messageOwner.fwd_from.saved_out;
|
||||
} else {
|
||||
|
@ -7882,10 +7937,6 @@ public class MessageObject {
|
|||
if (messageOwner.fwd_from == null) {
|
||||
return isOutOwnerCached = true;
|
||||
}
|
||||
if (getDialogId() == selfUserId) {
|
||||
return isOutOwnerCached = messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerUser && messageOwner.fwd_from.from_id.user_id == selfUserId && (messageOwner.fwd_from.saved_from_peer == null || messageOwner.fwd_from.saved_from_peer.user_id == selfUserId)
|
||||
|| messageOwner.fwd_from.saved_from_peer != null && messageOwner.fwd_from.saved_from_peer.user_id == selfUserId && (messageOwner.fwd_from.from_id == null || messageOwner.fwd_from.from_id.user_id == selfUserId);
|
||||
}
|
||||
return isOutOwnerCached = messageOwner.fwd_from.saved_from_peer == null || messageOwner.fwd_from.saved_from_peer.user_id == selfUserId;
|
||||
}
|
||||
|
||||
|
@ -8136,6 +8187,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean isFromGroup() {
|
||||
if (messageOwner == null) return false;
|
||||
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null;
|
||||
return messageOwner.from_id instanceof TLRPC.TL_peerChannel && ChatObject.isChannel(chat) && chat.megagroup;
|
||||
}
|
||||
|
@ -8145,7 +8197,11 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean isUnread() {
|
||||
return messageOwner.unread;
|
||||
return messageOwner != null && messageOwner.unread;
|
||||
}
|
||||
|
||||
public boolean isEdited() {
|
||||
return messageOwner != null && (messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 && messageOwner.edit_date != 0 && !messageOwner.edit_hide;
|
||||
}
|
||||
|
||||
public boolean isContentUnread() {
|
||||
|
@ -8156,10 +8212,6 @@ public class MessageObject {
|
|||
messageOwner.unread = false;
|
||||
}
|
||||
|
||||
public int getUnradFlags() {
|
||||
return getUnreadFlags(messageOwner);
|
||||
}
|
||||
|
||||
public static int getUnreadFlags(TLRPC.Message message) {
|
||||
int flags = 0;
|
||||
if (!message.unread) {
|
||||
|
@ -8206,6 +8258,11 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public long getSize() {
|
||||
if (highestQuality != null) {
|
||||
return highestQuality.document.size;
|
||||
} else if (thumbQuality != null) {
|
||||
return thumbQuality.document.size;
|
||||
}
|
||||
return getMessageSize(messageOwner);
|
||||
}
|
||||
|
||||
|
@ -8338,6 +8395,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean canStreamVideo() {
|
||||
if (hasVideoQualities()) return true;
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document == null || document instanceof TLRPC.TL_documentEncrypted) {
|
||||
return false;
|
||||
|
@ -8442,7 +8500,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean isSendError() {
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SEND_ERROR && messageOwner.id < 0 || scheduled && messageOwner.id > 0 && messageOwner.date < ConnectionsManager.getInstance(currentAccount).getCurrentTime() - 60;
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SEND_ERROR && messageOwner.id < 0 || scheduled && messageOwner.id > 0 && messageOwner.date < ConnectionsManager.getInstance(currentAccount).getCurrentTime() - (messageOwner.video_processing_pending ? 5 * 60 : 60);
|
||||
}
|
||||
|
||||
public boolean isSent() {
|
||||
|
@ -8677,6 +8735,9 @@ public class MessageObject {
|
|||
if (emojiAnimatedSticker != null) {
|
||||
return emojiAnimatedSticker;
|
||||
}
|
||||
if (hasVideoQualities() && highestQuality != null) {
|
||||
return highestQuality.document;
|
||||
}
|
||||
return getDocument(messageOwner);
|
||||
}
|
||||
|
||||
|
@ -9619,6 +9680,8 @@ public class MessageObject {
|
|||
return true;
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return !isVoice() && !isSticker() && !isAnimatedSticker() && !isRoundVideo();
|
||||
} else if (isMediaEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -9651,6 +9714,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public static boolean canEditMessageScheduleTime(int currentAccount, TLRPC.Message message, TLRPC.Chat chat) {
|
||||
if (message.video_processing_pending) return false;
|
||||
if (chat == null && message.peer_id.channel_id != 0) {
|
||||
chat = MessagesController.getInstance(currentAccount).getChat(message.peer_id.channel_id);
|
||||
if (chat == null) {
|
||||
|
@ -9966,37 +10030,42 @@ public class MessageObject {
|
|||
mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(photo.video_sizes.get(0), null, true, useFileDatabaseQueue).exists();
|
||||
}
|
||||
}
|
||||
updateQualitiesCached(useFileDatabaseQueue);
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
setQuery(query, true);
|
||||
}
|
||||
public void setQuery(String query, boolean cut) {
|
||||
if (TextUtils.isEmpty(query)) {
|
||||
highlightedWords = null;
|
||||
messageTrimmedToHighlight = null;
|
||||
messageTrimmedToHighlightCut = true;
|
||||
return;
|
||||
}
|
||||
ArrayList<String> foundWords = new ArrayList<>();
|
||||
query = query.trim().toLowerCase();
|
||||
String[] queryWord = query.split("\\P{L}+");
|
||||
String[] queryWord = query.split("[^\\p{L}#$]+");
|
||||
|
||||
ArrayList<String> searchForWords = new ArrayList<>();
|
||||
if (messageOwner.reply_to != null && !TextUtils.isEmpty(messageOwner.reply_to.quote_text)) {
|
||||
String message = messageOwner.reply_to.quote_text.trim().toLowerCase();
|
||||
if (message.contains(query) && !foundWords.contains(query)) {
|
||||
foundWords.add(query);
|
||||
handleFoundWords(foundWords, queryWord, true);
|
||||
handleFoundWords(foundWords, queryWord, true, cut);
|
||||
return;
|
||||
}
|
||||
String[] words = message.split("\\P{L}+");
|
||||
String[] words = message.split("[^\\p{L}#$]+");
|
||||
searchForWords.addAll(Arrays.asList(words));
|
||||
}
|
||||
if (!TextUtils.isEmpty(messageOwner.message)) {
|
||||
String message = messageOwner.message.trim().toLowerCase();
|
||||
if (message.contains(query) && !foundWords.contains(query)) {
|
||||
foundWords.add(query);
|
||||
handleFoundWords(foundWords, queryWord, false);
|
||||
handleFoundWords(foundWords, queryWord, false, cut);
|
||||
return;
|
||||
}
|
||||
String[] words = message.split("\\P{L}+");
|
||||
String[] words = message.split("[^\\p{L}#$]+");
|
||||
searchForWords.addAll(Arrays.asList(words));
|
||||
}
|
||||
if (getDocument() != null) {
|
||||
|
@ -10004,7 +10073,7 @@ public class MessageObject {
|
|||
if (fileName.contains(query) && !foundWords.contains(query)) {
|
||||
foundWords.add(query);
|
||||
}
|
||||
String[] words = fileName.split("\\P{L}+");
|
||||
String[] words = fileName.split("[^\\p{L}#$]+");
|
||||
searchForWords.addAll(Arrays.asList(words));
|
||||
}
|
||||
|
||||
|
@ -10019,7 +10088,7 @@ public class MessageObject {
|
|||
if (title.contains(query) && !foundWords.contains(query)) {
|
||||
foundWords.add(query);
|
||||
}
|
||||
String[] words = title.split("\\P{L}+");
|
||||
String[] words = title.split("[^\\p{L}#$]+");
|
||||
searchForWords.addAll(Arrays.asList(words));
|
||||
}
|
||||
}
|
||||
|
@ -10030,7 +10099,7 @@ public class MessageObject {
|
|||
if (musicAuthor.contains(query) && !foundWords.contains(query)) {
|
||||
foundWords.add(query);
|
||||
}
|
||||
String[] words = musicAuthor.split("\\P{L}+");
|
||||
String[] words = musicAuthor.split("[^\\p{L}#$]+");
|
||||
searchForWords.addAll(Arrays.asList(words));
|
||||
}
|
||||
for (int k = 0; k < queryWord.length; k++) {
|
||||
|
@ -10065,10 +10134,13 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
handleFoundWords(foundWords, queryWord, false);
|
||||
handleFoundWords(foundWords, queryWord, false, cut);
|
||||
}
|
||||
|
||||
private void handleFoundWords(ArrayList<String> foundWords, String[] queryWord, boolean inQuote) {
|
||||
handleFoundWords(foundWords, queryWord, inQuote, true);
|
||||
}
|
||||
private void handleFoundWords(ArrayList<String> foundWords, String[] queryWord, boolean inQuote, boolean cut) {
|
||||
if (!foundWords.isEmpty()) {
|
||||
boolean foundExactly = false;
|
||||
for (int i = 0; i < foundWords.size(); i++) {
|
||||
|
@ -10128,11 +10200,12 @@ public class MessageObject {
|
|||
if (startHighlightedIndex < 0) {
|
||||
startHighlightedIndex = 0;
|
||||
}
|
||||
if (lastIndex > maxSymbols) {
|
||||
if (lastIndex > maxSymbols && cut) {
|
||||
int newStart = Math.max(0, startHighlightedIndex - (int) (maxSymbols * .1f));
|
||||
charSequence = charSequence.subSequence(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + (int) (maxSymbols * .9f)));
|
||||
}
|
||||
messageTrimmedToHighlight = charSequence;
|
||||
messageTrimmedToHighlightCut = cut;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11031,11 +11104,21 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
private Boolean videoQualitiesCached;
|
||||
public ArrayList<VideoPlayer.Quality> videoQualities;
|
||||
public TLRPC.Document qualityToSave;
|
||||
|
||||
public VideoPlayer.VideoUri highestQuality, thumbQuality;
|
||||
|
||||
public boolean hasVideoQualities() {
|
||||
if (videoQualitiesCached == null) {
|
||||
try {
|
||||
videoQualitiesCached = messageOwner != null && VideoPlayer.hasQualities(currentAccount, messageOwner.media);
|
||||
if (messageOwner == null || messageOwner.media == null || messageOwner.media.document == null || messageOwner.media.alt_documents.isEmpty()) {
|
||||
return videoQualitiesCached = false;
|
||||
}
|
||||
videoQualities = VideoPlayer.getQualities(currentAccount, messageOwner != null ? messageOwner.media : null);
|
||||
videoQualitiesCached = videoQualities != null && videoQualities.size() > 1;
|
||||
highestQuality = VideoPlayer.getQualityForPlayer(videoQualities);
|
||||
thumbQuality = VideoPlayer.getQualityForThumb(videoQualities);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
videoQualitiesCached = false;
|
||||
|
@ -11047,4 +11130,21 @@ public class MessageObject {
|
|||
public boolean isStarGiftAction() {
|
||||
return messageOwner != null && messageOwner.action instanceof TLRPC.TL_messageActionStarGift;
|
||||
}
|
||||
|
||||
public boolean mediaExists() {
|
||||
if (hasVideoQualities() && highestQuality != null) {
|
||||
return highestQuality.isCached();
|
||||
}
|
||||
return mediaExists;
|
||||
}
|
||||
|
||||
public void updateQualitiesCached(boolean useFileDatabaseQueue) {
|
||||
if (videoQualities == null) return;
|
||||
for (VideoPlayer.Quality q : videoQualities) {
|
||||
for (VideoPlayer.VideoUri u : q.uris) {
|
||||
u.updateCached(useFileDatabaseQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -697,6 +697,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
public int stargiftsMessageLengthMax;
|
||||
public int stargiftsConvertPeriodMax;
|
||||
public boolean videoIgnoreAltDocuments;
|
||||
public boolean disableBotFullscreenBlur;
|
||||
|
||||
public int checkResetLangpack;
|
||||
public boolean folderTags;
|
||||
|
@ -965,7 +966,6 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
public Integer posts_between;
|
||||
public long loadTime;
|
||||
public boolean loading;
|
||||
public boolean faked;
|
||||
}
|
||||
|
||||
private class SendAsPeersInfo {
|
||||
|
@ -1553,6 +1553,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
stargiftsMessageLengthMax = mainPreferences.getInt("stargiftsMessageLengthMax", 255);
|
||||
stargiftsConvertPeriodMax = mainPreferences.getInt("stargiftsConvertPeriodMax", isTest ? 300 : 90 * 86400);
|
||||
videoIgnoreAltDocuments = mainPreferences.getBoolean("videoIgnoreAltDocuments", false);
|
||||
disableBotFullscreenBlur = mainPreferences.getBoolean("disableBotFullscreenBlur", false);
|
||||
storiesPosting = mainPreferences.getString("storiesPosting", "enabled");
|
||||
storiesEntities = mainPreferences.getString("storiesEntities", "premium");
|
||||
storiesExportNopublicLink = mainPreferences.getBoolean("storiesExportNopublicLink", false);
|
||||
|
@ -2381,7 +2382,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
private Runnable loadAppConfigRunnable = this::loadAppConfig;
|
||||
|
||||
public void loadAppConfig() {
|
||||
loadAppConfig(false);
|
||||
loadAppConfig(true);
|
||||
}
|
||||
|
||||
public void loadAppConfig(boolean force) {
|
||||
|
@ -3738,6 +3739,17 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "bot_fullscreen_blur_disable": {
|
||||
if (value.value instanceof TLRPC.TL_jsonBool) {
|
||||
TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value;
|
||||
if (bool.value != disableBotFullscreenBlur) {
|
||||
disableBotFullscreenBlur = bool.value;
|
||||
editor.putBoolean("disableBotFullscreenBlur", disableBotFullscreenBlur);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "stories_posting": {
|
||||
if (value.value instanceof TLRPC.TL_jsonString) {
|
||||
TLRPC.TL_jsonString str = (TLRPC.TL_jsonString) value.value;
|
||||
|
@ -4929,7 +4941,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
canEditFactcheck = false;
|
||||
starsLocked = true;
|
||||
factcheckLengthLimit = 1024;
|
||||
mainPreferences.edit().remove("starsLocked").remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").remove("canEditFactcheck").remove("factcheckLengthLimit").apply();
|
||||
videoIgnoreAltDocuments = false;
|
||||
mainPreferences.edit().remove("starsLocked").remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").remove("canEditFactcheck").remove("factcheckLengthLimit").remove("videoIgnoreAltDocuments").apply();
|
||||
}
|
||||
|
||||
private boolean savePremiumFeaturesPreviewOrder(String key, SparseIntArray array, SharedPreferences.Editor editor, ArrayList<TLRPC.JSONValue> value) {
|
||||
|
@ -8320,6 +8333,10 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
public void deleteMessages(ArrayList<Integer> messages, ArrayList<Long> randoms, TLRPC.EncryptedChat encryptedChat, long dialogId, boolean forAll, int mode, boolean cacheOnly, long taskId, TLObject taskRequest, int topicId) {
|
||||
deleteMessages(messages, randoms, encryptedChat, dialogId, forAll, mode, cacheOnly, taskId, taskRequest, topicId, false, 0);
|
||||
}
|
||||
|
||||
public void deleteMessages(ArrayList<Integer> messages, ArrayList<Long> randoms, TLRPC.EncryptedChat encryptedChat, long dialogId, boolean forAll, int mode, boolean cacheOnly, long taskId, TLObject taskRequest, int topicId, boolean movedToScheduled, int movedToScheduledMessageId) {
|
||||
final boolean scheduled = mode == ChatActivity.MODE_SCHEDULED;
|
||||
final boolean quickReplies = mode == ChatActivity.MODE_QUICK_REPLIES;
|
||||
if ((messages == null || messages.isEmpty()) && taskId == 0) {
|
||||
|
@ -8365,7 +8382,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
getMessagesStorage().markMessagesAsDeleted(dialogId, messages, true, forAll, 0, topicId);
|
||||
getMessagesStorage().updateDialogsWithDeletedMessages(dialogId, channelId, messages, null, true);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, channelId, scheduled);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, channelId, scheduled, false, movedToScheduled, movedToScheduledMessageId);
|
||||
} else {
|
||||
if (taskRequest instanceof TLRPC.TL_channels_deleteMessages) {
|
||||
channelId = ((TLRPC.TL_channels_deleteMessages) taskRequest).channel.channel_id;
|
||||
|
@ -10816,6 +10833,14 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
});
|
||||
}
|
||||
|
||||
public void forceNoReload(long dialogId, int mode) {
|
||||
if (mode == ChatActivity.MODE_SCHEDULED) {
|
||||
lastScheduledServerQueryTime.put(dialogId, SystemClock.elapsedRealtime());
|
||||
} else if (mode == ChatActivity.MODE_DEFAULT) {
|
||||
lastServerQueryTime.put(dialogId, SystemClock.elapsedRealtime());
|
||||
}
|
||||
}
|
||||
|
||||
public void loadHintDialogs() {
|
||||
if (!hintDialogs.isEmpty() || TextUtils.isEmpty(installReferer)) {
|
||||
return;
|
||||
|
@ -16648,6 +16673,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
LongSparseArray<ArrayList<Integer>> deletedMessages = null;
|
||||
LongSparseArray<ArrayList<Integer>> deletedQuickReplyMessages = null;
|
||||
LongSparseArray<ArrayList<Integer>> scheduledDeletedMessages = null;
|
||||
LongSparseArray<ArrayList<Integer>> scheduledDeletedMessagesSent = null;
|
||||
LongSparseArray<ArrayList<Long>> groupSpeakingActions = null;
|
||||
LongSparseIntArray importingActions = null;
|
||||
LongSparseIntArray clearHistoryMessages = null;
|
||||
|
@ -16994,12 +17020,24 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
scheduledDeletedMessages = new LongSparseArray<>();
|
||||
}
|
||||
long id = MessageObject.getPeerId(update.peer);
|
||||
ArrayList<Integer> arrayList = scheduledDeletedMessages.get(MessageObject.getPeerId(update.peer));
|
||||
ArrayList<Integer> arrayList = scheduledDeletedMessages.get(id);
|
||||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
scheduledDeletedMessages.put(id, arrayList);
|
||||
}
|
||||
arrayList.addAll(update.messages);
|
||||
|
||||
if (!update.sent_messages.isEmpty()) {
|
||||
if (scheduledDeletedMessagesSent == null) {
|
||||
scheduledDeletedMessagesSent = new LongSparseArray<>();
|
||||
}
|
||||
ArrayList<Integer> arrayList2 = scheduledDeletedMessagesSent.get(id);
|
||||
if (arrayList2 == null) {
|
||||
arrayList2 = new ArrayList<>();
|
||||
scheduledDeletedMessagesSent.put(id, arrayList2);
|
||||
}
|
||||
arrayList2.addAll(update.sent_messages);
|
||||
}
|
||||
} else if (baseUpdate instanceof TLRPC.TL_updateUserTyping || baseUpdate instanceof TLRPC.TL_updateChatUserTyping || baseUpdate instanceof TLRPC.TL_updateChannelUserTyping) {
|
||||
long userId;
|
||||
long chatId;
|
||||
|
@ -17891,6 +17929,10 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_VOICE_MESSAGES);
|
||||
} else if (update.key instanceof TLRPC.TL_privacyKeyAbout) {
|
||||
getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_BIO);
|
||||
} else if (update.key instanceof TLRPC.TL_privacyKeyBirthday) {
|
||||
getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_BIRTHDAY);
|
||||
} else if (update.key instanceof TLRPC.TL_privacyKeyStarGiftsAutoSave) {
|
||||
getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_GIFTS);
|
||||
}
|
||||
} else if (baseUpdate instanceof TLRPC.TL_updateStarsRevenueStatus) {
|
||||
BotStarsController.getInstance(currentAccount).onUpdate((TLRPC.TL_updateStarsRevenueStatus) baseUpdate);
|
||||
|
@ -18483,7 +18525,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
svc.onCallUpdated(call);
|
||||
} else {
|
||||
if (call instanceof TLRPC.TL_phoneCallDiscarded) {
|
||||
VoIPPreNotificationService.dismiss(ApplicationLoader.applicationContext);
|
||||
VoIPPreNotificationService.dismiss(ApplicationLoader.applicationContext, false);
|
||||
}
|
||||
if (VoIPService.callIShouldHavePutIntoIntent != null) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
|
@ -18885,6 +18927,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
LongSparseArray<ArrayList<Integer>> deletedMessagesFinal = deletedMessages;
|
||||
LongSparseArray<ArrayList<Integer>> deletedQuickRepliesMessagesFinal = deletedQuickReplyMessages;
|
||||
LongSparseArray<ArrayList<Integer>> scheduledDeletedMessagesFinal = scheduledDeletedMessages;
|
||||
LongSparseArray<ArrayList<Integer>> scheduledDeletedMessagesSentFinal = scheduledDeletedMessagesSent;
|
||||
LongSparseIntArray clearHistoryMessagesFinal = clearHistoryMessages;
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> {
|
||||
int updateMask = 0;
|
||||
|
@ -19023,8 +19066,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
if (arrayList == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, arrayList, DialogObject.isChatDialog(key) && ChatObject.isChannel(getChat(-key)) ? -key : 0, true);
|
||||
ArrayList<Integer> sentMessageIds = scheduledDeletedMessagesSentFinal != null ? scheduledDeletedMessagesSentFinal.get(key) : null;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, arrayList, DialogObject.isChatDialog(key) && ChatObject.isChannel(getChat(-key)) ? -key : 0, true, false, false, 0, sentMessageIds);
|
||||
}
|
||||
}
|
||||
if (clearHistoryMessagesFinal != null) {
|
||||
|
@ -19315,36 +19358,19 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
public SponsoredMessagesInfo getSponsoredMessages(long dialogId) {
|
||||
// for (int i = 0; i < sponsoredMessages.size(); ++i) {
|
||||
// if (sponsoredMessages.valueAt(i).messages != null && !sponsoredMessages.valueAt(i).messages.isEmpty()) {
|
||||
// SponsoredMessagesInfo info = sponsoredMessages.valueAt(i);
|
||||
// if (info.faked) {
|
||||
// return info;
|
||||
// }
|
||||
// info.loading = true;
|
||||
// info.faked = true;
|
||||
// AndroidUtilities.runOnUIThread(() -> {
|
||||
// info.loading = false;
|
||||
// getNotificationCenter().postNotificationName(NotificationCenter.didLoadSponsoredMessages, dialogId, info.messages);
|
||||
// AndroidUtilities.runOnUIThread(() -> { info.faked = false; }, 500);
|
||||
// }, 1500);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
SponsoredMessagesInfo info = sponsoredMessages.get(dialogId);
|
||||
if (info != null && (info.loading || Math.abs(SystemClock.elapsedRealtime() - info.loadTime) <= 5 * 60 * 1000)) {
|
||||
return info;
|
||||
}
|
||||
TLRPC.Chat chat = getChat(-dialogId);
|
||||
if (!ChatObject.isChannel(chat)) {
|
||||
if (dialogId < 0 ? !ChatObject.isChannel(getChat(-dialogId)) : !UserObject.isBot(getUser(dialogId))) {
|
||||
return null;
|
||||
}
|
||||
info = new SponsoredMessagesInfo();
|
||||
info.loading = true;
|
||||
sponsoredMessages.put(dialogId, info);
|
||||
SponsoredMessagesInfo infoFinal = info;
|
||||
TLRPC.TL_channels_getSponsoredMessages req = new TLRPC.TL_channels_getSponsoredMessages();
|
||||
req.channel = getInputChannel(chat);
|
||||
TLRPC.TL_messages_getSponsoredMessages req = new TLRPC.TL_messages_getSponsoredMessages();
|
||||
req.peer = getInputPeer(dialogId);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
ArrayList<MessageObject> result;
|
||||
Integer posts_between;
|
||||
|
@ -21918,6 +21944,9 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
openApp(null, bot, null, classGuid, null);
|
||||
}
|
||||
public void openApp(BaseFragment _fragment, TLRPC.User bot, String param, int classGuid, Browser.Progress progress) {
|
||||
openApp(_fragment, bot, param, classGuid, progress, false, false);
|
||||
}
|
||||
public void openApp(BaseFragment _fragment, TLRPC.User bot, String param, int classGuid, Browser.Progress progress, boolean botCompact, boolean botFullscreen) {
|
||||
if (bot == null) return;
|
||||
|
||||
boolean[] cancelled = new boolean[] { false };
|
||||
|
@ -21939,50 +21968,50 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
fragment = ((ActionBarLayout) fragment.getParentLayout()).getSheetFragment();
|
||||
}
|
||||
AndroidUtilities.hideKeyboard(fragment.getFragmentView());
|
||||
WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, null, null, BotWebViewAttachedSheet.TYPE_WEB_VIEW_BOT_MAIN, 0, false, null, false, param, bot, 0, false);
|
||||
WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, null, null, BotWebViewAttachedSheet.TYPE_WEB_VIEW_BOT_MAIN, 0, false, null, false, param, bot, 0, botCompact, botFullscreen);
|
||||
if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(props) != null) {
|
||||
return;
|
||||
}
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
// if (AndroidUtilities.isTablet() || true) {
|
||||
BotWebViewSheet webViewSheet = new BotWebViewSheet(fragment.getContext(), fragment.getResourceProvider());
|
||||
webViewSheet.setDefaultFullsize(true);
|
||||
webViewSheet.setNeedsContext(true);
|
||||
webViewSheet.setNeedsContext(false);
|
||||
webViewSheet.setParentActivity(fragment.getParentActivity());
|
||||
webViewSheet.requestWebView(fragment, props);
|
||||
webViewSheet.show();
|
||||
} else {
|
||||
BotWebViewAttachedSheet sheet = fragment.createBotViewer();
|
||||
sheet.setDefaultFullsize(true);
|
||||
sheet.setNeedsContext(false);
|
||||
sheet.setParentActivity(fragment.getParentActivity());
|
||||
sheet.requestWebView(fragment, props);
|
||||
sheet.show();
|
||||
}
|
||||
// } else {
|
||||
// BotWebViewAttachedSheet sheet = fragment.createBotViewer();
|
||||
// sheet.setDefaultFullsize(true);
|
||||
// sheet.setNeedsContext(false);
|
||||
// sheet.setParentActivity(fragment.getParentActivity());
|
||||
// sheet.requestWebView(fragment, props);
|
||||
// sheet.show();
|
||||
// }
|
||||
} else if (botInfo[0] != null && botInfo[0].menu_button instanceof TL_bots.TL_botMenuButton) {
|
||||
if (fragment.getParentLayout() instanceof ActionBarLayout) {
|
||||
fragment = ((ActionBarLayout) fragment.getParentLayout()).getSheetFragment();
|
||||
}
|
||||
TL_bots.TL_botMenuButton btn = (TL_bots.TL_botMenuButton) botInfo[0].menu_button;
|
||||
AndroidUtilities.hideKeyboard(fragment.getFragmentView());
|
||||
WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, btn.text, btn.url, BotWebViewAttachedSheet.TYPE_BOT_MENU_BUTTON, 0, false, null, false, param, bot, 0, false);
|
||||
WebViewRequestProps props = WebViewRequestProps.of(currentAccount, bot.id, bot.id, btn.text, btn.url, BotWebViewAttachedSheet.TYPE_BOT_MENU_BUTTON, 0, false, null, false, param, bot, 0, botCompact, botFullscreen);
|
||||
if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(props) != null) {
|
||||
return;
|
||||
}
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
// if (AndroidUtilities.isTablet() || true) {
|
||||
BotWebViewSheet webViewSheet = new BotWebViewSheet(fragment.getContext(), fragment.getResourceProvider());
|
||||
webViewSheet.setDefaultFullsize(false);
|
||||
webViewSheet.setNeedsContext(true);
|
||||
webViewSheet.setParentActivity(fragment.getParentActivity());
|
||||
webViewSheet.requestWebView(fragment, props);
|
||||
webViewSheet.show();
|
||||
} else {
|
||||
BotWebViewAttachedSheet sheet = fragment.createBotViewer();
|
||||
sheet.setDefaultFullsize(false);
|
||||
sheet.setNeedsContext(false);
|
||||
sheet.setParentActivity(fragment.getParentActivity());
|
||||
sheet.requestWebView(fragment, props);
|
||||
sheet.show();
|
||||
}
|
||||
// } else {
|
||||
// BotWebViewAttachedSheet sheet = fragment.createBotViewer();
|
||||
// sheet.setDefaultFullsize(false);
|
||||
// sheet.setNeedsContext(false);
|
||||
// sheet.setParentActivity(fragment.getParentActivity());
|
||||
// sheet.requestWebView(fragment, props);
|
||||
// sheet.show();
|
||||
// }
|
||||
} else {
|
||||
fragment.presentFragment(ChatActivity.of(bot.id));
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.telegram.ui.ActionBar.Theme;
|
|||
import org.telegram.ui.Adapters.DialogsSearchAdapter;
|
||||
import org.telegram.ui.ChatActivity;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
|
||||
import org.telegram.ui.Components.VideoPlayer;
|
||||
import org.telegram.ui.DialogsActivity;
|
||||
import org.telegram.ui.EditWidgetActivity;
|
||||
|
||||
|
@ -11927,12 +11928,20 @@ public class MessagesStorage extends BaseController {
|
|||
}
|
||||
data.reuse();
|
||||
|
||||
if (downloadMask != 0 && (message.peer_id.channel_id == 0 || message.post) && message.date >= getConnectionsManager().getCurrentTime() - 60 * 60 && getDownloadController().canDownloadMedia(message) == 1) {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
if (downloadMask != 0 && (message.peer_id.channel_id == 0 || message.post) && message.date >= getConnectionsManager().getCurrentTime() - 15 * 60 && getDownloadController().canDownloadMedia(message) == 1) {
|
||||
final long dialogId = MessageObject.getDialogId(message);
|
||||
if (getDialogFolderIdInternal(dialogId) != 1 && (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaWebPage)) {
|
||||
int type = 0;
|
||||
long id = 0;
|
||||
TLRPC.MessageMedia object = null;
|
||||
TLRPC.Document document = MessageObject.getDocument(message);
|
||||
ArrayList<VideoPlayer.Quality> qualities = VideoPlayer.getQualities(currentAccount, message.media);
|
||||
if (qualities != null) {
|
||||
VideoPlayer.VideoUri v = VideoPlayer.getQualityForThumb(qualities);
|
||||
if (v != null) {
|
||||
document = v.document;
|
||||
}
|
||||
}
|
||||
TLRPC.Photo photo = MessageObject.getPhoto(message);
|
||||
if (MessageObject.isVoiceMessage(message)) {
|
||||
id = document.id;
|
||||
|
@ -16097,6 +16106,32 @@ public class MessagesStorage extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private int getDialogFolderIdInternal(long dialogId) {
|
||||
SQLiteCursor cursor = null;
|
||||
try {
|
||||
int folderId;
|
||||
if (unknownDialogsIds.get(dialogId) != null) {
|
||||
folderId = -1;
|
||||
} else {
|
||||
cursor = database.queryFinalized("SELECT folder_id FROM dialogs WHERE did = ?", dialogId);
|
||||
if (cursor.next()) {
|
||||
folderId = cursor.intValue(0);
|
||||
} else {
|
||||
folderId = -1;
|
||||
}
|
||||
cursor.dispose();
|
||||
}
|
||||
return folderId;
|
||||
} catch (Exception e) {
|
||||
checkSQLException(e);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.dispose();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void getDialogFolderId(long dialogId, IntCallback callback) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
SQLiteCursor cursor = null;
|
||||
|
|
|
@ -146,24 +146,18 @@ public class NotificationCenter {
|
|||
public static final int quickRepliesDeleted = totalEvents++;
|
||||
public static final int bookmarkAdded = totalEvents++;
|
||||
public static final int starReactionAnonymousUpdate = totalEvents++;
|
||||
|
||||
public static final int businessLinksUpdated = totalEvents++;
|
||||
public static final int businessLinkCreated = totalEvents++;
|
||||
public static final int needDeleteBusinessLink = totalEvents++;
|
||||
|
||||
public static final int messageTranslated = totalEvents++;
|
||||
public static final int messageTranslating = totalEvents++;
|
||||
public static final int dialogIsTranslatable = totalEvents++;
|
||||
public static final int dialogTranslate = totalEvents++;
|
||||
|
||||
public static final int didGenerateFingerprintKeyPair = totalEvents++;
|
||||
|
||||
public static final int walletPendingTransactionsChanged = totalEvents++;
|
||||
public static final int walletSyncProgressChanged = totalEvents++;
|
||||
|
||||
public static final int httpFileDidLoad = totalEvents++;
|
||||
public static final int httpFileDidFailedLoad = totalEvents++;
|
||||
|
||||
public static final int didUpdateConnectionState = totalEvents++;
|
||||
|
||||
public static final int fileUploaded = totalEvents++;
|
||||
|
@ -267,6 +261,8 @@ public class NotificationCenter {
|
|||
public static final int starGiftsLoaded = totalEvents++;
|
||||
public static final int starUserGiftsLoaded = totalEvents++;
|
||||
public static final int starGiftSoldOut = totalEvents++;
|
||||
public static final int updateStories = totalEvents++;
|
||||
public static final int botDownloadsUpdate = totalEvents++;
|
||||
|
||||
//global
|
||||
public static final int pushMessagesUpdated = totalEvents++;
|
||||
|
|
|
@ -2179,6 +2179,8 @@ public class NotificationsController extends BaseController {
|
|||
peername = peerchat == null ? "" : peerchat.title;
|
||||
}
|
||||
return LocaleController.formatPluralStringComma("BoostingReceivedStars", (int) action.stars, peername);
|
||||
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentRefunded) {
|
||||
return messageObject.messageText.toString();
|
||||
}
|
||||
} else {
|
||||
if (messageObject.isMediaEmpty()) {
|
||||
|
@ -4071,7 +4073,7 @@ public class NotificationsController extends BaseController {
|
|||
return;
|
||||
}
|
||||
if (replace) {
|
||||
if (chat != null) {
|
||||
if (chat != null && allowSummary) {
|
||||
message = message.replace(" @ " + name, "");
|
||||
} else {
|
||||
if (text[0]) {
|
||||
|
|
|
@ -152,7 +152,6 @@ public class PushListenerController {
|
|||
buffer.readBytes(strBytes, true);
|
||||
jsonString = new String(strBytes);
|
||||
JSONObject json = new JSONObject(jsonString);
|
||||
// FileLog.d("FCM DATA: " + jsonString);
|
||||
|
||||
if (ApplicationLoader.applicationLoaderInstance != null && ApplicationLoader.applicationLoaderInstance.consumePush(currentAccount, json)) {
|
||||
countDownLatch.countDown();
|
||||
|
|
|
@ -2321,7 +2321,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.Update update = updates.updates.get(a1);
|
||||
if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateNewChannelMessage || update instanceof TLRPC.TL_updateNewScheduledMessage || update instanceof TLRPC.TL_updateQuickReplyMessage) {
|
||||
|
||||
boolean currentSchedule = scheduleDate != 0;
|
||||
boolean currentSchedule = false;
|
||||
boolean scheduled = scheduleDate != 0;
|
||||
|
||||
updates.updates.remove(a1);
|
||||
a1--;
|
||||
|
@ -2330,9 +2331,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_updateNewMessage updateNewMessage = (TLRPC.TL_updateNewMessage) update;
|
||||
message = updateNewMessage.message;
|
||||
getMessagesController().processNewDifferenceParams(-1, updateNewMessage.pts, -1, updateNewMessage.pts_count);
|
||||
currentSchedule = false;
|
||||
} else if (update instanceof TLRPC.TL_updateNewScheduledMessage) {
|
||||
TLRPC.TL_updateNewScheduledMessage updateNewMessage = (TLRPC.TL_updateNewScheduledMessage) update;
|
||||
message = updateNewMessage.message;
|
||||
currentSchedule = true;
|
||||
} else if (update instanceof TLRPC.TL_updateQuickReplyMessage) {
|
||||
QuickRepliesController.getInstance(currentAccount).processUpdate(update, null, 0);
|
||||
TLRPC.TL_updateQuickReplyMessage updateQuickReplyMessage = (TLRPC.TL_updateQuickReplyMessage) update;
|
||||
|
@ -2341,6 +2344,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_updateNewChannelMessage updateNewChannelMessage = (TLRPC.TL_updateNewChannelMessage) update;
|
||||
message = updateNewChannelMessage.message;
|
||||
getMessagesController().processNewChannelDifferenceParams(updateNewChannelMessage.pts, updateNewChannelMessage.pts_count, message.peer_id.channel_id);
|
||||
currentSchedule = false;
|
||||
}
|
||||
if (scheduledOnline && message.date != 0x7FFFFFFE) {
|
||||
currentSchedule = false;
|
||||
|
@ -2380,17 +2384,19 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
newMsgObj1.id = message.id;
|
||||
sentCount++;
|
||||
|
||||
if (scheduleDate != 0 && !currentSchedule) {
|
||||
if (scheduled != currentSchedule) {
|
||||
final int fromMode = scheduled ? ChatActivity.MODE_SCHEDULED : 0;
|
||||
final int toMode = currentSchedule ? ChatActivity.MODE_SCHEDULED : 0;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<Integer> messageIds = new ArrayList<>();
|
||||
messageIds.add(oldId);
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj1.dialog_id, newMsgObj1.quick_reply_shortcut_id, false, ChatActivity.MODE_SCHEDULED);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, 0, 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, toMode, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<Integer> messageIds = new ArrayList<>();
|
||||
messageIds.add(oldId);
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj1.dialog_id, false, fromMode, false, 0, null, 0, toMode == ChatActivity.MODE_SCHEDULED, message.id);
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
messageObjects.add(new MessageObject(msgObj.currentAccount, msgObj.messageOwner, true, true));
|
||||
getMessagesController().updateInterfaceWithMessages(newMsgObj1.dialog_id, messageObjects, 0);
|
||||
getMessagesController().updateInterfaceWithMessages(newMsgObj1.dialog_id, messageObjects, toMode);
|
||||
getMediaDataController().increasePeerRaiting(newMsgObj1.dialog_id);
|
||||
processSentMessage(oldId);
|
||||
removeFromSendingMessages(oldId, scheduleDate != 0);
|
||||
|
@ -2851,6 +2857,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
delayedMessage.performMediaUpload = performMediaUpload;
|
||||
}
|
||||
}
|
||||
if (inputMedia instanceof TLRPC.TL_inputMediaEmpty && (messageObject.type == MessageObject.TYPE_TEXT || messageObject.type == MessageObject.TYPE_EMOJIS)) {
|
||||
inputMedia = null;
|
||||
}
|
||||
|
||||
TLObject reqSend;
|
||||
|
||||
|
@ -2861,6 +2870,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
if (inputMedia != null) {
|
||||
request.flags |= 16384;
|
||||
request.media = inputMedia;
|
||||
} else if (!messageObject.editingMessageSearchWebPage) {
|
||||
request.no_webpage = true;
|
||||
}
|
||||
if (messageObject.scheduled) {
|
||||
request.schedule_date = messageObject.messageOwner.date;
|
||||
|
@ -6094,6 +6105,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
final TLRPC.Updates updates = (TLRPC.Updates) response;
|
||||
ArrayList<TLRPC.Update> updatesArr = ((TLRPC.Updates) response).updates;
|
||||
LongSparseArray<SparseArray<TLRPC.MessageReplies>> channelReplies = null;
|
||||
boolean currentSchedule = scheduled;
|
||||
for (int a = 0; a < updatesArr.size(); a++) {
|
||||
TLRPC.Update update = updatesArr.get(a);
|
||||
if (update instanceof TLRPC.TL_updateMessageID) {
|
||||
|
@ -6102,6 +6114,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
updatesArr.remove(a);
|
||||
a--;
|
||||
} else if (update instanceof TLRPC.TL_updateNewMessage) {
|
||||
currentSchedule = false;
|
||||
final TLRPC.TL_updateNewMessage newMessage = (TLRPC.TL_updateNewMessage) update;
|
||||
newMessages.put(newMessage.message.id, newMessage.message);
|
||||
Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewDifferenceParams(-1, newMessage.pts, -1, newMessage.pts_count));
|
||||
|
@ -6145,11 +6158,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
});
|
||||
}
|
||||
} else if (update instanceof TLRPC.TL_updateNewScheduledMessage) {
|
||||
currentSchedule = true;
|
||||
final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update;
|
||||
newMessages.put(newMessage.message.id, newMessage.message);
|
||||
updatesArr.remove(a);
|
||||
a--;
|
||||
} else if (update instanceof TLRPC.TL_updateQuickReplyMessage) {
|
||||
currentSchedule = false;
|
||||
QuickRepliesController.getInstance(currentAccount).processUpdate(update, msgObjs.isEmpty() ? null : msgObjs.get(0).getQuickReplyName(), msgObjs.isEmpty() ? null : msgObjs.get(0).getQuickReplyId());
|
||||
final TLRPC.TL_updateQuickReplyMessage newMessage = (TLRPC.TL_updateQuickReplyMessage) update;
|
||||
newMessages.put(newMessage.message.id, newMessage.message);
|
||||
|
@ -6162,6 +6177,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.didUpdateMessagesViews, null, null, channelReplies, true);
|
||||
}
|
||||
|
||||
final int[] totalSent = new int[1];
|
||||
final int[] done = new int[1];
|
||||
totalSent[0] = 0;
|
||||
done[0] = 0;
|
||||
final ArrayList<Integer> oldIds = new ArrayList<>();
|
||||
for (int i = 0; i < msgObjs.size(); i++) {
|
||||
final MessageObject msgObj = msgObjs.get(i);
|
||||
final String originalPath = originalPaths.get(i);
|
||||
|
@ -6212,22 +6232,31 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
break;
|
||||
}
|
||||
|
||||
final boolean finalCurrentSchedule = currentSchedule;
|
||||
if (!isSentError) {
|
||||
totalSent[0]++;
|
||||
oldIds.add(oldId);
|
||||
getStatsController().incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1);
|
||||
newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, currentSchedule);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, currentSchedule);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
int mode = scheduled ? ChatActivity.MODE_SCHEDULED : 0;
|
||||
int mode = finalCurrentSchedule ? ChatActivity.MODE_SCHEDULED : 0;
|
||||
if (newMsgObj.quick_reply_shortcut_id != 0 || newMsgObj.quick_reply_shortcut != null) {
|
||||
mode = ChatActivity.MODE_QUICK_REPLIES;
|
||||
}
|
||||
getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, MessageObject.getPeerId(newMsgObj.peer_id), oldId, newMsgObj.id, 0, false, scheduled ? 1 : 0, newMsgObj.quick_reply_shortcut_id);
|
||||
getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, MessageObject.getPeerId(newMsgObj.peer_id), oldId, newMsgObj.id, 0, false, mode, newMsgObj.quick_reply_shortcut_id);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, mode, newMsgObj.quick_reply_shortcut_id);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
done[0]++;
|
||||
if (done[0] == totalSent[0] && scheduled != finalCurrentSchedule) {
|
||||
long dialogId = msgObj.getDialogId();
|
||||
final int scheduledMessageId = finalCurrentSchedule && newMessages.size() > 1 ? newMessages.keyAt(0) : 0;
|
||||
getMessagesController().deleteMessages(oldIds, null, null, dialogId, false, scheduled ? ChatActivity.MODE_SCHEDULED : 0, false, 0, null, 0, finalCurrentSchedule && !scheduled, scheduledMessageId);
|
||||
}
|
||||
getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, finalCurrentSchedule);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, finalCurrentSchedule);
|
||||
processSentMessage(oldId);
|
||||
removeFromSendingMessages(oldId, scheduled);
|
||||
});
|
||||
|
@ -6432,7 +6461,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
sentMessages.add(message = newMessage.message);
|
||||
Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewDifferenceParams(-1, newMessage.pts, -1, newMessage.pts_count));
|
||||
updatesArr.remove(a);
|
||||
break;
|
||||
a--;
|
||||
} else if (update instanceof TLRPC.TL_updateNewChannelMessage) {
|
||||
final TLRPC.TL_updateNewChannelMessage newMessage = (TLRPC.TL_updateNewChannelMessage) update;
|
||||
long channelId = MessagesController.getUpdateChannelId(newMessage);
|
||||
|
@ -6462,6 +6491,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
sentMessages.add(message = newMessage.message);
|
||||
Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.peer_id.channel_id));
|
||||
updatesArr.remove(a);
|
||||
currentSchedule = false;
|
||||
a--;
|
||||
if (newMessage.message.pinned) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
|
@ -6470,18 +6500,39 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
getMessagesStorage().updatePinnedMessages(-channelId, mids, true, -1, 0, false, null);
|
||||
});
|
||||
}
|
||||
break;
|
||||
} else if (update instanceof TLRPC.TL_updateNewScheduledMessage) {
|
||||
final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update;
|
||||
for (int i = 0; i < sentMessages.size(); ++i) {
|
||||
if (sentMessages.get(i).id == newMessage.message.id) {
|
||||
sentMessages.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sentMessages.add(message = newMessage.message);
|
||||
updatesArr.remove(a);
|
||||
break;
|
||||
a--;
|
||||
currentSchedule = true;
|
||||
} else if (update instanceof TLRPC.TL_updateQuickReplyMessage) {
|
||||
QuickRepliesController.getInstance(currentAccount).processUpdate(update, msgObj.getQuickReplyName(), msgObj.getQuickReplyId());
|
||||
final TLRPC.TL_updateQuickReplyMessage newMessage = (TLRPC.TL_updateQuickReplyMessage) update;
|
||||
sentMessages.add(message = newMessage.message);
|
||||
updatesArr.remove(a);
|
||||
break;
|
||||
a--;
|
||||
} else if (update instanceof TLRPC.TL_updateDeleteScheduledMessages) {
|
||||
final TLRPC.TL_updateDeleteScheduledMessages upd = (TLRPC.TL_updateDeleteScheduledMessages) update;
|
||||
if (msgObj.getDialogId() == DialogObject.getPeerDialogId(upd.peer)) {
|
||||
for (int msg_id : upd.messages) {
|
||||
for (int i = 0; i < sentMessages.size(); ++i) {
|
||||
if (sentMessages.get(i).id == msg_id) {
|
||||
sentMessages.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
currentSchedule = false;
|
||||
updatesArr.remove(a);
|
||||
a--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (channelReplies != null) {
|
||||
|
@ -6538,16 +6589,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
if (!isSentError) {
|
||||
getStatsController().incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1);
|
||||
newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
|
||||
if (scheduled && !currentSchedule) {
|
||||
if (scheduled != currentSchedule) {
|
||||
final boolean finalCurrentSchedule = currentSchedule;
|
||||
ArrayList<Integer> messageIds = new ArrayList<>();
|
||||
messageIds.add(oldId);
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj.dialog_id, 0, false, ChatActivity.MODE_SCHEDULED);
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
messageObjects.add(new MessageObject(msgObj.currentAccount, msgObj.messageOwner, true, true));
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false, 0, 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false, !scheduled ? ChatActivity.MODE_SCHEDULED : ChatActivity.MODE_DEFAULT, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
messageObjects.add(new MessageObject(msgObj.currentAccount, msgObj.messageOwner, true, true));
|
||||
getMessagesController().updateInterfaceWithMessages(newMsgObj.dialog_id, messageObjects, 0);
|
||||
final int scheduledMessageId = finalCurrentSchedule && newMsgObj != null ? newMsgObj.id : 0;
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj.dialog_id, false, scheduled ? ChatActivity.MODE_SCHEDULED : ChatActivity.MODE_DEFAULT, false, 0, null, 0, !scheduled && finalCurrentSchedule, scheduledMessageId);
|
||||
getMessagesController().updateInterfaceWithMessages(newMsgObj.dialog_id, messageObjects, finalCurrentSchedule ? ChatActivity.MODE_SCHEDULED : ChatActivity.MODE_DEFAULT);
|
||||
getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id);
|
||||
processSentMessage(oldId);
|
||||
removeFromSendingMessages(oldId, scheduled);
|
||||
|
@ -8775,6 +8828,29 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
fillVideoAttribute(info.path, attributeVideo, null);
|
||||
}
|
||||
} else if (!document.thumbs.isEmpty()) {
|
||||
if (info.thumbPath != null) {
|
||||
thumb = BitmapFactory.decodeFile(info.thumbPath);
|
||||
}
|
||||
if (thumb == null) {
|
||||
thumb = createVideoThumbnailAtTime(info.path, startTime);
|
||||
if (thumb == null) {
|
||||
thumb = createVideoThumbnail(info.path, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
}
|
||||
}
|
||||
|
||||
TLRPC.PhotoSize size = null;
|
||||
if (thumb != null) {
|
||||
int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight());
|
||||
size = ImageLoader.scaleAndSaveImage(null, thumb, videoEditedInfo != null && videoEditedInfo.isSticker ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG, false, side, side, side > 90 ? 80 : 55, isEncrypted, 0, 0, false);
|
||||
if (size != null && size.location != null) {
|
||||
thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false);
|
||||
}
|
||||
}
|
||||
if (size != null) {
|
||||
document.thumbs.add(size);
|
||||
document.flags |= 1;
|
||||
}
|
||||
}
|
||||
if (videoEditedInfo != null && videoEditedInfo.muted) {
|
||||
boolean found = false;
|
||||
|
@ -9475,6 +9551,38 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
fillVideoAttribute(videoPath, attributeVideo, null);
|
||||
}
|
||||
} else if (document.thumbs.isEmpty()) {
|
||||
if (videoEditedInfo != null && videoEditedInfo.notReadyYet) {
|
||||
thumb = videoEditedInfo.thumb;
|
||||
}
|
||||
if (thumb == null) {
|
||||
thumb = createVideoThumbnailAtTime(videoPath, startTime);
|
||||
}
|
||||
if (thumb == null) {
|
||||
thumb = createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
}
|
||||
int side = isEncrypted || ttl != 0 ? 90 : 320;
|
||||
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted);
|
||||
if (thumb != null && size != null) {
|
||||
if (isRound) {
|
||||
if (isEncrypted) {
|
||||
thumb = Bitmap.createScaledBitmap(thumb, 90, 90, true);
|
||||
Utilities.blurBitmap(thumb, 7, Build.VERSION.SDK_INT < 21 ? 0 : 1, thumb.getWidth(), thumb.getHeight(), thumb.getRowBytes());
|
||||
Utilities.blurBitmap(thumb, 7, Build.VERSION.SDK_INT < 21 ? 0 : 1, thumb.getWidth(), thumb.getHeight(), thumb.getRowBytes());
|
||||
Utilities.blurBitmap(thumb, 7, Build.VERSION.SDK_INT < 21 ? 0 : 1, thumb.getWidth(), thumb.getHeight(), thumb.getRowBytes());
|
||||
thumbKey = String.format(size.location.volume_id + "_" + size.location.local_id + "@%d_%d_b2", (int) (AndroidUtilities.roundMessageSize / AndroidUtilities.density), (int) (AndroidUtilities.roundMessageSize / AndroidUtilities.density));
|
||||
} else {
|
||||
Utilities.blurBitmap(thumb, 3, Build.VERSION.SDK_INT < 21 ? 0 : 1, thumb.getWidth(), thumb.getHeight(), thumb.getRowBytes());
|
||||
thumbKey = String.format(size.location.volume_id + "_" + size.location.local_id + "@%d_%d_b", (int) (AndroidUtilities.roundMessageSize / AndroidUtilities.density), (int) (AndroidUtilities.roundMessageSize / AndroidUtilities.density));
|
||||
}
|
||||
} else {
|
||||
thumb = null;
|
||||
}
|
||||
}
|
||||
if (size != null) {
|
||||
document.thumbs.add(size);
|
||||
document.flags |= 1;
|
||||
}
|
||||
}
|
||||
if (videoEditedInfo != null && videoEditedInfo.needConvert()) {
|
||||
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".mp4";
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class ShortcutResultReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final int currentAccount = intent.getIntExtra("account", UserConfig.selectedAccount);
|
||||
final String req_id = intent.getStringExtra("req_id");
|
||||
|
||||
Utilities.Callback<Boolean> callback = MediaDataController.getInstance(currentAccount).shortcutCallbacks.remove(req_id);
|
||||
if (callback != null) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
callback.run(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,13 +27,13 @@ public class UserNameResolver {
|
|||
LruCache<String, CachedPeer> resolvedCache = new LruCache<>(100);
|
||||
HashMap<String, ArrayList<Consumer<Long>>> resolvingConsumers = new HashMap<>();
|
||||
|
||||
public void resolve(String username, Consumer<Long> resolveConsumer) {
|
||||
public int resolve(String username, Consumer<Long> resolveConsumer) {
|
||||
CachedPeer cachedPeer = resolvedCache.get(username);
|
||||
if (cachedPeer != null) {
|
||||
if (System.currentTimeMillis() - cachedPeer.time < CACHE_TIME) {
|
||||
resolveConsumer.accept(cachedPeer.peerId);
|
||||
FileLog.d("resolve username from cache " + username + " " + cachedPeer.peerId);
|
||||
return;
|
||||
return -1;
|
||||
} else {
|
||||
resolvedCache.remove(username);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class UserNameResolver {
|
|||
ArrayList<Consumer<Long>> consumers = resolvingConsumers.get(username);
|
||||
if (consumers != null) {
|
||||
consumers.add(resolveConsumer);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
consumers = new ArrayList<>();
|
||||
consumers.add(resolveConsumer);
|
||||
|
@ -59,7 +59,7 @@ public class UserNameResolver {
|
|||
resolveUsername.username = username;
|
||||
req = resolveUsername;
|
||||
}
|
||||
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
return ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<Consumer<Long>> finalConsumers = resolvingConsumers.remove(username);
|
||||
if (finalConsumers == null) {
|
||||
return;
|
||||
|
|
|
@ -41,6 +41,10 @@ public class UserObject {
|
|||
return user != null && user.id == ANONYMOUS;
|
||||
}
|
||||
|
||||
public static boolean isBot(TLRPC.User user) {
|
||||
return user != null && user.bot;
|
||||
}
|
||||
|
||||
public static boolean isReplyUser(long did) {
|
||||
return did == 708513 || did == REPLY_BOT;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,10 @@ public abstract class AudioInfo {
|
|||
OtherAudioInfo info = new OtherAudioInfo(file);
|
||||
if (info.failed) return null;
|
||||
return info;
|
||||
} else if (file.getAbsolutePath().endsWith("mp3")) {
|
||||
} else if (file.getAbsolutePath().endsWith("mp3") || (
|
||||
(header[0] == 'I' && header[1] == 'D' && header[2] == '3') ||
|
||||
(header[0] == 'T' && header[1] == 'A' && header[2] == 'G')
|
||||
)) {
|
||||
return new MP3Info(input, file.length());
|
||||
} else {
|
||||
OtherAudioInfo info = new OtherAudioInfo(file);
|
||||
|
|
|
@ -255,14 +255,14 @@ public class Browser {
|
|||
}
|
||||
|
||||
public static void openUrl(final Context context, Uri uri, final boolean allowCustom, boolean tryTelegraph) {
|
||||
openUrl(context, uri, allowCustom, tryTelegraph, false, null, null, false, true);
|
||||
openUrl(context, uri, allowCustom, tryTelegraph, false, null, null, false, true, false);
|
||||
}
|
||||
|
||||
public static void openUrl(final Context context, Uri uri, final boolean allowCustom, boolean tryTelegraph, Progress inCaseLoading) {
|
||||
openUrl(context, uri, allowCustom, tryTelegraph, false, inCaseLoading, null, false, true);
|
||||
openUrl(context, uri, allowCustom, tryTelegraph, false, inCaseLoading, null, false, true, false);
|
||||
}
|
||||
|
||||
public static void openUrl(final Context context, Uri uri, boolean _allowCustom, boolean tryTelegraph, boolean forceNotInternalForApps, Progress inCaseLoading, String browser, boolean allowIntent, boolean allowInAppBrowser) {
|
||||
public static void openUrl(final Context context, Uri uri, boolean _allowCustom, boolean tryTelegraph, boolean forceNotInternalForApps, Progress inCaseLoading, String browser, boolean allowIntent, boolean allowInAppBrowser, boolean forceRequest) {
|
||||
if (context == null || uri == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ public class Browser {
|
|||
);
|
||||
final boolean isIntentScheme = uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("intent");
|
||||
if (internalUri && LaunchActivity.instance != null) {
|
||||
openAsInternalIntent(LaunchActivity.instance, uri.toString(), forceNotInternalForApps, inCaseLoading);
|
||||
openAsInternalIntent(LaunchActivity.instance, uri.toString(), forceNotInternalForApps, forceRequest, inCaseLoading);
|
||||
} else {
|
||||
if (inappBrowser) {
|
||||
if (!openInExternalApp(context, uri.toString(), allowIntent)) {
|
||||
|
@ -420,15 +420,15 @@ public class Browser {
|
|||
}
|
||||
|
||||
public static boolean openAsInternalIntent(Context context, String url) {
|
||||
return openAsInternalIntent(context, url, false, null);
|
||||
return openAsInternalIntent(context, url, false, false, null);
|
||||
}
|
||||
public static boolean openAsInternalIntent(Context context, String url, Browser.Progress progress) {
|
||||
return openAsInternalIntent(context, url, false, progress);
|
||||
return openAsInternalIntent(context, url, false, false, progress);
|
||||
}
|
||||
public static boolean openAsInternalIntent(Context context, String url, boolean forceNotInternalForApps) {
|
||||
return openAsInternalIntent(context, url, forceNotInternalForApps, null);
|
||||
return openAsInternalIntent(context, url, forceNotInternalForApps, false, null);
|
||||
}
|
||||
public static boolean openAsInternalIntent(Context context, String url, boolean forceNotInternalForApps, Browser.Progress progress) {
|
||||
public static boolean openAsInternalIntent(Context context, String url, boolean forceNotInternalForApps, boolean forceRequest, Progress progress) {
|
||||
if (url == null) return false;
|
||||
LaunchActivity activity = null;
|
||||
if (AndroidUtilities.findActivity(context) instanceof LaunchActivity) {
|
||||
|
@ -445,6 +445,7 @@ public class Browser {
|
|||
intent.putExtra(android.provider.Browser.EXTRA_CREATE_NEW_TAB, true);
|
||||
intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
||||
intent.putExtra(LaunchActivity.EXTRA_FORCE_NOT_INTERNAL_APPS, forceNotInternalForApps);
|
||||
intent.putExtra(LaunchActivity.EXTRA_FORCE_REQUEST, forceRequest);
|
||||
activity.onNewIntent(intent, progress);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,17 +23,24 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
|
|||
import com.google.android.exoplayer2.upstream.FileDataSource;
|
||||
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheSpan;
|
||||
import com.google.android.exoplayer2.upstream.cache.ContentMetadata;
|
||||
import com.google.android.exoplayer2.upstream.cache.ContentMetadataMutations;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import org.telegram.messenger.FileStreamLoadOperation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ExtendedDefaultDataSource implements DataSource {
|
||||
|
||||
|
@ -314,4 +321,103 @@ public final class ExtendedDefaultDataSource implements DataSource {
|
|||
dataSource.addTransferListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Cache cache = new Cache() {
|
||||
@Override
|
||||
public long getUid() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableSet<CacheSpan> addListener(String key, Listener listener) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(String key, Listener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableSet<CacheSpan> getCachedSpans(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCacheSpace() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheSpan startReadWrite(String key, long position, long length) throws InterruptedException, CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CacheSpan startReadWriteNonBlocking(String key, long position, long length) throws CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File startFile(String key, long position, long length) throws CacheException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitFile(File file, long length) throws CacheException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseHoleSpan(CacheSpan holeSpan) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeResource(String key) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpan(CacheSpan span) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCached(String key, long position, long length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCachedLength(String key, long position, long length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCachedBytes(String key, long position, long length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyContentMetadataMutations(String key, ContentMetadataMutations mutations) throws CacheException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentMetadata getContentMetadata(String key) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
package org.telegram.messenger.video;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.ui.Components.PhotoViewerWebView;
|
||||
import org.telegram.ui.Components.VideoForwardDrawable;
|
||||
import org.telegram.ui.Components.VideoPlayer;
|
||||
|
||||
public class OldVideoPlayerRewinder {
|
||||
|
||||
public int rewindCount;
|
||||
private boolean rewindForward;
|
||||
public boolean rewindByBackSeek;
|
||||
private long startRewindFrom;
|
||||
private Runnable updateRewindRunnable;
|
||||
private long rewindLastTime;
|
||||
private long rewindLastUpdatePlayerTime;
|
||||
private long rewindBackSeekPlayerPosition;
|
||||
private float playSpeed = 1f;
|
||||
|
||||
private VideoPlayer videoPlayer;
|
||||
private PhotoViewerWebView webView;
|
||||
|
||||
private final Runnable backSeek = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (videoPlayer == null && webView == null) {
|
||||
return;
|
||||
}
|
||||
long duration = getDuration();
|
||||
if (duration == 0 || duration == C.TIME_UNSET) {
|
||||
rewindLastTime = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
|
||||
long t = System.currentTimeMillis();
|
||||
long dt = t - rewindLastTime;
|
||||
rewindLastTime = t;
|
||||
if (rewindCount == 1) {
|
||||
dt *= 3;
|
||||
} else if (rewindCount == 2) {
|
||||
dt *= 6;
|
||||
} else {
|
||||
dt *= 12;
|
||||
}
|
||||
if (rewindForward) {
|
||||
rewindBackSeekPlayerPosition += dt;
|
||||
} else {
|
||||
rewindBackSeekPlayerPosition -= dt;
|
||||
}
|
||||
if (rewindBackSeekPlayerPosition < 0) {
|
||||
rewindBackSeekPlayerPosition = 0;
|
||||
} else if (rewindBackSeekPlayerPosition > duration) {
|
||||
rewindBackSeekPlayerPosition = duration;
|
||||
}
|
||||
if (rewindByBackSeek && rewindLastTime - rewindLastUpdatePlayerTime > 350) {
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
}
|
||||
|
||||
long timeDiff = rewindBackSeekPlayerPosition - startRewindFrom;
|
||||
float progress = rewindBackSeekPlayerPosition / (float) getDuration();
|
||||
updateRewindProgressUi(timeDiff, progress, rewindByBackSeek);
|
||||
|
||||
if (rewindBackSeekPlayerPosition == 0 || rewindBackSeekPlayerPosition >= duration) {
|
||||
if (rewindByBackSeek) {
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
}
|
||||
cancelRewind();
|
||||
}
|
||||
if (rewindCount > 0) {
|
||||
AndroidUtilities.runOnUIThread(backSeek, 16);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void startRewind(PhotoViewerWebView webView, boolean forward, float playbackSpeed) {
|
||||
this.webView = webView;
|
||||
this.playSpeed = playbackSpeed;
|
||||
rewindForward = forward;
|
||||
cancelRewind();
|
||||
incrementRewindCount();
|
||||
}
|
||||
|
||||
public void startRewind(VideoPlayer videoPlayer, boolean forward, float playbackSpeed) {
|
||||
this.videoPlayer = videoPlayer;
|
||||
this.playSpeed = playbackSpeed;
|
||||
rewindForward = forward;
|
||||
cancelRewind();
|
||||
incrementRewindCount();
|
||||
}
|
||||
|
||||
public void cancelRewind() {
|
||||
if (rewindCount != 0) {
|
||||
rewindCount = 0;
|
||||
|
||||
if (videoPlayer != null || webView != null) {
|
||||
if (rewindByBackSeek) {
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
} else {
|
||||
long current = getCurrentPosition();
|
||||
seekTo(current);
|
||||
}
|
||||
setPlaybackSpeed(playSpeed);
|
||||
}
|
||||
}
|
||||
AndroidUtilities.cancelRunOnUIThread(backSeek);
|
||||
|
||||
if (updateRewindRunnable != null) {
|
||||
AndroidUtilities.cancelRunOnUIThread(updateRewindRunnable);
|
||||
updateRewindRunnable = null;
|
||||
}
|
||||
|
||||
onRewindCanceled();
|
||||
}
|
||||
|
||||
private void incrementRewindCount() {
|
||||
if (videoPlayer == null && webView == null) {
|
||||
return;
|
||||
}
|
||||
rewindCount++;
|
||||
boolean needUpdate = false;
|
||||
if (rewindCount == 1) {
|
||||
if (rewindForward && isPlaying()) {
|
||||
rewindByBackSeek = false;
|
||||
} else {
|
||||
rewindByBackSeek = true;
|
||||
}
|
||||
}
|
||||
if (rewindForward && !rewindByBackSeek) {
|
||||
if (rewindCount == 1) {
|
||||
setPlaybackSpeed(4);
|
||||
needUpdate = true;
|
||||
} else if (rewindCount == 2) {
|
||||
setPlaybackSpeed(7);
|
||||
needUpdate = true;
|
||||
} else {
|
||||
setPlaybackSpeed(13);
|
||||
}
|
||||
} else {
|
||||
if (rewindCount == 1 || rewindCount == 2) {
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (rewindCount == 1) {
|
||||
rewindBackSeekPlayerPosition = getCurrentPosition();
|
||||
rewindLastTime = System.currentTimeMillis();
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
startRewindFrom = getCurrentPosition();
|
||||
onRewindStart(rewindForward);
|
||||
}
|
||||
|
||||
AndroidUtilities.cancelRunOnUIThread(backSeek);
|
||||
AndroidUtilities.runOnUIThread(backSeek);
|
||||
|
||||
if (needUpdate) {
|
||||
if (updateRewindRunnable != null) {
|
||||
AndroidUtilities.cancelRunOnUIThread(updateRewindRunnable);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(updateRewindRunnable = () -> {
|
||||
updateRewindRunnable = null;
|
||||
incrementRewindCount();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateRewindProgressUi(long timeDiff, float progress, boolean rewindByBackSeek) {
|
||||
|
||||
}
|
||||
|
||||
protected void onRewindStart(boolean rewindForward) {
|
||||
|
||||
}
|
||||
|
||||
protected void onRewindCanceled() {
|
||||
|
||||
}
|
||||
|
||||
private void seekTo(long position) {
|
||||
if (webView != null) {
|
||||
webView.seekTo(position);
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return;
|
||||
}
|
||||
videoPlayer.seekTo(position);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPlaybackSpeed(float speed) {
|
||||
if (webView != null) {
|
||||
webView.setPlaybackSpeed(speed);
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return;
|
||||
}
|
||||
videoPlayer.setPlaybackSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
private long getCurrentPosition() {
|
||||
if (webView != null) {
|
||||
return webView.getCurrentPosition();
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return 0;
|
||||
}
|
||||
return videoPlayer.getCurrentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
private long getDuration() {
|
||||
if (webView != null) {
|
||||
return webView.getVideoDuration();
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return 0;
|
||||
}
|
||||
return videoPlayer.getDuration();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPlaying() {
|
||||
if (webView != null) {
|
||||
return webView.isPlaying();
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
return videoPlayer.isPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
public float getVideoProgress() {
|
||||
return rewindBackSeekPlayerPosition / (float) getDuration();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
package org.telegram.messenger.video;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedFileDrawable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class VideoFramesRewinder {
|
||||
|
||||
private int maxFramesCount;
|
||||
private int maxFrameSide;
|
||||
|
||||
private final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
|
||||
private View parentView;
|
||||
int w, h;
|
||||
|
||||
public VideoFramesRewinder() {
|
||||
switch (SharedConfig.getDevicePerformanceClass()) {
|
||||
case SharedConfig.PERFORMANCE_CLASS_HIGH:
|
||||
maxFramesCount = 400;
|
||||
maxFrameSide = 720;
|
||||
break;
|
||||
case SharedConfig.PERFORMANCE_CLASS_AVERAGE:
|
||||
maxFramesCount = 200;
|
||||
maxFrameSide = 580;
|
||||
break;
|
||||
default:
|
||||
maxFramesCount = 100;
|
||||
maxFrameSide = 480;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, int w, int h) {
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
if (ptr != 0 && currentFrame != null) {
|
||||
canvas.save();
|
||||
canvas.scale(w / (float) currentFrame.bitmap.getWidth(), h / (float) currentFrame.bitmap.getHeight());
|
||||
canvas.drawBitmap(currentFrame.bitmap, 0, 0, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
private long ptr;
|
||||
private final int[] meta = new int[6];
|
||||
|
||||
public boolean isReady() {
|
||||
return ptr != 0;
|
||||
}
|
||||
|
||||
public void setup(File file) {
|
||||
if (file == null) {
|
||||
release();
|
||||
return;
|
||||
}
|
||||
stop.set(false);
|
||||
ptr = AnimatedFileDrawable.createDecoder(file.getAbsolutePath(), meta, UserConfig.selectedAccount, 0, null, true);
|
||||
}
|
||||
|
||||
private final ArrayList<Frame> freeFrames = new ArrayList<>();
|
||||
private final TreeSet<Frame> frames = new TreeSet<Frame>((a, b) -> {
|
||||
return (int) (a.position - b.position);
|
||||
});
|
||||
private Frame currentFrame;
|
||||
|
||||
private class Frame {
|
||||
long position;
|
||||
Bitmap bitmap;
|
||||
}
|
||||
|
||||
private AtomicBoolean stop = new AtomicBoolean(false);
|
||||
private AtomicLong until = new AtomicLong(0);
|
||||
private boolean isPreparing;
|
||||
private long lastSeek;
|
||||
private float lastSpeed = 1.0f;
|
||||
private long prepareToMs;
|
||||
private float prepareWithSpeed;
|
||||
private boolean destroyAfterPrepare;
|
||||
private Runnable prepareRunnable = () -> {
|
||||
final ArrayList<Frame> newFrames = new ArrayList<>();
|
||||
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
final int fps = meta[4];
|
||||
int w = Math.min(this.w / 4, meta[0]), h = Math.min(this.h / 4, meta[1]);
|
||||
if (w > maxFrameSide || h > maxFrameSide) {
|
||||
final float scale = (float) maxFrameSide / Math.max(w, h);
|
||||
w = (int) (w * scale);
|
||||
h = (int) (h * scale);
|
||||
}
|
||||
final long toMs = prepareToMs;
|
||||
AnimatedFileDrawable.seekToMs(ptr, toMs - (long) (350 * prepareWithSpeed), meta, false);
|
||||
long ms = meta[3];
|
||||
int triesCount = 0;
|
||||
for (int i = 0; meta[3] <= until.get() && i < maxFramesCount && !stop.get(); ++i) {
|
||||
long nextms = (long) (ms + (1000.0f / fps) * prepareWithSpeed);
|
||||
Frame frame;
|
||||
if (!freeFrames.isEmpty()) {
|
||||
frame = freeFrames.remove(0);
|
||||
} else {
|
||||
frame = new Frame();
|
||||
}
|
||||
if (frame.bitmap == null || frame.bitmap.getWidth() != w || frame.bitmap.getHeight() != h) {
|
||||
AndroidUtilities.recycleBitmap(frame.bitmap);
|
||||
try {
|
||||
frame.bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
} catch (OutOfMemoryError e) {
|
||||
FileLog.d("[VideoFramesRewinder] failed to create bitmap: out of memory");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (meta[3] + (long) Math.ceil(1000.0f / fps) < nextms) {
|
||||
AnimatedFileDrawable.getVideoFrame(ptr, null, meta, 0, true, 0, meta[4], false);
|
||||
}
|
||||
if (0 == AnimatedFileDrawable.getVideoFrame(ptr, frame.bitmap, meta, frame.bitmap.getRowBytes(), true, 0, meta[4], false)) {
|
||||
triesCount++;
|
||||
if (triesCount > 6) break;
|
||||
continue;
|
||||
}
|
||||
ms = frame.position = meta[3];
|
||||
newFrames.add(frame);
|
||||
}
|
||||
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
FileLog.d("[VideoFramesRewinder] total prepare of " + newFrames.size() + " took " + (System.currentTimeMillis() - start) + "ms");
|
||||
if (!newFrames.isEmpty()) {
|
||||
FileLog.d("[VideoFramesRewinder] prepared from " + newFrames.get(0).position + "ms to " + newFrames.get(newFrames.size() - 1).position + "ms (requested up to "+prepareToMs+"ms)");
|
||||
}
|
||||
isPreparing = false;
|
||||
final Iterator<Frame> i = frames.iterator();
|
||||
while (i.hasNext()) {
|
||||
final Frame f = i.next();
|
||||
if (currentFrame != f && f.position > lastSeek) {
|
||||
if (freeFrames.size() > 20) {
|
||||
AndroidUtilities.recycleBitmap(f.bitmap);
|
||||
} else {
|
||||
freeFrames.add(f);
|
||||
}
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
while (!newFrames.isEmpty() && frames.size() < maxFramesCount) {
|
||||
frames.add(newFrames.remove(newFrames.size() - 1));
|
||||
}
|
||||
if (newFrames.size() > 0) {
|
||||
FileLog.d("[VideoFramesRewinder] prepared "+newFrames.size()+" more frames than I could fit :(");
|
||||
}
|
||||
|
||||
if (destroyAfterPrepare) {
|
||||
release();
|
||||
stop.set(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
private void prepare(long toMs) {
|
||||
if (isPreparing) {
|
||||
return;
|
||||
}
|
||||
FileLog.d("[VideoFramesRewinder] starting preparing " + toMs + "ms");
|
||||
isPreparing = true;
|
||||
prepareToMs = toMs;
|
||||
prepareWithSpeed = lastSpeed;
|
||||
Utilities.themeQueue.postRunnable(prepareRunnable);
|
||||
}
|
||||
|
||||
public void seek(long position, float currentSpeed) {
|
||||
if (ptr == 0) return;
|
||||
|
||||
lastSeek = position;
|
||||
lastSpeed = currentSpeed;
|
||||
until.set(position);
|
||||
|
||||
final Iterator<Frame> i = frames.iterator();
|
||||
final ArrayList<Long> pastPositions = new ArrayList<>();
|
||||
while (i.hasNext()) {
|
||||
final Frame f = i.next();
|
||||
pastPositions.add(f.position);
|
||||
if (Math.abs(f.position - position) < 25 * currentSpeed) {
|
||||
if (currentFrame != f) {
|
||||
FileLog.d("[VideoFramesRewinder] found a frame " + f.position + "ms to fit to "+position+"ms from " + frames.size() + " frames");
|
||||
currentFrame = f;
|
||||
invalidate();
|
||||
|
||||
int deleted = 0;
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
i.remove();
|
||||
deleted++;
|
||||
}
|
||||
if (deleted > 0) {
|
||||
FileLog.d("[VideoFramesRewinder] also deleted " + deleted + " frames after this frame");
|
||||
}
|
||||
}
|
||||
for (int j = pastPositions.size() - 2; j >= 0; --j) {
|
||||
final long next = pastPositions.get(j + 1);
|
||||
final long pos = pastPositions.get(j);
|
||||
if (Math.abs(next - pos) > 25 * currentSpeed) {
|
||||
prepare(pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
prepare(Math.max(0, frames.first().position - 20));
|
||||
return;
|
||||
}
|
||||
}
|
||||
FileLog.d("[VideoFramesRewinder] didn't find a frame, wanting to prepare " + position + "ms");
|
||||
prepare(Math.max(0, position));
|
||||
}
|
||||
|
||||
public void clearCurrent() {
|
||||
if (currentFrame != null) {
|
||||
currentFrame = null;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
if (isPreparing) {
|
||||
stop.set(true);
|
||||
destroyAfterPrepare = true;
|
||||
return;
|
||||
}
|
||||
AnimatedFileDrawable.destroyDecoder(ptr);
|
||||
ptr = 0;
|
||||
destroyAfterPrepare = false;
|
||||
clearCurrent();
|
||||
until.set(0);
|
||||
|
||||
for (Frame f : frames) {
|
||||
AndroidUtilities.recycleBitmap(f.bitmap);
|
||||
}
|
||||
frames.clear();
|
||||
for (Frame f : freeFrames) {
|
||||
AndroidUtilities.recycleBitmap(f.bitmap);
|
||||
}
|
||||
freeFrames.clear();
|
||||
}
|
||||
|
||||
public void setParentView(View view) {
|
||||
parentView = view;
|
||||
}
|
||||
|
||||
private void invalidate() {
|
||||
if (parentView != null) {
|
||||
parentView.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
package org.telegram.messenger.video;
|
||||
|
||||
import static org.telegram.messenger.AndroidUtilities.dp;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Components.PhotoViewerWebView;
|
||||
import org.telegram.ui.Components.SeekSpeedDrawable;
|
||||
import org.telegram.ui.Components.VideoForwardDrawable;
|
||||
import org.telegram.ui.Components.VideoPlayer;
|
||||
|
||||
|
@ -11,16 +17,27 @@ public class VideoPlayerRewinder {
|
|||
|
||||
public int rewindCount;
|
||||
private boolean rewindForward;
|
||||
private boolean fastSeeking;
|
||||
public boolean rewindByBackSeek;
|
||||
private long startRewindFrom;
|
||||
private Runnable updateRewindRunnable;
|
||||
private long rewindLastTime;
|
||||
private long rewindLastUpdatePlayerTime;
|
||||
private long rewindBackSeekPlayerPosition;
|
||||
private long rewindBackSeekLastPlayerPosition;
|
||||
private long rewindBackSeekPlayerPosition = -1;
|
||||
private float playSpeed = 1f;
|
||||
private boolean wasMuted;
|
||||
private boolean wasPaused;
|
||||
|
||||
private float value;
|
||||
|
||||
private VideoPlayer videoPlayer;
|
||||
private PhotoViewerWebView webView;
|
||||
private VideoFramesRewinder framesRewinder;
|
||||
|
||||
public VideoPlayerRewinder(VideoFramesRewinder framesRewinder) {
|
||||
this.framesRewinder = framesRewinder;
|
||||
}
|
||||
|
||||
private final Runnable backSeek = new Runnable() {
|
||||
@Override
|
||||
|
@ -34,29 +51,20 @@ public class VideoPlayerRewinder {
|
|||
return;
|
||||
}
|
||||
|
||||
long t = System.currentTimeMillis();
|
||||
long dt = t - rewindLastTime;
|
||||
rewindLastTime = t;
|
||||
if (rewindCount == 1) {
|
||||
dt *= 3;
|
||||
} else if (rewindCount == 2) {
|
||||
dt *= 6;
|
||||
} else {
|
||||
dt *= 12;
|
||||
}
|
||||
if (rewindForward) {
|
||||
rewindBackSeekPlayerPosition += dt;
|
||||
} else {
|
||||
rewindBackSeekPlayerPosition -= dt;
|
||||
}
|
||||
if (rewindBackSeekPlayerPosition < 0) {
|
||||
rewindBackSeekPlayerPosition = 0;
|
||||
} else if (rewindBackSeekPlayerPosition > duration) {
|
||||
rewindBackSeekPlayerPosition = duration;
|
||||
}
|
||||
if (rewindByBackSeek && rewindLastTime - rewindLastUpdatePlayerTime > 350) {
|
||||
final long now = System.currentTimeMillis();
|
||||
long dt = now - rewindLastTime;
|
||||
rewindLastTime = now;
|
||||
final float speed = Math.max(0, -getRewindSpeed() * playSpeed);
|
||||
dt *= speed;
|
||||
rewindBackSeekPlayerPosition -= dt;
|
||||
rewindBackSeekPlayerPosition = Utilities.clamp(rewindBackSeekPlayerPosition, duration, 0);
|
||||
if (rewindByBackSeek && getCurrentPosition() > rewindBackSeekPlayerPosition && rewindLastTime - rewindLastUpdatePlayerTime > 10) {
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
if (framesRewinder != null) {
|
||||
framesRewinder.seek(rewindBackSeekPlayerPosition, Math.abs(speed));
|
||||
} else {
|
||||
seekTo(rewindBackSeekPlayerPosition, false);
|
||||
}
|
||||
}
|
||||
|
||||
long timeDiff = rewindBackSeekPlayerPosition - startRewindFrom;
|
||||
|
@ -66,47 +74,165 @@ public class VideoPlayerRewinder {
|
|||
if (rewindBackSeekPlayerPosition == 0 || rewindBackSeekPlayerPosition >= duration) {
|
||||
if (rewindByBackSeek) {
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
seekTo(rewindBackSeekPlayerPosition, false);
|
||||
}
|
||||
cancelRewind();
|
||||
}
|
||||
if (rewindCount > 0) {
|
||||
if (rewinding && getRewindSpeed() < 0) {
|
||||
AndroidUtilities.runOnUIThread(backSeek, 16);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void startRewind(PhotoViewerWebView webView, boolean forward, float playbackSpeed) {
|
||||
this.webView = webView;
|
||||
this.playSpeed = playbackSpeed;
|
||||
rewindForward = forward;
|
||||
public boolean rewinding;
|
||||
private float x;
|
||||
private SeekSpeedDrawable seekSpeedDrawable;
|
||||
|
||||
public void startRewind(PhotoViewerWebView webView, boolean forward, float initialX, float playbackSpeed, SeekSpeedDrawable seekSpeedDrawable) {
|
||||
cancelRewind();
|
||||
incrementRewindCount();
|
||||
this.videoPlayer = null;
|
||||
this.webView = null;
|
||||
if (framesRewinder != null) {
|
||||
framesRewinder.release();
|
||||
}
|
||||
rewindByBackSeek = forward;
|
||||
rewinding = true;
|
||||
rewindBackSeekPlayerPosition = -1;
|
||||
this.webView = webView;
|
||||
this.seekSpeedDrawable = seekSpeedDrawable;
|
||||
this.playSpeed = playbackSpeed;
|
||||
this.wasMuted = false;
|
||||
this.wasPaused = webView != null && !webView.isPlaying();
|
||||
fastSeeking = false;
|
||||
rewindLastUpdatePlayerTime = 0;
|
||||
x = initialX;
|
||||
value = forward ? getValueBySpeed(2.0f) : getValueBySpeed(-2.0f);
|
||||
rewindBackSeekLastPlayerPosition = -100;
|
||||
if (seekSpeedDrawable != null) {
|
||||
seekSpeedDrawable.setSpeed(getRewindSpeed(), false);
|
||||
seekSpeedDrawable.setShown(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void startRewind(VideoPlayer videoPlayer, boolean forward, float playbackSpeed) {
|
||||
this.videoPlayer = videoPlayer;
|
||||
this.playSpeed = playbackSpeed;
|
||||
rewindForward = forward;
|
||||
public void startRewind(VideoPlayer videoPlayer, boolean forward, float initialX, float playbackSpeed, SeekSpeedDrawable seekSpeedDrawable) {
|
||||
cancelRewind();
|
||||
incrementRewindCount();
|
||||
this.videoPlayer = null;
|
||||
this.webView = null;
|
||||
if (framesRewinder != null) {
|
||||
framesRewinder.release();
|
||||
}
|
||||
rewindByBackSeek = forward;
|
||||
rewinding = true;
|
||||
rewindBackSeekPlayerPosition = -1;
|
||||
this.videoPlayer = videoPlayer;
|
||||
this.seekSpeedDrawable = seekSpeedDrawable;
|
||||
this.playSpeed = playbackSpeed;
|
||||
this.wasMuted = videoPlayer != null && videoPlayer.isMuted();
|
||||
this.wasPaused = videoPlayer != null && !videoPlayer.isPlaying();
|
||||
fastSeeking = false;
|
||||
rewindLastUpdatePlayerTime = 0;
|
||||
x = initialX;
|
||||
value = forward ? getValueBySpeed(2.0f) : getValueBySpeed(-2.0f);
|
||||
rewindBackSeekLastPlayerPosition = -100;
|
||||
if (seekSpeedDrawable != null) {
|
||||
seekSpeedDrawable.setSpeed(getRewindSpeed(), false);
|
||||
seekSpeedDrawable.setShown(true, true);
|
||||
}
|
||||
updateRewindSpeed();
|
||||
}
|
||||
|
||||
public float getRewindSpeed() {
|
||||
float v = value;
|
||||
v = v < 0.4f ? v - 1.9f : v;
|
||||
// v /= 2.0f;
|
||||
// v = v * v * v;
|
||||
return Utilities.clamp(v, +10.0f, -6.0f);
|
||||
}
|
||||
|
||||
public float getValueBySpeed(float speed) {
|
||||
float value = speed;
|
||||
// value = (float) Math.cbrt(value);
|
||||
// value *= 2.0f;
|
||||
if (value < -1.5f) {
|
||||
value += 1.9f;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void updateRewindSpeed() {
|
||||
final float rewindSpeed = getRewindSpeed();
|
||||
if (rewindSpeed < 0) {
|
||||
if (!rewindByBackSeek) {
|
||||
rewindByBackSeek = true;
|
||||
rewindBackSeekPlayerPosition = getCurrentPosition();
|
||||
rewindLastTime = System.currentTimeMillis();
|
||||
AndroidUtilities.runOnUIThread(backSeek);
|
||||
setMuted(true);
|
||||
setPaused(true);
|
||||
setPlaybackSpeed(playSpeed);
|
||||
if (framesRewinder != null && !framesRewinder.isReady() && videoPlayer != null) {
|
||||
framesRewinder.setup(videoPlayer.getLowestFile());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rewindByBackSeek) {
|
||||
rewindByBackSeek = false;
|
||||
AndroidUtilities.cancelRunOnUIThread(backSeek);
|
||||
setMuted(wasMuted || wasPaused);
|
||||
setPaused(false);
|
||||
if (videoPlayer != null && framesRewinder != null && rewindBackSeekPlayerPosition >= 0) {
|
||||
videoPlayer.seekTo(rewindBackSeekPlayerPosition, false, () -> {
|
||||
if (framesRewinder != null) {
|
||||
framesRewinder.clearCurrent();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
setPlaybackSpeed(playSpeed * rewindSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
float diff = this.x - x;
|
||||
value -= diff / dp(40);
|
||||
this.x = x;
|
||||
|
||||
if (seekSpeedDrawable != null) {
|
||||
seekSpeedDrawable.setSpeed(getRewindSpeed(), true);
|
||||
}
|
||||
|
||||
updateRewindSpeed();
|
||||
}
|
||||
|
||||
public void cancelRewind() {
|
||||
if (rewindCount != 0) {
|
||||
rewindCount = 0;
|
||||
if (!rewinding) return;
|
||||
|
||||
if (videoPlayer != null || webView != null) {
|
||||
if (rewindByBackSeek) {
|
||||
seekTo(rewindBackSeekPlayerPosition);
|
||||
rewinding = false;
|
||||
fastSeeking = false;
|
||||
boolean awaitSeek = false;
|
||||
if (videoPlayer != null || webView != null) {
|
||||
if (rewindByBackSeek) {
|
||||
if (videoPlayer != null && framesRewinder != null) {
|
||||
awaitSeek = true;
|
||||
videoPlayer.seekTo(rewindBackSeekPlayerPosition, false, () -> {
|
||||
if (framesRewinder != null) {
|
||||
framesRewinder.release();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
long current = getCurrentPosition();
|
||||
seekTo(current);
|
||||
seekTo(rewindBackSeekPlayerPosition, false);
|
||||
}
|
||||
setPlaybackSpeed(playSpeed);
|
||||
} else {
|
||||
seekTo(getCurrentPosition(), false);
|
||||
}
|
||||
setPlaybackSpeed(playSpeed);
|
||||
}
|
||||
setMuted(wasMuted);
|
||||
setPaused(wasPaused);
|
||||
AndroidUtilities.cancelRunOnUIThread(backSeek);
|
||||
if (framesRewinder != null && !awaitSeek) {
|
||||
framesRewinder.release();
|
||||
}
|
||||
|
||||
if (updateRewindRunnable != null) {
|
||||
AndroidUtilities.cancelRunOnUIThread(updateRewindRunnable);
|
||||
|
@ -114,61 +240,12 @@ public class VideoPlayerRewinder {
|
|||
}
|
||||
|
||||
onRewindCanceled();
|
||||
}
|
||||
|
||||
private void incrementRewindCount() {
|
||||
if (videoPlayer == null && webView == null) {
|
||||
return;
|
||||
}
|
||||
rewindCount++;
|
||||
boolean needUpdate = false;
|
||||
if (rewindCount == 1) {
|
||||
if (rewindForward && isPlaying()) {
|
||||
rewindByBackSeek = false;
|
||||
} else {
|
||||
rewindByBackSeek = true;
|
||||
}
|
||||
}
|
||||
if (rewindForward && !rewindByBackSeek) {
|
||||
if (rewindCount == 1) {
|
||||
setPlaybackSpeed(4);
|
||||
needUpdate = true;
|
||||
} else if (rewindCount == 2) {
|
||||
setPlaybackSpeed(7);
|
||||
needUpdate = true;
|
||||
} else {
|
||||
setPlaybackSpeed(13);
|
||||
}
|
||||
} else {
|
||||
if (rewindCount == 1 || rewindCount == 2) {
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (rewindCount == 1) {
|
||||
rewindBackSeekPlayerPosition = getCurrentPosition();
|
||||
rewindLastTime = System.currentTimeMillis();
|
||||
rewindLastUpdatePlayerTime = rewindLastTime;
|
||||
startRewindFrom = getCurrentPosition();
|
||||
onRewindStart(rewindForward);
|
||||
}
|
||||
|
||||
AndroidUtilities.cancelRunOnUIThread(backSeek);
|
||||
AndroidUtilities.runOnUIThread(backSeek);
|
||||
|
||||
if (needUpdate) {
|
||||
if (updateRewindRunnable != null) {
|
||||
AndroidUtilities.cancelRunOnUIThread(updateRewindRunnable);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(updateRewindRunnable = () -> {
|
||||
updateRewindRunnable = null;
|
||||
incrementRewindCount();
|
||||
}, 2000);
|
||||
if (seekSpeedDrawable != null) {
|
||||
seekSpeedDrawable.setShown(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateRewindProgressUi(long timeDiff, float progress, boolean rewindByBackSeek) {
|
||||
|
||||
}
|
||||
|
@ -181,14 +258,34 @@ public class VideoPlayerRewinder {
|
|||
|
||||
}
|
||||
|
||||
private void seekTo(long position) {
|
||||
private void seekTo(long position, boolean fast) {
|
||||
if (webView != null) {
|
||||
webView.seekTo(position);
|
||||
} else {
|
||||
if (videoPlayer == null) {
|
||||
return;
|
||||
} else if (videoPlayer != null) {
|
||||
videoPlayer.seekTo(position, fast);
|
||||
}
|
||||
rewindBackSeekLastPlayerPosition = position;
|
||||
}
|
||||
|
||||
private void setMuted(boolean muted) {
|
||||
if (videoPlayer != null) {
|
||||
videoPlayer.setMute(muted);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPaused(boolean paused) {
|
||||
if (webView != null) {
|
||||
if (paused) {
|
||||
webView.pauseVideo();
|
||||
} else {
|
||||
webView.playVideo();
|
||||
}
|
||||
} else if (videoPlayer != null) {
|
||||
if (paused) {
|
||||
videoPlayer.pause();
|
||||
} else {
|
||||
videoPlayer.play();
|
||||
}
|
||||
videoPlayer.seekTo(position);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ public class VoIPActionsReceiver extends BroadcastReceiver {
|
|||
} else if ((packageName + ".ANSWER_CALL").equals(intent.getAction())) {
|
||||
VoIPPreNotificationService.answer(context);
|
||||
} else if ((packageName + ".HIDE_CALL").equals(intent.getAction())) {
|
||||
VoIPPreNotificationService.dismiss(context);
|
||||
VoIPPreNotificationService.dismiss(context, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,9 @@ import android.app.NotificationChannel;
|
|||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Person;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.media.AudioAttributes;
|
||||
|
@ -21,15 +18,12 @@ import android.media.MediaPlayer;
|
|||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.BuildVars;
|
||||
|
@ -400,7 +394,7 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
FileLog.d("VoIPPreNotification.show()");
|
||||
|
||||
if (call == null || intent == null) {
|
||||
dismiss(context);
|
||||
dismiss(context, false);
|
||||
FileLog.d("VoIPPreNotification.show(): call or intent is null");
|
||||
return;
|
||||
}
|
||||
|
@ -409,7 +403,7 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
return;
|
||||
}
|
||||
|
||||
dismiss(context);
|
||||
dismiss(context, false);
|
||||
|
||||
pendingVoIP = intent;
|
||||
pendingCall = call;
|
||||
|
@ -472,7 +466,7 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
if (currentState != null) {
|
||||
currentState.destroy();
|
||||
}
|
||||
dismiss(context);
|
||||
dismiss(context, false);
|
||||
} else if (whenAcknowledged != null) {
|
||||
whenAcknowledged.run();
|
||||
}
|
||||
|
@ -493,7 +487,7 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
context.startService(pendingVoIP);
|
||||
}
|
||||
pendingVoIP = null;
|
||||
dismiss(context);
|
||||
dismiss(context, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -533,7 +527,7 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
}
|
||||
pendingVoIP = null;
|
||||
}
|
||||
dismiss(context);
|
||||
dismiss(context, true);
|
||||
}
|
||||
|
||||
public static void decline(Context context, int reason) {
|
||||
|
@ -580,10 +574,10 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
}
|
||||
}
|
||||
}, ConnectionsManager.RequestFlagFailOnServerErrors);
|
||||
dismiss(context);
|
||||
dismiss(context, false);
|
||||
}
|
||||
|
||||
public static void dismiss(Context context) {
|
||||
public static void dismiss(Context context, boolean answered) {
|
||||
FileLog.d("VoIPPreNotification.dismiss()");
|
||||
pendingVoIP = null;
|
||||
pendingCall = null;
|
||||
|
@ -593,6 +587,11 @@ public class VoIPPreNotificationService { // } extends Service implements AudioM
|
|||
final NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.cancel(VoIPService.ID_INCOMING_CALL_PRENOTIFICATION);
|
||||
stopRinging();
|
||||
if (!answered) {
|
||||
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; ++i) {
|
||||
MessagesController.getInstance(i).ignoreSetOnline = false;
|
||||
}
|
||||
}
|
||||
// if (pendingNotificationService != null) {
|
||||
// context.stopService(pendingNotificationService);
|
||||
// }
|
||||
|
|
|
@ -2,7 +2,9 @@ package org.telegram.tgnet;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.InstallSourceInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
|
@ -10,6 +12,7 @@ import android.os.SystemClock;
|
|||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.play.core.integrity.IntegrityManager;
|
||||
import com.google.android.play.core.integrity.IntegrityManagerFactory;
|
||||
|
@ -38,6 +41,7 @@ import org.telegram.messenger.SharedConfig;
|
|||
import org.telegram.messenger.StatsController;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Components.VideoPlayer;
|
||||
import org.telegram.ui.LoginActivity;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -346,7 +350,7 @@ public class ConnectionsManager extends BaseController {
|
|||
object.freeResources();
|
||||
|
||||
long startRequestTime = 0;
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED || (connectionType & ConnectionTypeDownload) != 0) {
|
||||
startRequestTime = System.currentTimeMillis();
|
||||
}
|
||||
long finalStartRequestTime = startRequestTime;
|
||||
|
@ -377,6 +381,10 @@ public class ConnectionsManager extends BaseController {
|
|||
FileLog.e(object + " got error " + error.code + " " + error.text);
|
||||
}
|
||||
}
|
||||
if ((connectionType & ConnectionTypeDownload) != 0 && VideoPlayer.activePlayers.isEmpty()) {
|
||||
long ping_time = native_getCurrentPingTime(currentAccount);
|
||||
DefaultBandwidthMeter.getSingletonInstance(ApplicationLoader.applicationContext).onTransfer(responseSize, Math.max(0, (System.currentTimeMillis() - finalStartRequestTime) - ping_time));
|
||||
}
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION && !getUserConfig().isClientActivated() && error != null && error.code == 400 && Objects.equals(error.text, "CONNECTION_NOT_INITED")) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("Cleanup keys for " + currentAccount + " because of CONNECTION_NOT_INITED");
|
||||
|
@ -578,7 +586,18 @@ public class ConnectionsManager extends BaseController {
|
|||
}
|
||||
String installer = "";
|
||||
try {
|
||||
installer = ApplicationLoader.applicationContext.getPackageManager().getInstallerPackageName(ApplicationLoader.applicationContext.getPackageName());
|
||||
Context context = ApplicationLoader.applicationContext;
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
InstallSourceInfo installSourceInfo = context.getPackageManager().getInstallSourceInfo(context.getPackageName());
|
||||
if (installSourceInfo != null) {
|
||||
installer = installSourceInfo.getInitiatingPackageName();
|
||||
if (installer == null) {
|
||||
installer = installSourceInfo.getInstallingPackageName();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
installer = context.getPackageManager().getInstallerPackageName(context.getPackageName());
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
|
||||
}
|
||||
|
@ -906,6 +925,7 @@ public class ConnectionsManager extends BaseController {
|
|||
public static native void native_resumeNetwork(int currentAccount, boolean partial);
|
||||
public static native long native_getCurrentTimeMillis(int currentAccount);
|
||||
public static native int native_getCurrentTime(int currentAccount);
|
||||
public static native int native_getCurrentPingTime(int currentAccount);
|
||||
public static native int native_getCurrentDatacenterId(int currentAccount);
|
||||
public static native int native_getTimeDifference(int currentAccount);
|
||||
public static native void native_sendRequest(int currentAccount, long object, int flags, int datacenterId, int connectionType, boolean immediate, int requestToken);
|
||||
|
|
|
@ -81,8 +81,7 @@ public class TLRPC {
|
|||
public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800;
|
||||
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
|
||||
|
||||
public static final int LAYER = 191;
|
||||
|
||||
public static final int LAYER = 193;
|
||||
|
||||
public static abstract class EmailVerifyPurpose extends TLObject {
|
||||
|
||||
|
@ -5835,6 +5834,9 @@ public class TLRPC {
|
|||
case TL_privacyKeyBirthday.constructor:
|
||||
result = new TL_privacyKeyBirthday();
|
||||
break;
|
||||
case TL_privacyKeyStarGiftsAutoSave.constructor:
|
||||
result = new TL_privacyKeyStarGiftsAutoSave();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in PrivacyKey", constructor));
|
||||
|
@ -5945,6 +5947,15 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_privacyKeyStarGiftsAutoSave extends PrivacyKey {
|
||||
public static final int constructor = 0x2ca4fdf8;
|
||||
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class GeoPoint extends TLObject {
|
||||
public int flags;
|
||||
public double _long;
|
||||
|
@ -8238,6 +8249,12 @@ public class TLRPC {
|
|||
case 0xece9814b:
|
||||
result = new TL_privacyValueAllowPremium();
|
||||
break;
|
||||
case TL_privacyValueAllowBots.constructor:
|
||||
result = new TL_privacyValueAllowBots();
|
||||
break;
|
||||
case TL_privacyValueDisallowBots.constructor:
|
||||
result = new TL_privacyValueDisallowBots();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in PrivacyRule", constructor));
|
||||
|
@ -8423,6 +8440,24 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_privacyValueAllowBots extends PrivacyRule {
|
||||
public static final int constructor = 0x21461b5d;
|
||||
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_privacyValueDisallowBots extends PrivacyRule {
|
||||
public static final int constructor = 0xf6a5f82f;
|
||||
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_pageTableCell extends TLObject {
|
||||
public static final int constructor = 0x34566b6a;
|
||||
|
||||
|
@ -12459,6 +12494,9 @@ public class TLRPC {
|
|||
case TL_inputPrivacyKeyBirthday.constructor:
|
||||
result = new TL_inputPrivacyKeyBirthday();
|
||||
break;
|
||||
case TL_inputPrivacyKeyStarGiftsAutoSave.constructor:
|
||||
result = new TL_inputPrivacyKeyStarGiftsAutoSave();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in InputPrivacyKey", constructor));
|
||||
|
@ -12551,6 +12589,15 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_inputPrivacyKeyStarGiftsAutoSave extends InputPrivacyKey {
|
||||
public static final int constructor = 0xe1732341;
|
||||
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_inputPrivacyKeyProfilePhoto extends InputPrivacyKey {
|
||||
public static final int constructor = 0x5719bacc;
|
||||
|
||||
|
@ -28263,6 +28310,9 @@ public class TLRPC {
|
|||
case TL_messageActionStarGift.constructor:
|
||||
result = new TL_messageActionStarGift();
|
||||
break;
|
||||
case TL_messageActionStarGift_layer192.constructor:
|
||||
result = new TL_messageActionStarGift_layer192();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in MessageAction", constructor));
|
||||
|
@ -29989,7 +30039,7 @@ public class TLRPC {
|
|||
}
|
||||
|
||||
public static class TL_invoice extends TLObject {
|
||||
public static final int constructor = 0x5db95a15;
|
||||
public static final int constructor = 0x49ee584;
|
||||
|
||||
public int flags;
|
||||
public boolean test;
|
||||
|
@ -30006,13 +30056,17 @@ public class TLRPC {
|
|||
public long max_tip_amount;
|
||||
public ArrayList<Long> suggested_tip_amounts = new ArrayList<>();
|
||||
public String terms_url;
|
||||
public int subscription_period;
|
||||
|
||||
public static TL_invoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
TL_invoice result = null;
|
||||
switch (constructor) {
|
||||
case 0x5db95a15:
|
||||
case 0x49ee584:
|
||||
result = new TL_invoice();
|
||||
break;
|
||||
case 0x5db95a15:
|
||||
result = new TL_invoice_layer193();
|
||||
break;
|
||||
case 0x3e85a91b:
|
||||
result = new TL_invoice_layer163();
|
||||
break;
|
||||
|
@ -30026,6 +30080,99 @@ public class TLRPC {
|
|||
return result;
|
||||
}
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
test = (flags & 1) != 0;
|
||||
name_requested = (flags & 2) != 0;
|
||||
phone_requested = (flags & 4) != 0;
|
||||
email_requested = (flags & 8) != 0;
|
||||
shipping_address_requested = (flags & 16) != 0;
|
||||
flexible = (flags & 32) != 0;
|
||||
phone_to_provider = (flags & 64) != 0;
|
||||
email_to_provider = (flags & 128) != 0;
|
||||
recurring = (flags & 512) != 0;
|
||||
currency = stream.readString(exception);
|
||||
int magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
int count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
TL_labeledPrice object = TL_labeledPrice.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
prices.add(object);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
max_tip_amount = stream.readInt64(exception);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
suggested_tip_amounts.add(stream.readInt64(exception));
|
||||
}
|
||||
}
|
||||
if ((flags & 1024) != 0) {
|
||||
terms_url = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 2048) != 0) {
|
||||
subscription_period = stream.readInt32(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = test ? (flags | 1) : (flags &~ 1);
|
||||
flags = name_requested ? (flags | 2) : (flags &~ 2);
|
||||
flags = phone_requested ? (flags | 4) : (flags &~ 4);
|
||||
flags = email_requested ? (flags | 8) : (flags &~ 8);
|
||||
flags = shipping_address_requested ? (flags | 16) : (flags &~ 16);
|
||||
flags = flexible ? (flags | 32) : (flags &~ 32);
|
||||
flags = phone_to_provider ? (flags | 64) : (flags &~ 64);
|
||||
flags = email_to_provider ? (flags | 128) : (flags &~ 128);
|
||||
flags = recurring ? (flags | 512) : (flags &~ 512);
|
||||
stream.writeInt32(flags);
|
||||
stream.writeString(currency);
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
int count = prices.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
prices.get(a).serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
stream.writeInt64(max_tip_amount);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
count = suggested_tip_amounts.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
stream.writeInt64(suggested_tip_amounts.get(a));
|
||||
}
|
||||
}
|
||||
if ((flags & 1024) != 0) {
|
||||
stream.writeString(terms_url);
|
||||
}
|
||||
if ((flags & 2048) != 0) {
|
||||
stream.writeInt32(subscription_period);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_invoice_layer193 extends TL_invoice {
|
||||
public static final int constructor = 0x5db95a15;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
test = (flags & 1) != 0;
|
||||
|
@ -33930,36 +34077,42 @@ public class TLRPC {
|
|||
public static InputPrivacyRule TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
InputPrivacyRule result = null;
|
||||
switch (constructor) {
|
||||
case 0xd66b66c9:
|
||||
case TL_inputPrivacyValueDisallowAll.constructor:
|
||||
result = new TL_inputPrivacyValueDisallowAll();
|
||||
break;
|
||||
case 0x90110467:
|
||||
case TL_inputPrivacyValueDisallowUsers.constructor:
|
||||
result = new TL_inputPrivacyValueDisallowUsers();
|
||||
break;
|
||||
case 0xd09e07b:
|
||||
case TL_inputPrivacyValueAllowContacts.constructor:
|
||||
result = new TL_inputPrivacyValueAllowContacts();
|
||||
break;
|
||||
case 0x840649cf:
|
||||
case TL_inputPrivacyValueAllowChatParticipants.constructor:
|
||||
result = new TL_inputPrivacyValueAllowChatParticipants();
|
||||
break;
|
||||
case 0xba52007:
|
||||
case TL_inputPrivacyValueDisallowContacts.constructor:
|
||||
result = new TL_inputPrivacyValueDisallowContacts();
|
||||
break;
|
||||
case 0x184b35ce:
|
||||
case TL_inputPrivacyValueAllowAll.constructor:
|
||||
result = new TL_inputPrivacyValueAllowAll();
|
||||
break;
|
||||
case 0x131cc67f:
|
||||
case TL_inputPrivacyValueAllowUsers.constructor:
|
||||
result = new TL_inputPrivacyValueAllowUsers();
|
||||
break;
|
||||
case 0xe94f0f86:
|
||||
case TL_inputPrivacyValueDisallowChatParticipants.constructor:
|
||||
result = new TL_inputPrivacyValueDisallowChatParticipants();
|
||||
break;
|
||||
case 0x2f453e49:
|
||||
case TL_inputPrivacyValueAllowCloseFriends.constructor:
|
||||
result = new TL_inputPrivacyValueAllowCloseFriends();
|
||||
break;
|
||||
case 0x77cdc9f1:
|
||||
case TL_inputPrivacyValueAllowPremium.constructor:
|
||||
result = new TL_inputPrivacyValueAllowPremium();
|
||||
break;
|
||||
case TL_inputPrivacyValueAllowBots.constructor:
|
||||
result = new TL_inputPrivacyValueAllowBots();
|
||||
break;
|
||||
case TL_inputPrivacyValueDisallowBots.constructor:
|
||||
result = new TL_inputPrivacyValueDisallowBots();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in InputPrivacyRule", constructor));
|
||||
|
@ -34151,6 +34304,22 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_inputPrivacyValueAllowBots extends InputPrivacyRule {
|
||||
public static final int constructor = 0x5a4fcce5;
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_inputPrivacyValueDisallowBots extends InputPrivacyRule {
|
||||
public static final int constructor = 0xc4e57915;
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_maskCoords extends TLObject {
|
||||
public static final int constructor = 0xaed6dbb2;
|
||||
|
||||
|
@ -36515,6 +36684,9 @@ public class TLRPC {
|
|||
case TL_updatePaidReactionPrivacy.constructor:
|
||||
result = new TL_updatePaidReactionPrivacy();
|
||||
break;
|
||||
case TL_updateBotSubscriptionExpire.constructor:
|
||||
result = new TL_updateBotSubscriptionExpire();
|
||||
break;
|
||||
}
|
||||
if (result == null && ApplicationLoader.applicationLoaderInstance != null) {
|
||||
result = ApplicationLoader.applicationLoaderInstance.parseTLUpdate(constructor);
|
||||
|
@ -38401,12 +38573,15 @@ public class TLRPC {
|
|||
}
|
||||
|
||||
public static class TL_updateDeleteScheduledMessages extends Update {
|
||||
public static final int constructor = 0x90866cee;
|
||||
public static final int constructor = 0xf2a71983;
|
||||
|
||||
public int flags;
|
||||
public Peer peer;
|
||||
public ArrayList<Integer> messages = new ArrayList<>();
|
||||
public ArrayList<Integer> sent_messages = new ArrayList<>();
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
int magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
|
@ -38419,10 +38594,24 @@ public class TLRPC {
|
|||
for (int a = 0; a < count; a++) {
|
||||
messages.add(stream.readInt32(exception));
|
||||
}
|
||||
if ((flags & 1) != 0) {
|
||||
magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
sent_messages.add(stream.readInt32(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(flags);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
int count = messages.size();
|
||||
|
@ -38430,6 +38619,14 @@ public class TLRPC {
|
|||
for (int a = 0; a < count; a++) {
|
||||
stream.writeInt32(messages.get(a));
|
||||
}
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
count = sent_messages.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
stream.writeInt32(sent_messages.get(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43655,10 +43852,10 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_channels_reportSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0xaf8ff6b9;
|
||||
public static class TL_messages_reportSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0x1af3dbb8;
|
||||
|
||||
public InputChannel channel;
|
||||
public InputPeer peer;
|
||||
public byte[] random_id;
|
||||
public byte[] option;
|
||||
|
||||
|
@ -43668,7 +43865,7 @@ public class TLRPC {
|
|||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeByteArray(random_id);
|
||||
stream.writeByteArray(option);
|
||||
}
|
||||
|
@ -54167,6 +54364,7 @@ public class TLRPC {
|
|||
public boolean phone_calls_available;
|
||||
public boolean phone_calls_private;
|
||||
public boolean can_pin_message;
|
||||
public boolean bot_can_manage_emoji_status;
|
||||
public boolean has_scheduled;
|
||||
public boolean video_calls_available;
|
||||
public boolean voice_messages_forbidden;
|
||||
|
@ -54177,6 +54375,7 @@ public class TLRPC {
|
|||
public boolean contact_require_premium;
|
||||
public boolean read_dates_private;
|
||||
public boolean sponsored_enabled;
|
||||
public boolean can_view_revenue;
|
||||
public User user;
|
||||
public String about;
|
||||
public TL_contacts_link_layer101 link;
|
||||
|
@ -54296,6 +54495,8 @@ public class TLRPC {
|
|||
read_dates_private = (flags & 1073741824) != 0;
|
||||
flags2 = stream.readInt32(exception);
|
||||
sponsored_enabled = (flags2 & 128) != 0;
|
||||
can_view_revenue = (flags2 & 512) != 0;
|
||||
bot_can_manage_emoji_status = (flags2 & 1024) != 0;
|
||||
id = stream.readInt64(exception);
|
||||
if ((flags & 2) != 0) {
|
||||
about = stream.readString(exception);
|
||||
|
@ -54403,6 +54604,8 @@ public class TLRPC {
|
|||
flags = read_dates_private ? (flags | 1073741824) : (flags &~ 1073741824);
|
||||
stream.writeInt32(flags);
|
||||
flags2 = sponsored_enabled ? (flags2 | 128) : (flags2 &~ 128);
|
||||
flags2 = can_view_revenue ? (flags2 | 512) : (flags2 &~ 512);
|
||||
flags2 = bot_can_manage_emoji_status ? (flags2 | 1024) : (flags2 &~ 1024);
|
||||
stream.writeInt32(flags2);
|
||||
stream.writeInt64(id);
|
||||
if ((flags & 2) != 0) {
|
||||
|
@ -66762,10 +66965,10 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_channels_viewSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0xbeaedb94;
|
||||
public static class TL_messages_viewSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0x673ad8f1;
|
||||
|
||||
public InputChannel channel;
|
||||
public InputPeer peer;
|
||||
public byte[] random_id;
|
||||
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
|
@ -66774,15 +66977,15 @@ public class TLRPC {
|
|||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeByteArray(random_id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_channels_getSponsoredMessages extends TLObject {
|
||||
public static final int constructor = 0xec210fbf;
|
||||
public static class TL_messages_getSponsoredMessages extends TLObject {
|
||||
public static final int constructor = 0x9bd2f439;
|
||||
|
||||
public InputChannel channel;
|
||||
public InputPeer peer;
|
||||
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
return messages_SponsoredMessages.TLdeserialize(stream, constructor, exception);
|
||||
|
@ -66790,7 +66993,7 @@ public class TLRPC {
|
|||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69174,6 +69377,7 @@ public class TLRPC {
|
|||
public boolean noforwards;
|
||||
public boolean invert_media;
|
||||
public boolean offline;
|
||||
public boolean video_processing_pending;
|
||||
public TL_factCheck factcheck;
|
||||
public int send_state = 0; //custom
|
||||
public int fwd_msg_id = 0; //custom
|
||||
|
@ -70050,6 +70254,7 @@ public class TLRPC {
|
|||
invert_media = (flags & 134217728) != 0;
|
||||
flags2 = stream.readInt32(exception);
|
||||
offline = (flags2 & 2) != 0;
|
||||
video_processing_pending = (flags2 & 16) != 0;
|
||||
id = stream.readInt32(exception);
|
||||
if ((flags & 256) != 0) {
|
||||
from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
|
@ -70171,6 +70376,7 @@ public class TLRPC {
|
|||
flags = invert_media ? (flags | 134217728) : (flags &~ 134217728);
|
||||
stream.writeInt32(flags);
|
||||
flags2 = offline ? (flags2 | 2) : (flags2 &~ 2);
|
||||
flags2 = video_processing_pending ? (flags2 | 16) : (flags2 &~ 16);
|
||||
stream.writeInt32(flags2);
|
||||
stream.writeInt32(id);
|
||||
if ((flags & 256) != 0) {
|
||||
|
@ -75101,6 +75307,7 @@ public class TLRPC {
|
|||
|
||||
public int flags;
|
||||
public boolean fullsize;
|
||||
public boolean fullscreen;
|
||||
public long query_id;
|
||||
public String url;
|
||||
|
||||
|
@ -75120,6 +75327,7 @@ public class TLRPC {
|
|||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
fullsize = (flags & 2) != 0;
|
||||
fullscreen = (flags & 4) != 0;
|
||||
if ((flags & 1) != 0) {
|
||||
query_id = stream.readInt64(exception);
|
||||
}
|
||||
|
@ -75129,6 +75337,7 @@ public class TLRPC {
|
|||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = fullsize ? flags | 2 : flags &~ 2;
|
||||
flags = fullscreen ? flags | 4 : flags &~ 4;
|
||||
stream.writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeInt64(query_id);
|
||||
|
@ -75144,6 +75353,7 @@ public class TLRPC {
|
|||
public boolean from_bot_menu;
|
||||
public boolean silent;
|
||||
public boolean compact;
|
||||
public boolean fullscreen;
|
||||
public InputPeer peer;
|
||||
public InputUser bot;
|
||||
public String url;
|
||||
|
@ -75162,6 +75372,7 @@ public class TLRPC {
|
|||
flags = from_bot_menu ? (flags | 16) : (flags &~ 16);
|
||||
flags = silent ? (flags | 32) : (flags &~ 32);
|
||||
flags = compact ? (flags | 128) : (flags &~ 128);
|
||||
flags = fullscreen ? (flags | 256) : (flags &~ 256);
|
||||
stream.writeInt32(flags);
|
||||
peer.serializeToStream(stream);
|
||||
bot.serializeToStream(stream);
|
||||
|
@ -75189,6 +75400,7 @@ public class TLRPC {
|
|||
|
||||
public int flags;
|
||||
public boolean compact;
|
||||
public boolean fullscreen;
|
||||
public InputPeer peer;
|
||||
public InputUser bot;
|
||||
public String start_param;
|
||||
|
@ -75202,6 +75414,7 @@ public class TLRPC {
|
|||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = compact ? (flags | 128) : (flags &~ 128);
|
||||
flags = fullscreen ? (flags | 256) : (flags &~ 256);
|
||||
stream.writeInt32(flags);
|
||||
peer.serializeToStream(stream);
|
||||
bot.serializeToStream(stream);
|
||||
|
@ -75269,6 +75482,7 @@ public class TLRPC {
|
|||
public int flags;
|
||||
public boolean write_allowed;
|
||||
public boolean compact;
|
||||
public boolean fullscreen;
|
||||
public InputPeer peer;
|
||||
public InputBotApp app;
|
||||
public String start_param;
|
||||
|
@ -75283,6 +75497,7 @@ public class TLRPC {
|
|||
stream.writeInt32(constructor);
|
||||
flags = write_allowed ? (flags | 1) : (flags &~ 1);
|
||||
flags = compact ? (flags | 128) : (flags &~ 128);
|
||||
flags = fullscreen ? (flags | 256) : (flags &~ 256);
|
||||
stream.writeInt32(flags);
|
||||
peer.serializeToStream(stream);
|
||||
app.serializeToStream(stream);
|
||||
|
@ -75303,6 +75518,7 @@ public class TLRPC {
|
|||
public boolean from_switch_webview;
|
||||
public boolean from_side_menu;
|
||||
public boolean compact;
|
||||
public boolean fullscreen;
|
||||
public InputUser bot;
|
||||
public String url;
|
||||
public String start_param;
|
||||
|
@ -75318,6 +75534,7 @@ public class TLRPC {
|
|||
flags = from_switch_webview ? (flags | 2) : (flags &~ 2);
|
||||
flags = from_side_menu ? (flags | 4) : (flags &~ 4);
|
||||
flags = compact ? (flags | 128) : (flags &~ 128);
|
||||
flags = fullscreen ? (flags | 256) : (flags &~ 256);
|
||||
stream.writeInt32(flags);
|
||||
bot.serializeToStream(stream);
|
||||
if ((flags & 8) != 0) {
|
||||
|
@ -77414,13 +77631,13 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_channels_clickSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0x1445d75;
|
||||
public static class TL_messages_clickSponsoredMessage extends TLObject {
|
||||
public static final int constructor = 0xf093465;
|
||||
|
||||
public int flags;
|
||||
public boolean media;
|
||||
public boolean fullscreen;
|
||||
public InputChannel channel;
|
||||
public InputPeer peer;
|
||||
public byte[] random_id;
|
||||
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
|
@ -77432,7 +77649,7 @@ public class TLRPC {
|
|||
flags = media ? flags | 1 : flags &~ 1;
|
||||
flags = fullscreen ? flags | 2 : flags &~ 2;
|
||||
stream.writeInt32(flags);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeByteArray(random_id);
|
||||
}
|
||||
}
|
||||
|
@ -78086,7 +78303,7 @@ public class TLRPC {
|
|||
|
||||
public static class TL_updatePaidReactionPrivacy extends Update {
|
||||
public static final int constructor = 0x51ca7aec;
|
||||
|
||||
|
||||
public boolean isPrivate;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
|
@ -78099,6 +78316,30 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_updateBotSubscriptionExpire extends Update {
|
||||
public static final int constructor = 0xa8ae3eb1;
|
||||
|
||||
public long user_id;
|
||||
public String payload;
|
||||
public int until_date;
|
||||
public int qts;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
user_id = stream.readInt64(exception);
|
||||
payload = stream.readString(exception);
|
||||
until_date = stream.readInt32(exception);
|
||||
qts = stream.readInt32(exception);
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt64(user_id);
|
||||
stream.writeString(payload);
|
||||
stream.writeInt32(until_date);
|
||||
stream.writeInt32(qts);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_updateSavedDialogPinned extends Update {
|
||||
public static final int constructor = 0xaeaf9e74;
|
||||
|
||||
|
@ -79954,19 +80195,9 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_messageActionStarGift extends MessageAction {
|
||||
public static class TL_messageActionStarGift_layer192 extends TL_messageActionStarGift {
|
||||
public static final int constructor = 0x9bb3ef44;
|
||||
|
||||
public int flags;
|
||||
public boolean name_hidden;
|
||||
public boolean saved;
|
||||
public boolean converted;
|
||||
public TL_stars.StarGift gift;
|
||||
public TL_textWithEntities message;
|
||||
public long convert_stars;
|
||||
|
||||
public boolean forceIn; //custom
|
||||
|
||||
@Override
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
|
@ -79994,6 +80225,50 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_messageActionStarGift extends MessageAction {
|
||||
public static final int constructor = 0x8557637;
|
||||
|
||||
public int flags;
|
||||
public boolean name_hidden;
|
||||
public boolean saved;
|
||||
public boolean converted;
|
||||
public TL_stars.StarGift gift;
|
||||
public TL_textWithEntities message;
|
||||
public long convert_stars;
|
||||
|
||||
public boolean forceIn; //custom
|
||||
|
||||
@Override
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
name_hidden = (flags & 1) != 0;
|
||||
saved = (flags & 4) != 0;
|
||||
converted = (flags & 8) != 0;
|
||||
gift = TL_stars.StarGift.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if ((flags & 2) != 0) {
|
||||
message = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
convert_stars = stream.readInt64(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = name_hidden ? (flags | 1) : (flags &~ 1);
|
||||
flags = saved ? (flags | 4) : (flags &~ 4);
|
||||
flags = converted ? (flags | 8) : (flags &~ 8);
|
||||
stream.writeInt32(flags);
|
||||
gift.serializeToStream(stream);
|
||||
if ((flags & 2) != 0) {
|
||||
message.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
stream.writeInt64(convert_stars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_channels_updateEmojiStatus extends TLObject {
|
||||
public static final int constructor = 0xf0d3e6a8;
|
||||
|
||||
|
@ -83768,5 +84043,104 @@ public class TLRPC {
|
|||
stream.writeString(provider_charge_id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_messages_preparedInlineMessage extends TLObject {
|
||||
public static final int constructor = 0xff57708d;
|
||||
|
||||
public long query_id;
|
||||
public BotInlineResult result;
|
||||
public ArrayList<InlineQueryPeerType> peer_types = new ArrayList<>();
|
||||
public int cache_time;
|
||||
public ArrayList<User> users = new ArrayList<>();
|
||||
|
||||
public static TL_messages_preparedInlineMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
if (TL_messages_preparedInlineMessage.constructor != constructor) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in TL_messages_preparedInlineMessage", constructor));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
TL_messages_preparedInlineMessage result = new TL_messages_preparedInlineMessage();
|
||||
result.readParams(stream, exception);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
query_id = stream.readInt64(exception);
|
||||
result = BotInlineResult.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
int magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
int count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
InlineQueryPeerType object = InlineQueryPeerType.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
peer_types.add(object);
|
||||
}
|
||||
cache_time = stream.readInt32(exception);
|
||||
magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
User object = User.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
users.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt64(query_id);
|
||||
result.serializeToStream(stream);
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
int count = peer_types.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
peer_types.get(a).serializeToStream(stream);
|
||||
}
|
||||
stream.writeInt32(cache_time);
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
count = users.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
users.get(a).serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_messages_getPreparedInlineMessage extends TLObject {
|
||||
public static final int constructor = 0x857ebdb8;
|
||||
|
||||
public InputUser bot;
|
||||
public String id;
|
||||
|
||||
@Override
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
return TL_messages_preparedInlineMessage.TLdeserialize(stream, constructor, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
bot.serializeToStream(stream);
|
||||
stream.writeString(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package org.telegram.tgnet.tl;
|
||||
|
||||
import android.graphics.Path;
|
||||
|
||||
import org.telegram.messenger.SvgHelper;
|
||||
import org.telegram.tgnet.AbstractSerializedData;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
|
@ -352,6 +355,7 @@ public class TL_bots {
|
|||
public TLRPC.Document description_document;
|
||||
public boolean has_preview_medias;
|
||||
public String privacy_policy_url;
|
||||
public botAppSettings app_settings;
|
||||
|
||||
public static BotInfo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
BotInfo result = null;
|
||||
|
@ -374,6 +378,9 @@ public class TL_bots {
|
|||
case TL_botInfo_layer185.constructor:
|
||||
result = new TL_botInfo_layer185();
|
||||
break;
|
||||
case TL_botInfo_layer192.constructor:
|
||||
result = new TL_botInfo_layer192();
|
||||
break;
|
||||
case TL_botInfo.constructor:
|
||||
result = new TL_botInfo();
|
||||
break;
|
||||
|
@ -513,6 +520,89 @@ public class TL_bots {
|
|||
}
|
||||
|
||||
public static class TL_botInfo extends BotInfo {
|
||||
public static final int constructor = 0x36607333;
|
||||
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
has_preview_medias = (flags & 64) != 0;
|
||||
if ((flags & 1) != 0) {
|
||||
user_id = stream.readInt64(exception);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
description = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
description_photo = TLRPC.Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
description_document = TLRPC.Document.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
int magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
int count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
TLRPC.TL_botCommand object = TLRPC.TL_botCommand.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
commands.add(object);
|
||||
}
|
||||
}
|
||||
if ((flags & 8) != 0) {
|
||||
menu_button = BotMenuButton.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 128) != 0) {
|
||||
privacy_policy_url = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
app_settings = botAppSettings.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = has_preview_medias ? flags | 64 : flags &~ 64;
|
||||
stream.writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeInt64(user_id);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
stream.writeString(description);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
description_photo.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
description_document.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
int count = commands.size();
|
||||
stream.writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
commands.get(a).serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
if ((flags & 8) != 0) {
|
||||
menu_button.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 128) != 0) {
|
||||
stream.writeString(privacy_policy_url);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
app_settings.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_botInfo_layer192 extends TL_botInfo {
|
||||
public static final int constructor = 0x82437e74;
|
||||
|
||||
|
||||
|
@ -934,4 +1024,113 @@ public class TL_bots {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class botAppSettings extends TLObject {
|
||||
public static final int constructor = 0xc99b1950;
|
||||
|
||||
public int flags;
|
||||
public byte[] placeholder_path;
|
||||
public Path placeholder_svg_path; //custom
|
||||
public int background_color;
|
||||
public int background_dark_color;
|
||||
public int header_color;
|
||||
public int header_dark_color;
|
||||
|
||||
public static botAppSettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
if (botAppSettings.constructor != constructor) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in botAppSettings", constructor));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
botAppSettings result = new botAppSettings();
|
||||
result.readParams(stream, exception);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
if ((flags & 1) != 0) {
|
||||
placeholder_path = stream.readByteArray(exception);
|
||||
placeholder_svg_path = SvgHelper.doPath(SvgHelper.decompress(placeholder_path));
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
background_color = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
background_dark_color = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 8) != 0) {
|
||||
header_color = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
header_dark_color = stream.readInt32(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeByteArray(placeholder_path);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
stream.writeInt32(background_color);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
stream.writeInt32(background_dark_color);
|
||||
}
|
||||
if ((flags & 8) != 0) {
|
||||
stream.writeInt32(header_color);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
stream.writeInt32(header_dark_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class toggleUserEmojiStatusPermission extends TLObject {
|
||||
public static final int constructor = 0x6de6392;
|
||||
|
||||
public TLRPC.InputUser bot;
|
||||
public boolean enabled;
|
||||
|
||||
@Override
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
return TLRPC.Bool.TLdeserialize(stream, constructor, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
bot.serializeToStream(stream);
|
||||
stream.writeBool(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public static class checkDownloadFileParams extends TLObject {
|
||||
public static final int constructor = 0x50077589;
|
||||
|
||||
public TLRPC.InputUser bot;
|
||||
public String file_name;
|
||||
public String url;
|
||||
|
||||
@Override
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
return TLRPC.Bool.TLdeserialize(stream, constructor, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
bot.serializeToStream(stream);
|
||||
stream.writeString(file_name);
|
||||
stream.writeString(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ public class TL_stars {
|
|||
public int flags;
|
||||
public boolean limited;
|
||||
public boolean sold_out;
|
||||
public boolean birthday;
|
||||
public long id;
|
||||
public TLRPC.Document sticker;
|
||||
public long stars;
|
||||
|
@ -51,6 +52,7 @@ public class TL_stars {
|
|||
stream.writeInt32(constructor);
|
||||
flags = limited ? flags | 1 : flags &~ 1;
|
||||
flags = sold_out ? flags | 2 : flags &~ 2;
|
||||
flags = birthday ? flags | 4 : flags &~ 4;
|
||||
stream.writeInt32(flags);
|
||||
stream.writeInt64(id);
|
||||
sticker.serializeToStream(stream);
|
||||
|
@ -71,6 +73,7 @@ public class TL_stars {
|
|||
flags = stream.readInt32(exception);
|
||||
limited = (flags & 1) != 0;
|
||||
sold_out = (flags & 2) != 0;
|
||||
birthday = (flags & 4) != 0;
|
||||
id = stream.readInt64(exception);
|
||||
sticker = TLRPC.Document.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
stars = stream.readInt64(exception);
|
||||
|
@ -671,6 +674,9 @@ public class TL_stars {
|
|||
case TL_starsTransactionPeerAds.constructor:
|
||||
result = new TL_starsTransactionPeerAds();
|
||||
break;
|
||||
case TL_starsTransactionPeerAPI.constructor:
|
||||
result = new TL_starsTransactionPeerAPI();
|
||||
break;
|
||||
}
|
||||
if (result == null && exception) {
|
||||
throw new RuntimeException(String.format("can't parse magic %x in StarsTransactionPeer", constructor));
|
||||
|
@ -755,6 +761,16 @@ public class TL_stars {
|
|||
}
|
||||
}
|
||||
|
||||
public static class TL_starsTransactionPeerAPI extends StarsTransactionPeer {
|
||||
public static final int constructor = 0xf9677aad;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StarsTransaction extends TLObject {
|
||||
|
||||
public int flags;
|
||||
|
@ -764,6 +780,7 @@ public class TL_stars {
|
|||
public boolean gift;
|
||||
public boolean reaction;
|
||||
public boolean subscription;
|
||||
public boolean floodskip;
|
||||
public String id;
|
||||
public long stars;
|
||||
public int date;
|
||||
|
@ -779,6 +796,7 @@ public class TL_stars {
|
|||
public int subscription_period;
|
||||
public int giveaway_post_id;
|
||||
public StarGift stargift;
|
||||
public int floodskip_number;
|
||||
|
||||
public TLRPC.Peer sent_by; //custom
|
||||
public TLRPC.Peer received_by; //custom
|
||||
|
@ -801,6 +819,9 @@ public class TL_stars {
|
|||
case TL_starsTransaction_layer188.constructor:
|
||||
result = new TL_starsTransaction_layer188();
|
||||
break;
|
||||
case TL_starsTransaction_layer191.constructor:
|
||||
result = new TL_starsTransaction_layer191();
|
||||
break;
|
||||
case TL_starsTransaction.constructor:
|
||||
result = new TL_starsTransaction();
|
||||
break;
|
||||
|
@ -909,6 +930,127 @@ public class TL_stars {
|
|||
}
|
||||
|
||||
public static class TL_starsTransaction extends StarsTransaction {
|
||||
public static final int constructor = 0x35d4f276;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
refund = (flags & 8) != 0;
|
||||
pending = (flags & 16) != 0;
|
||||
failed = (flags & 64) != 0;
|
||||
gift = (flags & 1024) != 0;
|
||||
reaction = (flags & 2048) != 0;
|
||||
subscription = (flags & 4096) != 0;
|
||||
floodskip = (flags & 32768) != 0;
|
||||
id = stream.readString(exception);
|
||||
stars = stream.readInt64(exception);
|
||||
date = stream.readInt32(exception);
|
||||
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if ((flags & 1) != 0) {
|
||||
title = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
description = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
transaction_date = stream.readInt32(exception);
|
||||
transaction_url = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 128) != 0) {
|
||||
bot_payload = stream.readByteArray(exception);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
msg_id = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 512) != 0) {
|
||||
int magic = stream.readInt32(exception);
|
||||
if (magic != 0x1cb5c415) {
|
||||
if (exception) {
|
||||
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
|
||||
}
|
||||
return;
|
||||
}
|
||||
int count = stream.readInt32(exception);
|
||||
for (int a = 0; a < count; a++) {
|
||||
TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
extended_media.add(object);
|
||||
}
|
||||
}
|
||||
if ((flags & 4096) != 0) {
|
||||
subscription_period = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 8192) != 0) {
|
||||
giveaway_post_id = stream.readInt32(exception);
|
||||
}
|
||||
if ((flags & 16384) != 0) {
|
||||
stargift = StarGift.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 32768) != 0) {
|
||||
floodskip_number = stream.readInt32(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = refund ? flags | 8 : flags &~ 8;
|
||||
flags = pending ? flags | 16 : flags &~ 16;
|
||||
flags = failed ? flags | 64 : flags &~ 64;
|
||||
flags = gift ? flags | 1024 : flags &~ 1024;
|
||||
flags = reaction ? flags | 2048 : flags &~ 2048;
|
||||
flags = subscription ? flags | 4096 : flags &~ 4096;
|
||||
flags = floodskip ? flags | 32768 : flags &~ 32768;
|
||||
stream.writeInt32(flags);
|
||||
stream.writeInt64(stars);
|
||||
stream.writeInt32(date);
|
||||
peer.serializeToStream(stream);
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeString(title);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
stream.writeString(description);
|
||||
}
|
||||
if ((flags & 4) != 0) {
|
||||
photo.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
stream.writeInt32(transaction_date);
|
||||
stream.writeString(transaction_url);
|
||||
}
|
||||
if ((flags & 128) != 0) {
|
||||
stream.writeByteArray(bot_payload);
|
||||
}
|
||||
if ((flags & 256) != 0) {
|
||||
stream.writeInt32(msg_id);
|
||||
}
|
||||
if ((flags & 512) != 0) {
|
||||
stream.writeInt32(0x1cb5c415);
|
||||
int count = extended_media.size();
|
||||
stream.writeInt32(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
extended_media.get(i).serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
if ((flags & 4096) != 0) {
|
||||
stream.writeInt32(subscription_period);
|
||||
}
|
||||
if ((flags & 8192) != 0) {
|
||||
stream.writeInt32(giveaway_post_id);
|
||||
}
|
||||
if ((flags & 16384) != 0) {
|
||||
stargift.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 32768) != 0) {
|
||||
stream.writeInt32(floodskip_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_starsTransaction_layer191 extends TL_starsTransaction {
|
||||
public static final int constructor = 0xa9ee4c2;
|
||||
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
|
@ -1597,11 +1739,15 @@ public class TL_stars {
|
|||
public boolean canceled;
|
||||
public boolean can_refulfill;
|
||||
public boolean missing_balance;
|
||||
public boolean bot_canceled;
|
||||
public String id;
|
||||
public TLRPC.Peer peer;
|
||||
public int until_date;
|
||||
public TL_starsSubscriptionPricing pricing;
|
||||
public String chat_invite_hash;
|
||||
public String title;
|
||||
public TLRPC.WebDocument photo;
|
||||
public String invoice_slug;
|
||||
|
||||
public static StarsSubscription TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
StarsSubscription result = null;
|
||||
|
@ -1609,6 +1755,9 @@ public class TL_stars {
|
|||
case TL_starsSubscription.constructor:
|
||||
result = new TL_starsSubscription();
|
||||
break;
|
||||
case TL_starsSubscription_layer193.constructor:
|
||||
result = new TL_starsSubscription_layer193();
|
||||
break;
|
||||
case TL_starsSubscription_old.constructor:
|
||||
result = new TL_starsSubscription_old();
|
||||
break;
|
||||
|
@ -1625,6 +1774,61 @@ public class TL_stars {
|
|||
}
|
||||
|
||||
public static class TL_starsSubscription extends StarsSubscription {
|
||||
public static final int constructor = 0x2e6eab1a;
|
||||
|
||||
@Override
|
||||
public void readParams(AbstractSerializedData stream, boolean exception) {
|
||||
flags = stream.readInt32(exception);
|
||||
canceled = (flags & 1) != 0;
|
||||
can_refulfill = (flags & 2) != 0;
|
||||
missing_balance = (flags & 4) != 0;
|
||||
bot_canceled = (flags & 128) != 0;
|
||||
id = stream.readString(exception);
|
||||
peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
until_date = stream.readInt32(exception);
|
||||
pricing = TL_starsSubscriptionPricing.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
if ((flags & 8) != 0) {
|
||||
chat_invite_hash = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
title = stream.readString(exception);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception);
|
||||
}
|
||||
if ((flags & 64) != 0) {
|
||||
invoice_slug = stream.readString(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
flags = canceled ? (flags | 1) : (flags &~ 1);
|
||||
flags = can_refulfill ? (flags | 2) : (flags &~ 2);
|
||||
flags = missing_balance ? (flags | 4) : (flags &~ 4);
|
||||
flags = bot_canceled ? (flags | 128) : (flags &~ 128);
|
||||
stream.writeInt32(flags);
|
||||
stream.writeString(id);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeInt32(until_date);
|
||||
pricing.serializeToStream(stream);
|
||||
if ((flags & 8) != 0) {
|
||||
stream.writeString(chat_invite_hash);
|
||||
}
|
||||
if ((flags & 16) != 0) {
|
||||
stream.writeString(title);
|
||||
}
|
||||
if ((flags & 32) != 0) {
|
||||
photo.serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 64) != 0) {
|
||||
stream.writeString(invoice_slug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_starsSubscription_layer193 extends StarsSubscription {
|
||||
public static final int constructor = 0x538ecf18;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1009,11 +1009,11 @@ public class TL_stats {
|
|||
}
|
||||
|
||||
public static class TL_getBroadcastRevenueStats extends TLObject {
|
||||
public static final int constructor = 0x75dfb671;
|
||||
public static final int constructor = 0xf788ee19;
|
||||
|
||||
public int flags;
|
||||
public boolean dark;
|
||||
public TLRPC.InputChannel channel;
|
||||
public TLRPC.InputPeer peer;
|
||||
|
||||
@Override
|
||||
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||
|
@ -1025,14 +1025,14 @@ public class TL_stats {
|
|||
stream.writeInt32(constructor);
|
||||
flags = dark ? (flags | 1) : (flags & ~1);
|
||||
stream.writeInt32(flags);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_getBroadcastRevenueWithdrawalUrl extends TLObject {
|
||||
public static final int constructor = 0x2a65ef73;
|
||||
public static final int constructor = 0x9df4faad;
|
||||
|
||||
public TLRPC.InputChannel channel;
|
||||
public TLRPC.InputPeer peer;
|
||||
public TLRPC.InputCheckPasswordSRP password;
|
||||
|
||||
@Override
|
||||
|
@ -1043,15 +1043,15 @@ public class TL_stats {
|
|||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
password.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_getBroadcastRevenueTransactions extends TLObject {
|
||||
public static final int constructor = 0x69280f;
|
||||
public static final int constructor = 0x70990b6d;
|
||||
|
||||
public TLRPC.InputChannel channel;
|
||||
public TLRPC.InputPeer peer;
|
||||
public int offset;
|
||||
public int limit;
|
||||
|
||||
|
@ -1063,7 +1063,7 @@ public class TL_stats {
|
|||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
channel.serializeToStream(stream);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeInt32(offset);
|
||||
stream.writeInt32(limit);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue