mirror of https://github.com/NekoX-Dev/NekoX.git
update to 9.1.0
This commit is contained in:
parent
e9a35cea54
commit
67b1fd17e6
|
@ -1,3 +1,5 @@
|
|||
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
repositories {
|
||||
|
@ -42,6 +44,7 @@ dependencies {
|
|||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
}
|
||||
|
||||
def isWindows = String.valueOf(DefaultNativePlatform.currentOperatingSystem.toFamilyName() == OperatingSystemFamily.WINDOWS)
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion '31.0.0'
|
||||
|
@ -102,7 +105,8 @@ android {
|
|||
ndk.debugSymbolLevel = 'FULL'
|
||||
buildConfigField "String", "APP_CENTER_HASH", "\"\""
|
||||
buildConfigField "boolean", "DEBUG_VERSION", "true"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
|
||||
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
|
||||
}
|
||||
|
||||
HA_private {
|
||||
|
@ -115,6 +119,7 @@ android {
|
|||
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PRIVATE") + "\""
|
||||
buildConfigField "boolean", "DEBUG_VERSION", "true"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
|
||||
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
|
||||
}
|
||||
|
||||
HA_public {
|
||||
|
@ -127,6 +132,7 @@ android {
|
|||
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PUBLIC") + "\""
|
||||
buildConfigField "boolean", "DEBUG_VERSION", "true"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
|
||||
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
|
||||
}
|
||||
|
||||
standalone {
|
||||
|
@ -139,6 +145,7 @@ android {
|
|||
buildConfigField "String", "APP_CENTER_HASH", "\"\""
|
||||
buildConfigField "boolean", "DEBUG_VERSION", "false"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
|
||||
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
|
||||
}
|
||||
|
||||
release {
|
||||
|
@ -152,6 +159,7 @@ android {
|
|||
buildConfigField "String", "APP_CENTER_HASH", "\"\""
|
||||
buildConfigField "boolean", "DEBUG_VERSION", "false"
|
||||
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
|
||||
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,86 @@
|
|||
android:requestLegacyExternalStorage="true"
|
||||
tools:replace="android:supportsRtl">
|
||||
|
||||
<activity-alias
|
||||
android:enabled="false"
|
||||
android:name="org.telegram.messenger.VintageIcon"
|
||||
android:targetActivity="org.telegram.ui.LaunchActivity"
|
||||
android:icon="@mipmap/icon_6_launcher_sa"
|
||||
android:roundIcon="@mipmap/icon_6_launcher_sa"
|
||||
android:exported="true"
|
||||
tools:node="replace">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:enabled="false"
|
||||
android:name="org.telegram.messenger.AquaIcon"
|
||||
android:targetActivity="org.telegram.ui.LaunchActivity"
|
||||
android:icon="@mipmap/icon_4_launcher_sa"
|
||||
android:roundIcon="@mipmap/icon_4_launcher_sa"
|
||||
android:exported="true"
|
||||
tools:node="replace">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:enabled="false"
|
||||
android:name="org.telegram.messenger.PremiumIcon"
|
||||
android:targetActivity="org.telegram.ui.LaunchActivity"
|
||||
android:icon="@mipmap/icon_3_launcher_sa"
|
||||
android:roundIcon="@mipmap/icon_3_launcher_sa"
|
||||
android:exported="true"
|
||||
tools:node="replace">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:enabled="false"
|
||||
android:name="org.telegram.messenger.TurboIcon"
|
||||
android:targetActivity="org.telegram.ui.LaunchActivity"
|
||||
android:icon="@mipmap/icon_5_launcher_sa"
|
||||
android:roundIcon="@mipmap/icon_5_launcher_sa"
|
||||
android:exported="true"
|
||||
tools:node="replace">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:enabled="false"
|
||||
android:name="org.telegram.messenger.NoxIcon"
|
||||
android:targetActivity="org.telegram.ui.LaunchActivity"
|
||||
android:icon="@mipmap/icon_2_launcher_sa"
|
||||
android:roundIcon="@mipmap/icon_2_launcher_sa"
|
||||
android:exported="true"
|
||||
tools:node="replace">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyA-t0jLPjUt2FxrA8VPK2EiYHcYcboIR6k" />
|
||||
|
||||
<service
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,7 +43,30 @@ extern "C" {
|
|||
|
||||
|
||||
/*
|
||||
** Provide the ability to override linkage features of the interface.
|
||||
** Facilitate override of interface linkage and calling conventions.
|
||||
** Be aware that these macros may not be used within this particular
|
||||
** translation of the amalgamation and its associated header file.
|
||||
**
|
||||
** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
|
||||
** compiler that the target identifier should have external linkage.
|
||||
**
|
||||
** The SQLITE_CDECL macro is used to set the calling convention for
|
||||
** public functions that accept a variable number of arguments.
|
||||
**
|
||||
** The SQLITE_APICALL macro is used to set the calling convention for
|
||||
** public functions that accept a fixed number of arguments.
|
||||
**
|
||||
** The SQLITE_STDCALL macro is no longer used and is now deprecated.
|
||||
**
|
||||
** The SQLITE_CALLBACK macro is used to set the calling convention for
|
||||
** function pointers.
|
||||
**
|
||||
** The SQLITE_SYSAPI macro is used to set the calling convention for
|
||||
** functions provided by the operating system.
|
||||
**
|
||||
** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
|
||||
** SQLITE_SYSAPI macros are used only when building for environments
|
||||
** that require non-default calling conventions.
|
||||
*/
|
||||
#ifndef SQLITE_EXTERN
|
||||
# define SQLITE_EXTERN extern
|
||||
|
@ -123,9 +146,9 @@ extern "C" {
|
|||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.35.4"
|
||||
#define SQLITE_VERSION_NUMBER 3035004
|
||||
#define SQLITE_SOURCE_ID "2021-04-02 15:20:15 5d4c65779dab868b285519b19e4cf9d451d50c6048f06f653aa701ec212df45e"
|
||||
#define SQLITE_VERSION "3.39.3"
|
||||
#define SQLITE_VERSION_NUMBER 3039003
|
||||
#define SQLITE_SOURCE_ID "2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
@ -537,12 +560,13 @@ SQLITE_API int sqlite3_exec(
|
|||
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
|
||||
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
|
||||
#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
|
||||
#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8))
|
||||
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
|
||||
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
|
||||
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
||||
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
||||
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
|
||||
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
|
@ -550,6 +574,19 @@ SQLITE_API int sqlite3_exec(
|
|||
** These bit values are intended for use in the
|
||||
** 3rd parameter to the [sqlite3_open_v2()] interface and
|
||||
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
|
||||
**
|
||||
** Only those flags marked as "Ok for sqlite3_open_v2()" may be
|
||||
** used as the third argument to the [sqlite3_open_v2()] interface.
|
||||
** The other flags have historically been ignored by sqlite3_open_v2(),
|
||||
** though future versions of SQLite might change so that an error is
|
||||
** raised if any of the disallowed bits are passed into sqlite3_open_v2().
|
||||
** Applications should not depend on the historical behavior.
|
||||
**
|
||||
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
|
||||
** [sqlite3_open_v2()] does *not* cause the underlying database file
|
||||
** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
|
||||
** [sqlite3_open_v2()] has historically be a no-op and might become an
|
||||
** error in future versions of SQLite.
|
||||
*/
|
||||
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
|
||||
|
@ -572,6 +609,7 @@ SQLITE_API int sqlite3_exec(
|
|||
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
||||
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
|
||||
|
||||
/* Reserved: 0x00F00000 */
|
||||
/* Legacy compatibility: */
|
||||
|
@ -1128,6 +1166,23 @@ struct sqlite3_io_methods {
|
|||
** file to the database file, but before the *-shm file is updated to
|
||||
** record the fact that the pages have been checkpointed.
|
||||
** </ul>
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
|
||||
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
|
||||
** whether or not there is a database client in another process with a wal-mode
|
||||
** transaction open on the database or not. It is only available on unix.The
|
||||
** (void*) argument passed with this file-control should be a pointer to a
|
||||
** value of type (int). The integer value is set to 1 if the database is a wal
|
||||
** mode database and there exists at least one client in another process that
|
||||
** currently has an SQL transaction open on the database. It is set to 0 if
|
||||
** the database is not a wal-mode db, or if there is no such connection in any
|
||||
** other process. This opcode cannot be used to detect transactions opened
|
||||
** by clients within the current process, only within other processes.
|
||||
** </ul>
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
||||
** Used by the cksmvfs VFS module only.
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
|
||||
|
@ -1167,6 +1222,8 @@ struct sqlite3_io_methods {
|
|||
#define SQLITE_FCNTL_CKPT_DONE 37
|
||||
#define SQLITE_FCNTL_RESERVE_BYTES 38
|
||||
#define SQLITE_FCNTL_CKPT_START 39
|
||||
#define SQLITE_FCNTL_EXTERNAL_READER 40
|
||||
#define SQLITE_FCNTL_CKSM_FILE 41
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
|
@ -2445,11 +2502,14 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
|
|||
** CAPI3REF: Count The Number Of Rows Modified
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This function returns the number of rows modified, inserted or
|
||||
** ^These functions return the number of rows modified, inserted or
|
||||
** deleted by the most recently completed INSERT, UPDATE or DELETE
|
||||
** statement on the database connection specified by the only parameter.
|
||||
** ^Executing any other type of SQL statement does not modify the value
|
||||
** returned by this function.
|
||||
** The two functions are identical except for the type of the return value
|
||||
** and that if the number of rows modified by the most recent INSERT, UPDATE
|
||||
** or DELETE is greater than the maximum value supported by type "int", then
|
||||
** the return value of sqlite3_changes() is undefined. ^Executing any other
|
||||
** type of SQL statement does not modify the value returned by these functions.
|
||||
**
|
||||
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
|
||||
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
|
||||
|
@ -2498,16 +2558,21 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
|
|||
** </ul>
|
||||
*/
|
||||
SQLITE_API int sqlite3_changes(sqlite3*);
|
||||
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Total Number Of Rows Modified
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^This function returns the total number of rows inserted, modified or
|
||||
** ^These functions return the total number of rows inserted, modified or
|
||||
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
|
||||
** since the database connection was opened, including those executed as
|
||||
** part of trigger programs. ^Executing any other type of SQL statement
|
||||
** does not affect the value returned by sqlite3_total_changes().
|
||||
** part of trigger programs. The two functions are identical except for the
|
||||
** type of the return value and that if the number of rows modified by the
|
||||
** connection exceeds the maximum value supported by type "int", then
|
||||
** the return value of sqlite3_total_changes() is undefined. ^Executing
|
||||
** any other type of SQL statement does not affect the value returned by
|
||||
** sqlite3_total_changes().
|
||||
**
|
||||
** ^Changes made as part of [foreign key actions] are included in the
|
||||
** count, but those made as part of REPLACE constraint resolution are
|
||||
|
@ -2535,6 +2600,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
|
|||
** </ul>
|
||||
*/
|
||||
SQLITE_API int sqlite3_total_changes(sqlite3*);
|
||||
SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Interrupt A Long-Running Query
|
||||
|
@ -3364,6 +3430,14 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|||
** the default shared cache setting provided by
|
||||
** [sqlite3_enable_shared_cache()].)^
|
||||
**
|
||||
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
|
||||
** <dd>The database connection comes up in "extended result code mode".
|
||||
** In other words, the database behaves has if
|
||||
** [sqlite3_extended_result_codes(db,1)] where called on the database
|
||||
** connection as soon as the connection is created. In addition to setting
|
||||
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
|
||||
** to return an extended result code.</dd>
|
||||
**
|
||||
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
|
||||
** <dd>The database filename is not allowed to be a symbolic link</dd>
|
||||
** </dl>)^
|
||||
|
@ -3371,7 +3445,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|||
** If the 3rd parameter to sqlite3_open_v2() is not one of the
|
||||
** required combinations shown above optionally combined with other
|
||||
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
|
||||
** then the behavior is undefined.
|
||||
** then the behavior is undefined. Historic versions of SQLite
|
||||
** have silently ignored surplus bits in the flags parameter to
|
||||
** sqlite3_open_v2(), however that behavior might not be carried through
|
||||
** into future versions of SQLite and so applications should not rely
|
||||
** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
|
||||
** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause
|
||||
** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE
|
||||
** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not
|
||||
** by sqlite3_open_v2().
|
||||
**
|
||||
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
||||
** [sqlite3_vfs] object that defines the operating system interface that
|
||||
|
@ -3742,13 +3824,14 @@ SQLITE_API void sqlite3_free_filename(char*);
|
|||
** sqlite3_extended_errcode() might change with each API call.
|
||||
** Except, there are some interfaces that are guaranteed to never
|
||||
** change the value of the error code. The error-code preserving
|
||||
** interfaces are:
|
||||
** interfaces include the following:
|
||||
**
|
||||
** <ul>
|
||||
** <li> sqlite3_errcode()
|
||||
** <li> sqlite3_extended_errcode()
|
||||
** <li> sqlite3_errmsg()
|
||||
** <li> sqlite3_errmsg16()
|
||||
** <li> sqlite3_error_offset()
|
||||
** </ul>
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
|
@ -3763,6 +3846,13 @@ SQLITE_API void sqlite3_free_filename(char*);
|
|||
** ^(Memory to hold the error message string is managed internally
|
||||
** and must not be freed by the application)^.
|
||||
**
|
||||
** ^If the most recent error references a specific token in the input
|
||||
** SQL, the sqlite3_error_offset() interface returns the byte offset
|
||||
** of the start of that token. ^The byte offset returned by
|
||||
** sqlite3_error_offset() assumes that the input SQL is UTF8.
|
||||
** ^If the most recent error does not reference a specific token in the input
|
||||
** SQL, then the sqlite3_error_offset() function returns -1.
|
||||
**
|
||||
** When the serialized [threading mode] is in use, it might be the
|
||||
** case that a second error occurs on a separate thread in between
|
||||
** the time of the first error and the call to these interfaces.
|
||||
|
@ -3782,6 +3872,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
|
|||
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
|
||||
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
|
||||
SQLITE_API const char *sqlite3_errstr(int);
|
||||
SQLITE_API int sqlite3_error_offset(sqlite3 *db);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Object
|
||||
|
@ -4139,12 +4230,17 @@ SQLITE_API int sqlite3_prepare16_v3(
|
|||
** are managed by SQLite and are automatically freed when the prepared
|
||||
** statement is finalized.
|
||||
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
|
||||
** is obtained from [sqlite3_malloc()] and must be free by the application
|
||||
** is obtained from [sqlite3_malloc()] and must be freed by the application
|
||||
** by passing it to [sqlite3_free()].
|
||||
**
|
||||
** ^The sqlite3_normalized_sql() interface is only available if
|
||||
** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
|
||||
*/
|
||||
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
|
||||
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If An SQL Statement Writes The Database
|
||||
|
@ -4179,6 +4275,19 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
|||
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
|
||||
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
|
||||
** sqlite3_stmt_readonly() returns false for those commands.
|
||||
**
|
||||
** ^This routine returns false if there is any possibility that the
|
||||
** statement might change the database file. ^A false return does
|
||||
** not guarantee that the statement will change the database file.
|
||||
** ^For example, an UPDATE statement might have a WHERE clause that
|
||||
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
|
||||
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
|
||||
** read-only no-op if the table already exists, but
|
||||
** sqlite3_stmt_readonly() still returns false for such a statement.
|
||||
**
|
||||
** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
|
||||
** statement, then sqlite3_stmt_readonly(X) returns the same value as
|
||||
** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
|
@ -4247,6 +4356,8 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
|
|||
**
|
||||
** ^The sqlite3_value objects that are passed as parameters into the
|
||||
** implementation of [application-defined SQL functions] are protected.
|
||||
** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
|
||||
** are protected.
|
||||
** ^The sqlite3_value object returned by
|
||||
** [sqlite3_column_value()] is unprotected.
|
||||
** Unprotected sqlite3_value objects may only be used as arguments
|
||||
|
@ -4348,18 +4459,22 @@ typedef struct sqlite3_context sqlite3_context;
|
|||
** contain embedded NULs. The result of expressions involving strings
|
||||
** with embedded NULs is undefined.
|
||||
**
|
||||
** ^The fifth argument to the BLOB and string binding interfaces
|
||||
** is a destructor used to dispose of the BLOB or
|
||||
** string after SQLite has finished with it. ^The destructor is called
|
||||
** to dispose of the BLOB or string even if the call to the bind API fails,
|
||||
** except the destructor is not called if the third parameter is a NULL
|
||||
** pointer or the fourth parameter is negative.
|
||||
** ^If the fifth argument is
|
||||
** the special value [SQLITE_STATIC], then SQLite assumes that the
|
||||
** information is in static, unmanaged space and does not need to be freed.
|
||||
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
|
||||
** SQLite makes its own private copy of the data immediately, before
|
||||
** the sqlite3_bind_*() routine returns.
|
||||
** ^The fifth argument to the BLOB and string binding interfaces controls
|
||||
** or indicates the lifetime of the object referenced by the third parameter.
|
||||
** These three options exist:
|
||||
** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
|
||||
** with it may be passed. ^It is called to dispose of the BLOB or string even
|
||||
** if the call to the bind API fails, except the destructor is not called if
|
||||
** the third parameter is a NULL pointer or the fourth parameter is negative.
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
|
||||
** the application remains responsible for disposing of the object. ^In this
|
||||
** case, the object and the provided pointer to it must remain valid until
|
||||
** either the prepared statement is finalized or the same SQL parameter is
|
||||
** bound to something else, whichever occurs sooner.
|
||||
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
|
||||
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
|
||||
** object and pointer to it must remain valid until then. ^SQLite will then
|
||||
** manage the lifetime of its private copy.
|
||||
**
|
||||
** ^The sixth argument to sqlite3_bind_text64() must be one of
|
||||
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
|
||||
|
@ -4864,6 +4979,10 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|||
** even empty strings, are always zero-terminated. ^The return
|
||||
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
|
||||
**
|
||||
** ^Strings returned by sqlite3_column_text16() always have the endianness
|
||||
** which is native to the platform, regardless of the text encoding set
|
||||
** for the database.
|
||||
**
|
||||
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
|
||||
** [unprotected sqlite3_value] object. In a multithreaded environment,
|
||||
** an unprotected sqlite3_value object may only be used safely with
|
||||
|
@ -4877,7 +4996,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|||
** [application-defined SQL functions] or [virtual tables], not within
|
||||
** top-level application code.
|
||||
**
|
||||
** The these routines may attempt to convert the datatype of the result.
|
||||
** These routines may attempt to convert the datatype of the result.
|
||||
** ^For example, if the internal representation is FLOAT and a text result
|
||||
** is requested, [sqlite3_snprintf()] is used internally to perform the
|
||||
** conversion automatically. ^(The following table details the conversions
|
||||
|
@ -4902,7 +5021,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|||
** <tr><td> TEXT <td> BLOB <td> No change
|
||||
** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
|
||||
** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
|
||||
** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
|
||||
** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
|
||||
** </table>
|
||||
** </blockquote>)^
|
||||
**
|
||||
|
@ -5101,7 +5220,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|||
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
|
||||
** index expressions, or the WHERE clause of partial indexes.
|
||||
**
|
||||
** <span style="background-color:#ffff90;">
|
||||
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
|
||||
** all application-defined SQL functions that do not need to be
|
||||
** used inside of triggers, view, CHECK constraints, or other elements of
|
||||
|
@ -5111,7 +5229,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|||
** a database file to include invocations of the function with parameters
|
||||
** chosen by the attacker, which the application will then execute when
|
||||
** the database file is opened and read.
|
||||
** </span>
|
||||
**
|
||||
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
||||
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
||||
|
@ -5476,7 +5593,8 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
|
|||
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
|
||||
** is a [protected sqlite3_value] object even if the input is not.
|
||||
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
|
||||
** memory allocation fails.
|
||||
** memory allocation fails. ^If V is a [pointer value], then the result
|
||||
** of sqlite3_value_dup(V) is a NULL value.
|
||||
**
|
||||
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
|
||||
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
|
||||
|
@ -6158,6 +6276,28 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
|
|||
*/
|
||||
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return The Schema Name For A Database Connection
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
|
||||
** for the N-th database on database connection D, or a NULL pointer of N is
|
||||
** out of range. An N value of 0 means the main database file. An N of 1 is
|
||||
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
|
||||
** databases.
|
||||
**
|
||||
** Space to hold the string that is returned by sqlite3_db_name() is managed
|
||||
** by SQLite itself. The string might be deallocated by any operation that
|
||||
** changes the schema, including [ATTACH] or [DETACH] or calls to
|
||||
** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that
|
||||
** occur on a different thread. Applications that need to
|
||||
** remember the string long-term should make their own copy. Applications that
|
||||
** are accessing the same database connection simultaneously on multiple
|
||||
** threads should mutex-protect calls to this API and should make their own
|
||||
** private copy of the result prior to releasing the mutex.
|
||||
*/
|
||||
SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return The Filename For A Database Connection
|
||||
** METHOD: sqlite3
|
||||
|
@ -6317,6 +6457,72 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
|||
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
|
||||
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Autovacuum Compaction Amount Callback
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
|
||||
** function C that is invoked prior to each autovacuum of the database
|
||||
** file. ^The callback is passed a copy of the generic data pointer (P),
|
||||
** the schema-name of the attached database that is being autovacuumed,
|
||||
** the the size of the database file in pages, the number of free pages,
|
||||
** and the number of bytes per page, respectively. The callback should
|
||||
** return the number of free pages that should be removed by the
|
||||
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
|
||||
** ^If the value returned is greater than or equal to the number of
|
||||
** free pages, then a complete autovacuum happens.
|
||||
**
|
||||
** <p>^If there are multiple ATTACH-ed database files that are being
|
||||
** modified as part of a transaction commit, then the autovacuum pages
|
||||
** callback is invoked separately for each file.
|
||||
**
|
||||
** <p><b>The callback is not reentrant.</b> The callback function should
|
||||
** not attempt to invoke any other SQLite interface. If it does, bad
|
||||
** things may happen, including segmentation faults and corrupt database
|
||||
** files. The callback function should be a simple function that
|
||||
** does some arithmetic on its input parameters and returns a result.
|
||||
**
|
||||
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
|
||||
** destructor for the P parameter. ^If X is not NULL, then X(P) is
|
||||
** invoked whenever the database connection closes or when the callback
|
||||
** is overwritten by another invocation of sqlite3_autovacuum_pages().
|
||||
**
|
||||
** <p>^There is only one autovacuum pages callback per database connection.
|
||||
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
|
||||
** previous invocations for that database connection. ^If the callback
|
||||
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
|
||||
** then the autovacuum steps callback is cancelled. The return value
|
||||
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
|
||||
** be some other error code if something goes wrong. The current
|
||||
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
|
||||
** return codes might be added in future releases.
|
||||
**
|
||||
** <p>If no autovacuum pages callback is specified (the usual case) or
|
||||
** a NULL pointer is provided for the callback,
|
||||
** then the default behavior is to vacuum all free pages. So, in other
|
||||
** words, the default behavior is the same as if the callback function
|
||||
** were something like this:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** unsigned int demonstration_autovac_pages_callback(
|
||||
** void *pClientData,
|
||||
** const char *zSchema,
|
||||
** unsigned int nDbPage,
|
||||
** unsigned int nFreePage,
|
||||
** unsigned int nBytePerPage
|
||||
** ){
|
||||
** return nFreePage;
|
||||
** }
|
||||
** </pre></blockquote>
|
||||
*/
|
||||
SQLITE_API int sqlite3_autovacuum_pages(
|
||||
sqlite3 *db,
|
||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||
void*,
|
||||
void(*)(void*)
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Data Change Notification Callbacks
|
||||
** METHOD: sqlite3
|
||||
|
@ -6958,24 +7164,56 @@ struct sqlite3_index_info {
|
|||
**
|
||||
** These macros define the allowed values for the
|
||||
** [sqlite3_index_info].aConstraint[].op field. Each value represents
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** an operator that is part of a constraint term in the WHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
**
|
||||
** ^The left-hand operand of the operator is given by the corresponding
|
||||
** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
|
||||
** operand is the rowid.
|
||||
** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
|
||||
** operators have no left-hand operand, and so for those operators the
|
||||
** corresponding aConstraint[].iColumn is meaningless and should not be
|
||||
** used.
|
||||
**
|
||||
** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
|
||||
** value 255 are reserved to represent functions that are overloaded
|
||||
** by the [xFindFunction|xFindFunction method] of the virtual table
|
||||
** implementation.
|
||||
**
|
||||
** The right-hand operands for each constraint might be accessible using
|
||||
** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand
|
||||
** operand is only available if it appears as a single constant literal
|
||||
** in the input SQL. If the right-hand operand is another column or an
|
||||
** expression (even a constant expression) or a parameter, then the
|
||||
** sqlite3_vtab_rhs_value() probably will not be able to extract it.
|
||||
** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
|
||||
** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
|
||||
** and hence calls to sqlite3_vtab_rhs_value() for those operators will
|
||||
** always return SQLITE_NOTFOUND.
|
||||
**
|
||||
** The collating sequence to be used for comparison can be found using
|
||||
** the [sqlite3_vtab_collation()] interface. For most real-world virtual
|
||||
** tables, the collating sequence of constraints does not matter (for example
|
||||
** because the constraints are numeric) and so the sqlite3_vtab_collation()
|
||||
** interface is no commonly needed.
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
|
||||
#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
|
||||
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
|
@ -7004,7 +7242,7 @@ struct sqlite3_index_info {
|
|||
** destructor.
|
||||
**
|
||||
** ^If the third parameter (the pointer to the sqlite3_module object) is
|
||||
** NULL then no new module is create and any existing modules with the
|
||||
** NULL then no new module is created and any existing modules with the
|
||||
** same name are dropped.
|
||||
**
|
||||
** See also: [sqlite3_drop_modules()]
|
||||
|
@ -7779,7 +8017,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
|||
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
||||
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_LAST 31 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
|
@ -8302,6 +8542,16 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
|||
** The counter is incremented on the first [sqlite3_step()] call of each
|
||||
** cycle.
|
||||
**
|
||||
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
|
||||
** [[SQLITE_STMTSTATUS_FILTER HIT]]
|
||||
** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
|
||||
** SQLITE_STMTSTATUS_FILTER_MISS</dt>
|
||||
** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
|
||||
** step was bypassed because a Bloom filter returned not-found. The
|
||||
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
|
||||
** times that the Bloom filter returned a find, and thus the join step
|
||||
** had to be processed as normal.
|
||||
**
|
||||
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
|
||||
** <dd>^This is the approximate number of bytes of heap memory
|
||||
** used to store the prepared statement. ^This value is not actually
|
||||
|
@ -8316,6 +8566,8 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
|||
#define SQLITE_STMTSTATUS_VM_STEP 4
|
||||
#define SQLITE_STMTSTATUS_REPREPARE 5
|
||||
#define SQLITE_STMTSTATUS_RUN 6
|
||||
#define SQLITE_STMTSTATUS_FILTER_MISS 7
|
||||
#define SQLITE_STMTSTATUS_FILTER_HIT 8
|
||||
#define SQLITE_STMTSTATUS_MEMUSED 99
|
||||
|
||||
/*
|
||||
|
@ -8979,8 +9231,9 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
|||
**
|
||||
** A single database handle may have at most a single write-ahead log callback
|
||||
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
|
||||
** previously registered write-ahead log callback. ^Note that the
|
||||
** [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** previously registered write-ahead log callback. ^The return value is
|
||||
** a copy of the third parameter from the previous call, if any, or 0.
|
||||
** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
|
||||
** overwrite any prior [sqlite3_wal_hook()] settings.
|
||||
*/
|
||||
|
@ -9283,19 +9536,276 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
|||
|
||||
/*
|
||||
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This function may only be called from within a call to the [xBestIndex]
|
||||
** method of a [virtual table].
|
||||
** method of a [virtual table]. This function returns a pointer to a string
|
||||
** that is the name of the appropriate collation sequence to use for text
|
||||
** comparisons on the constraint identified by its arguments.
|
||||
**
|
||||
** The first argument must be the sqlite3_index_info object that is the
|
||||
** first parameter to the xBestIndex() method. The second argument must be
|
||||
** an index into the aConstraint[] array belonging to the sqlite3_index_info
|
||||
** structure passed to xBestIndex. This function returns a pointer to a buffer
|
||||
** containing the name of the collation sequence for the corresponding
|
||||
** constraint.
|
||||
** The first argument must be the pointer to the [sqlite3_index_info] object
|
||||
** that is the first parameter to the xBestIndex() method. The second argument
|
||||
** must be an index into the aConstraint[] array belonging to the
|
||||
** sqlite3_index_info structure passed to xBestIndex.
|
||||
**
|
||||
** Important:
|
||||
** The first parameter must be the same pointer that is passed into the
|
||||
** xBestMethod() method. The first parameter may not be a pointer to a
|
||||
** different [sqlite3_index_info] object, even an exact copy.
|
||||
**
|
||||
** The return value is computed as follows:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p> If the constraint comes from a WHERE clause expression that contains
|
||||
** a [COLLATE operator], then the name of the collation specified by
|
||||
** that COLLATE operator is returned.
|
||||
** <li><p> If there is no COLLATE operator, but the column that is the subject
|
||||
** of the constraint specifies an alternative collating sequence via
|
||||
** a [COLLATE clause] on the column definition within the CREATE TABLE
|
||||
** statement that was passed into [sqlite3_declare_vtab()], then the
|
||||
** name of that alternative collating sequence is returned.
|
||||
** <li><p> Otherwise, "BINARY" is returned.
|
||||
** </ol>
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine if a virtual table query is DISTINCT
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This API may only be used from within an [xBestIndex|xBestIndex method]
|
||||
** of a [virtual table] implementation. The result of calling this
|
||||
** interface from outside of xBestIndex() is undefined and probably harmful.
|
||||
**
|
||||
** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and
|
||||
** 3. The integer returned by sqlite3_vtab_distinct()
|
||||
** gives the virtual table additional information about how the query
|
||||
** planner wants the output to be ordered. As long as the virtual table
|
||||
** can meet the ordering requirements of the query planner, it may set
|
||||
** the "orderByConsumed" flag.
|
||||
**
|
||||
** <ol><li value="0"><p>
|
||||
** ^If the sqlite3_vtab_distinct() interface returns 0, that means
|
||||
** that the query planner needs the virtual table to return all rows in the
|
||||
** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
|
||||
** [sqlite3_index_info] object. This is the default expectation. If the
|
||||
** virtual table outputs all rows in sorted order, then it is always safe for
|
||||
** the xBestIndex method to set the "orderByConsumed" flag, regardless of
|
||||
** the return value from sqlite3_vtab_distinct().
|
||||
** <li value="1"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
|
||||
** that the query planner does not need the rows to be returned in sorted order
|
||||
** as long as all rows with the same values in all columns identified by the
|
||||
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
|
||||
** is doing a GROUP BY.
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** <li value="3"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
|
||||
** that the query planner needs only distinct rows but it does need the
|
||||
** rows to be sorted.)^ ^The virtual table implementation is free to omit
|
||||
** rows that are identical in all aOrderBy columns, if it wants to, but
|
||||
** it is not required to omit any rows. This mode is used for queries
|
||||
** that have both DISTINCT and ORDER BY clauses.
|
||||
** </ol>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
** (or "IS NOT DISTINCT FROM") and not "==".
|
||||
**
|
||||
** If a virtual table implementation is unable to meet the requirements
|
||||
** specified above, then it must not set the "orderByConsumed" flag in the
|
||||
** [sqlite3_index_info] object or an incorrect answer may result.
|
||||
**
|
||||
** ^A virtual table implementation is always free to return rows in any order
|
||||
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
|
||||
** the "orderByConsumed" flag is unset, the query planner will add extra
|
||||
** [bytecode] to ensure that the final results returned by the SQL query are
|
||||
** ordered correctly. The use of the "orderByConsumed" flag and the
|
||||
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
|
||||
** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
|
||||
** flag might help queries against a virtual table to run faster. Being
|
||||
** overly aggressive and setting the "orderByConsumed" flag when it is not
|
||||
** valid to do so, on the other hand, might cause SQLite to return incorrect
|
||||
** results.
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Identify and handle IN constraints in xBestIndex
|
||||
**
|
||||
** This interface may only be used from within an
|
||||
** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
|
||||
** The result of invoking this interface from any other context is
|
||||
** undefined and probably harmful.
|
||||
**
|
||||
** ^(A constraint on a virtual table of the form
|
||||
** "[IN operator|column IN (...)]" is
|
||||
** communicated to the xBestIndex method as a
|
||||
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
|
||||
** this constraint, it must set the corresponding
|
||||
** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
|
||||
** the usual mode of handling IN operators, SQLite generates [bytecode]
|
||||
** that invokes the [xFilter|xFilter() method] once for each value
|
||||
** on the right-hand side of the IN operator.)^ Thus the virtual table
|
||||
** only sees a single value from the right-hand side of the IN operator
|
||||
** at a time.
|
||||
**
|
||||
** In some cases, however, it would be advantageous for the virtual
|
||||
** table to see all values on the right-hand of the IN operator all at
|
||||
** once. The sqlite3_vtab_in() interfaces facilitates this in two ways:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p>
|
||||
** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero)
|
||||
** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint
|
||||
** is an [IN operator] that can be processed all at once. ^In other words,
|
||||
** sqlite3_vtab_in() with -1 in the third argument is a mechanism
|
||||
** by which the virtual table can ask SQLite if all-at-once processing
|
||||
** of the IN operator is even possible.
|
||||
**
|
||||
** <li><p>
|
||||
** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
|
||||
** to SQLite that the virtual table does or does not want to process
|
||||
** the IN operator all-at-once, respectively. ^Thus when the third
|
||||
** parameter (F) is non-negative, this interface is the mechanism by
|
||||
** which the virtual table tells SQLite how it wants to process the
|
||||
** IN operator.
|
||||
** </ol>
|
||||
**
|
||||
** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
|
||||
** within the same xBestIndex method call. ^For any given P,N pair,
|
||||
** the return value from sqlite3_vtab_in(P,N,F) will always be the same
|
||||
** within the same xBestIndex call. ^If the interface returns true
|
||||
** (non-zero), that means that the constraint is an IN operator
|
||||
** that can be processed all-at-once. ^If the constraint is not an IN
|
||||
** operator or cannot be processed all-at-once, then the interface returns
|
||||
** false.
|
||||
**
|
||||
** ^(All-at-once processing of the IN operator is selected if both of the
|
||||
** following conditions are met:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
|
||||
** integer. This is how the virtual table tells SQLite that it wants to
|
||||
** use the N-th constraint.
|
||||
**
|
||||
** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was
|
||||
** non-negative had F>=1.
|
||||
** </ol>)^
|
||||
**
|
||||
** ^If either or both of the conditions above are false, then SQLite uses
|
||||
** the traditional one-at-a-time processing strategy for the IN constraint.
|
||||
** ^If both conditions are true, then the argvIndex-th parameter to the
|
||||
** xFilter method will be an [sqlite3_value] that appears to be NULL,
|
||||
** but which can be passed to [sqlite3_vtab_in_first()] and
|
||||
** [sqlite3_vtab_in_next()] to find all values on the right-hand side
|
||||
** of the IN constraint.
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
|
||||
**
|
||||
** These interfaces are only useful from within the
|
||||
** [xFilter|xFilter() method] of a [virtual table] implementation.
|
||||
** The result of invoking these interfaces from any other context
|
||||
** is undefined and probably harmful.
|
||||
**
|
||||
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
|
||||
** sqlite3_vtab_in_next(X,P) must be one of the parameters to the
|
||||
** xFilter method which invokes these routines, and specifically
|
||||
** a parameter that was previously selected for all-at-once IN constraint
|
||||
** processing use the [sqlite3_vtab_in()] interface in the
|
||||
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
|
||||
** an xFilter argument that was selected for all-at-once IN constraint
|
||||
** processing, then these routines return [SQLITE_MISUSE])^ or perhaps
|
||||
** exhibit some other undefined or harmful behavior.
|
||||
**
|
||||
** ^(Use these routines to access all values on the right-hand side
|
||||
** of the IN constraint using code like the following:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** for(rc=sqlite3_vtab_in_first(pList, &pVal);
|
||||
** rc==SQLITE_OK && pVal
|
||||
** rc=sqlite3_vtab_in_next(pList, &pVal)
|
||||
** ){
|
||||
** // do something with pVal
|
||||
** }
|
||||
** if( rc!=SQLITE_OK ){
|
||||
** // an error has occurred
|
||||
** }
|
||||
** </pre></blockquote>)^
|
||||
**
|
||||
** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
|
||||
** routines return SQLITE_OK and set *P to point to the first or next value
|
||||
** on the RHS of the IN constraint. ^If there are no more values on the
|
||||
** right hand side of the IN constraint, then *P is set to NULL and these
|
||||
** routines return [SQLITE_DONE]. ^The return value might be
|
||||
** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
|
||||
**
|
||||
** The *ppOut values returned by these routines are only valid until the
|
||||
** next call to either of these routines or until the end of the xFilter
|
||||
** method from which these routines were called. If the virtual table
|
||||
** implementation needs to retain the *ppOut values for longer, it must make
|
||||
** copies. The *ppOut values are [protected sqlite3_value|protected].
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constraint values in xBestIndex()
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This API may only be used from within the [xBestIndex|xBestIndex method]
|
||||
** of a [virtual table] implementation. The result of calling this interface
|
||||
** from outside of an xBestIndex method are undefined and probably harmful.
|
||||
**
|
||||
** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
|
||||
** the [xBestIndex] method of a [virtual table] implementation, with P being
|
||||
** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
|
||||
** J being a 0-based index into P->aConstraint[], then this routine
|
||||
** attempts to set *V to the value of the right-hand operand of
|
||||
** that constraint if the right-hand operand is known. ^If the
|
||||
** right-hand operand is not known, then *V is set to a NULL pointer.
|
||||
** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
|
||||
** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
|
||||
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
|
||||
** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
|
||||
** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
|
||||
** something goes wrong.
|
||||
**
|
||||
** The sqlite3_vtab_rhs_value() interface is usually only successful if
|
||||
** the right-hand operand of a constraint is a literal value in the original
|
||||
** SQL statement. If the right-hand operand is an expression or a reference
|
||||
** to some other column or a [host parameter], then sqlite3_vtab_rhs_value()
|
||||
** will probably return [SQLITE_NOTFOUND].
|
||||
**
|
||||
** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
|
||||
** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
|
||||
** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
|
||||
**
|
||||
** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value
|
||||
** and remains valid for the duration of the xBestIndex method call.
|
||||
** ^When xBestIndex returns, the sqlite3_value object returned by
|
||||
** sqlite3_vtab_rhs_value() is automatically deallocated.
|
||||
**
|
||||
** The "_rhs_" in the name of this routine is an abbreviation for
|
||||
** "Right-Hand Side".
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
|
@ -9531,6 +10041,15 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
|||
** triggers; or 2 for changes resulting from triggers called by top-level
|
||||
** triggers; and so forth.
|
||||
**
|
||||
** When the [sqlite3_blob_write()] API is used to update a blob column,
|
||||
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
|
||||
** in this case the new values are not available. In this case, when a
|
||||
** callback made with op==SQLITE_DELETE is actuall a write using the
|
||||
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
|
||||
** the index of the column being written. In other cases, where the
|
||||
** pre-update hook is being invoked for some other reason, including a
|
||||
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
|
||||
**
|
||||
** See also: [sqlite3_update_hook()]
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
|
||||
|
@ -9551,6 +10070,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
|
|||
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
|
||||
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
|
||||
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
||||
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -9789,8 +10309,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
|
|||
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
||||
** allocation error occurs.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
** This interface is omitted if SQLite is compiled with the
|
||||
** [SQLITE_OMIT_DESERIALIZE] option.
|
||||
*/
|
||||
SQLITE_API unsigned char *sqlite3_serialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
|
@ -9837,12 +10357,16 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
|||
** database is currently in a read transaction or is involved in a backup
|
||||
** operation.
|
||||
**
|
||||
** It is not possible to deserialized into the TEMP database. If the
|
||||
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
|
||||
** function returns SQLITE_ERROR.
|
||||
**
|
||||
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
|
||||
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
||||
** [sqlite3_free()] is invoked on argument P prior to returning.
|
||||
**
|
||||
** This interface is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_DESERIALIZE] option.
|
||||
** This interface is omitted if SQLite is compiled with the
|
||||
** [SQLITE_OMIT_DESERIALIZE] option.
|
||||
*/
|
||||
SQLITE_API int sqlite3_deserialize(
|
||||
sqlite3 *db, /* The database connection */
|
||||
|
@ -10091,6 +10615,38 @@ SQLITE_API int sqlite3session_create(
|
|||
*/
|
||||
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPIREF: Conigure a Session Object
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** This method is used to configure a session object after it has been
|
||||
** created. At present the only valid value for the second parameter is
|
||||
** [SQLITE_SESSION_OBJCONFIG_SIZE].
|
||||
**
|
||||
** Arguments for sqlite3session_object_config()
|
||||
**
|
||||
** The following values may passed as the the 4th parameter to
|
||||
** sqlite3session_object_config().
|
||||
**
|
||||
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
|
||||
** This option is used to set, clear or query the flag that enables
|
||||
** the [sqlite3session_changeset_size()] API. Because it imposes some
|
||||
** computational overhead, this API is disabled by default. Argument
|
||||
** pArg must point to a value of type (int). If the value is initially
|
||||
** 0, then the sqlite3session_changeset_size() API is disabled. If it
|
||||
** is greater than 0, then the same API is enabled. Or, if the initial
|
||||
** value is less than zero, no change is made. In all cases the (int)
|
||||
** variable is set to 1 if the sqlite3session_changeset_size() API is
|
||||
** enabled following the current call, or 0 otherwise.
|
||||
**
|
||||
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
||||
** the first table has been attached to the session object.
|
||||
*/
|
||||
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
|
||||
|
||||
/*
|
||||
*/
|
||||
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable A Session Object
|
||||
|
@ -10335,6 +10891,22 @@ SQLITE_API int sqlite3session_changeset(
|
|||
void **ppChangeset /* OUT: Buffer containing changeset */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
|
||||
** METHOD: sqlite3_session
|
||||
**
|
||||
** By default, this function always returns 0. For it to return
|
||||
** a useful result, the sqlite3_session object must have been configured
|
||||
** to enable this API using sqlite3session_object_config() with the
|
||||
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
|
||||
**
|
||||
** When enabled, this function returns an upper limit, in bytes, for the size
|
||||
** of the changeset that might be produced if sqlite3session_changeset() were
|
||||
** called. The final changeset size might be equal to or smaller than the
|
||||
** size in bytes returned by this function.
|
||||
*/
|
||||
SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Load The Difference Between Tables Into A Session
|
||||
** METHOD: sqlite3_session
|
||||
|
|
|
@ -358,6 +358,17 @@ TL_restrictionReason *TL_restrictionReason::TLdeserialize(NativeByteBuffer *stre
|
|||
return result;
|
||||
}
|
||||
|
||||
TL_username *TL_username::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
if (TL_username::constructor != constructor) {
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_username", constructor);
|
||||
return nullptr;
|
||||
}
|
||||
TL_username *result = new TL_username();
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_restrictionReason::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
platform = stream->readString(&error);
|
||||
reason = stream->readString(&error);
|
||||
|
@ -371,6 +382,21 @@ void TL_restrictionReason::serializeToStream(NativeByteBuffer *stream) {
|
|||
stream->writeString(text);
|
||||
}
|
||||
|
||||
void TL_username::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
flags = stream->readInt32(&error);
|
||||
editable = (flags & 1) != 0;
|
||||
active = (flags & 2) != 0;
|
||||
username = stream->readString(&error);
|
||||
}
|
||||
|
||||
void TL_username::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
flags = editable ? (flags | 1) : (flags &~ 1);
|
||||
flags = active ? (flags | 2) : (flags &~ 2);
|
||||
stream->writeInt32(flags);
|
||||
stream->writeString(username);
|
||||
}
|
||||
|
||||
User *User::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
User *result = nullptr;
|
||||
switch (constructor) {
|
||||
|
@ -400,6 +426,7 @@ void TL_userEmpty::serializeToStream(NativeByteBuffer *stream) {
|
|||
|
||||
void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
flags = stream->readInt32(&error);
|
||||
flags2 = stream->readInt32(&error);
|
||||
id = stream->readInt64(&error);
|
||||
if ((flags & 1) != 0) {
|
||||
access_hash = stream->readInt64(&error);
|
||||
|
@ -447,6 +474,22 @@ void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er
|
|||
if ((flags & 4194304) != 0) {
|
||||
lang_code = stream->readString(&error);
|
||||
}
|
||||
if ((flags2 & 1) != 0) {
|
||||
uint32_t magic = stream->readUint32(&error);
|
||||
if (magic != 0x1cb5c415) {
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
|
||||
return;
|
||||
}
|
||||
int32_t count = stream->readInt32(&error);
|
||||
for (int32_t a = 0; a < count; a++) {
|
||||
TL_username *object = TL_username::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error);
|
||||
if (object == nullptr) {
|
||||
return;
|
||||
}
|
||||
usernames.push_back(std::unique_ptr<TL_username>(object));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TL_user::serializeToStream(NativeByteBuffer *stream) {
|
||||
|
|
|
@ -301,6 +301,20 @@ public:
|
|||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_username : public TLObject {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xb4073647;
|
||||
int32_t flags;
|
||||
bool editable;
|
||||
bool active;
|
||||
std::string username;
|
||||
|
||||
static TL_username *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class User : public TLObject {
|
||||
|
||||
public:
|
||||
|
@ -313,10 +327,12 @@ public:
|
|||
std::unique_ptr<UserProfilePhoto> photo;
|
||||
std::unique_ptr<UserStatus> status;
|
||||
int32_t flags;
|
||||
int32_t flags2;
|
||||
int32_t bot_info_version;
|
||||
std::vector<std::unique_ptr<TL_restrictionReason>> restriction_reason;
|
||||
std::string bot_inline_placeholder;
|
||||
std::string lang_code;
|
||||
std::vector<std::unique_ptr<TL_username>> usernames;
|
||||
|
||||
static User *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
};
|
||||
|
@ -333,7 +349,7 @@ public:
|
|||
class TL_user : public User {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x5d99adee;
|
||||
static const uint32_t constructor = 0x8f97c628;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
|
@ -777,5 +793,4 @@ public:
|
|||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1299,7 +1299,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
|||
int32_t waitTime = 2;
|
||||
static std::string floodWait = "FLOOD_WAIT_";
|
||||
static std::string slowmodeWait = "SLOWMODE_WAIT_";
|
||||
discardResponse = true;
|
||||
discardResponse = (request->requestFlags & RequestFlagIgnoreFloodWait) == 0;
|
||||
if (error->error_message.find(floodWait) != std::string::npos) {
|
||||
std::string num = error->error_message.substr(floodWait.size(), error->error_message.size() - floodWait.size());
|
||||
waitTime = atoi(num.c_str());
|
||||
|
|
|
@ -169,7 +169,8 @@ enum RequestFlag {
|
|||
RequestFlagInvokeAfter = 64,
|
||||
RequestFlagNeedQuickAck = 128,
|
||||
RequestFlagUseUnboundKey = 256,
|
||||
RequestFlagResendAfter = 512
|
||||
RequestFlagResendAfter = 512,
|
||||
RequestFlagIgnoreFloodWait = 1024
|
||||
};
|
||||
|
||||
inline std::string to_string_int32(int32_t value) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4542,7 +4542,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
|
|||
final int childCount = mChildHelper.getUnfilteredChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
|
||||
if (!holder.shouldIgnore()) {
|
||||
if (holder != null && !holder.shouldIgnore()) {
|
||||
holder.clearOldPosition();
|
||||
}
|
||||
}
|
||||
|
@ -11645,7 +11645,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
|
|||
*/
|
||||
@Deprecated
|
||||
public int getViewPosition() {
|
||||
return mViewHolder.getPosition();
|
||||
return mViewHolder == null ? RecyclerView.NO_POSITION : mViewHolder.getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11655,7 +11655,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
|
|||
* @return the adapter position this view as of latest layout pass
|
||||
*/
|
||||
public int getViewLayoutPosition() {
|
||||
return mViewHolder.getLayoutPosition();
|
||||
return mViewHolder == null ? RecyclerView.NO_POSITION : mViewHolder.getLayoutPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11667,7 +11667,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
|
|||
* its up-to-date position cannot be calculated.
|
||||
*/
|
||||
public int getViewAdapterPosition() {
|
||||
return mViewHolder.getAdapterPosition();
|
||||
return mViewHolder == null ? RecyclerView.NO_POSITION :mViewHolder.getAdapterPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@ package org.telegram.messenger;
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
@ -55,6 +53,8 @@ import android.provider.CallLog;
|
|||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Settings;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.OsConstants;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
|
@ -66,6 +66,7 @@ import android.text.StaticLayout;
|
|||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.CharacterStyle;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.text.util.Linkify;
|
||||
|
@ -122,10 +123,10 @@ import org.telegram.messenger.utils.CustomHtml;
|
|||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.ActionBarLayout;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.BottomSheet;
|
||||
import org.telegram.ui.ActionBar.INavigationLayout;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Cells.TextDetailSettingsCell;
|
||||
import org.telegram.ui.Components.AlertsCreator;
|
||||
|
@ -172,6 +173,7 @@ import java.util.HashSet;
|
|||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -179,6 +181,9 @@ import java.util.regex.Pattern;
|
|||
public class AndroidUtilities {
|
||||
public final static int LIGHT_STATUS_BAR_OVERLAY = 0x0f000000, DARK_STATUS_BAR_OVERLAY = 0x33000000;
|
||||
|
||||
public final static int REPLACING_TAG_TYPE_LINK = 0;
|
||||
public final static int REPLACING_TAG_TYPE_BOLD = 1;
|
||||
|
||||
public final static String TYPEFACE_ROBOTO_MEDIUM = "fonts/rmedium.ttf";
|
||||
|
||||
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
|
||||
|
@ -421,10 +426,10 @@ public class AndroidUtilities {
|
|||
}
|
||||
|
||||
public static CharSequence replaceSingleTag(String str, Runnable runnable) {
|
||||
return replaceSingleTag(str, null, runnable);
|
||||
return replaceSingleTag(str, null, 0, runnable);
|
||||
}
|
||||
|
||||
public static CharSequence replaceSingleTag(String str, String colorKey, Runnable runnable) {
|
||||
public static CharSequence replaceSingleTag(String str, String colorKey, int type, Runnable runnable) {
|
||||
int startIndex = str.indexOf("**");
|
||||
int endIndex = str.indexOf("**", startIndex + 1);
|
||||
str = str.replace("**", "");
|
||||
|
@ -436,24 +441,36 @@ public class AndroidUtilities {
|
|||
}
|
||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str);
|
||||
if (index >= 0) {
|
||||
spannableStringBuilder.setSpan(new ClickableSpan() {
|
||||
if (type == REPLACING_TAG_TYPE_LINK) {
|
||||
spannableStringBuilder.setSpan(new ClickableSpan() {
|
||||
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
if (colorKey != null) {
|
||||
ds.setColor(Theme.getColor(colorKey));
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setUnderlineText(false);
|
||||
if (colorKey != null) {
|
||||
ds.setColor(Theme.getColor(colorKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, index, index + len, 0);
|
||||
}, index, index + len, 0);
|
||||
} else {
|
||||
spannableStringBuilder.setSpan(new CharacterStyle() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint textPaint) {
|
||||
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
int wasAlpha = textPaint.getAlpha();
|
||||
textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText));
|
||||
textPaint.setAlpha(wasAlpha);
|
||||
}
|
||||
}, index, index + len, 0);
|
||||
}
|
||||
}
|
||||
return spannableStringBuilder;
|
||||
}
|
||||
|
@ -705,6 +722,9 @@ public class AndroidUtilities {
|
|||
}
|
||||
|
||||
public static int calcBitmapColor(Bitmap bitmap) {
|
||||
if (bitmap == null) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
Bitmap b = Bitmaps.createScaledBitmap(bitmap, 1, 1, true);
|
||||
if (b != null) {
|
||||
|
@ -866,6 +886,30 @@ public class AndroidUtilities {
|
|||
}));
|
||||
}
|
||||
|
||||
public static void adjustHueColorMatrix(ColorMatrix cm, float value) {
|
||||
value = cleanValue(value, 180f) / 180f * (float) Math.PI;
|
||||
if (value == 0) {
|
||||
return;
|
||||
}
|
||||
float cosVal = (float) Math.cos(value);
|
||||
float sinVal = (float) Math.sin(value);
|
||||
float lumR = 0.213f;
|
||||
float lumG = 0.715f;
|
||||
float lumB = 0.072f;
|
||||
float[] mat = new float[]
|
||||
{
|
||||
lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
|
||||
lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
|
||||
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
|
||||
0f, 0f, 0f, 1f, 0f,
|
||||
0f, 0f, 0f, 0f, 1f};
|
||||
cm.postConcat(new ColorMatrix(mat));
|
||||
}
|
||||
|
||||
protected static float cleanValue(float p_val, float p_limit) {
|
||||
return Math.min(p_limit, Math.max(-p_limit, p_val));
|
||||
}
|
||||
|
||||
public static void multiplyBrightnessColorMatrix(ColorMatrix colorMatrix, float v) {
|
||||
if (colorMatrix == null) {
|
||||
return;
|
||||
|
@ -2026,9 +2070,13 @@ public class AndroidUtilities {
|
|||
return ch == '-' || ch == '~';
|
||||
}
|
||||
|
||||
public static boolean isTabletForce() {
|
||||
return ApplicationLoader.applicationContext != null && ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
|
||||
}
|
||||
|
||||
public static boolean isTabletInternal() {
|
||||
if (isTablet == null) {
|
||||
isTablet = ApplicationLoader.applicationContext != null && ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
|
||||
isTablet = isTabletForce();
|
||||
}
|
||||
return isTablet;
|
||||
}
|
||||
|
@ -2471,24 +2519,29 @@ public class AndroidUtilities {
|
|||
uptime + 5 < SharedConfig.lastPauseTime);
|
||||
}
|
||||
|
||||
public static void shakeView(final View view, final float x, final int num) {
|
||||
public static void shakeView(final View view) {
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
if (num == 6) {
|
||||
view.setTranslationX(0);
|
||||
return;
|
||||
final float N = 4;
|
||||
Object animator = view.getTag(R.id.shake_animation);
|
||||
if (animator instanceof ValueAnimator) {
|
||||
((ValueAnimator) animator).cancel();
|
||||
}
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(ObjectAnimator.ofFloat(view, "translationX", dp(x)));
|
||||
animatorSet.setDuration(50);
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
ValueAnimator va = ValueAnimator.ofFloat(0, 1);
|
||||
va.addUpdateListener(anm -> {
|
||||
float x = (float) anm.getAnimatedValue();
|
||||
view.setTranslationX((float) ((4 * x * (1 - x)) * Math.sin(N * (x * Math.PI)) * AndroidUtilities.dp(N)));
|
||||
});
|
||||
va.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
shakeView(view, num == 5 ? 0 : -x, num + 1);
|
||||
view.setTranslationX(0);
|
||||
}
|
||||
});
|
||||
animatorSet.start();
|
||||
va.setDuration(300);
|
||||
va.start();
|
||||
view.setTag(R.id.shake_animation, va);
|
||||
}
|
||||
|
||||
public static void shakeViewSpring(View view) {
|
||||
|
@ -2505,13 +2558,28 @@ public class AndroidUtilities {
|
|||
|
||||
public static void shakeViewSpring(View view, float shiftDp, Runnable endCallback) {
|
||||
int shift = dp(shiftDp);
|
||||
new SpringAnimation(view, DynamicAnimation.TRANSLATION_X, 0)
|
||||
.setSpring(new SpringForce(0).setStiffness(600f))
|
||||
if (view.getTag(R.id.spring_tag) != null) {
|
||||
((SpringAnimation)view.getTag(R.id.spring_tag)).cancel();
|
||||
}
|
||||
Float wasX = (Float) view.getTag(R.id.spring_was_translation_x_tag);
|
||||
if (wasX != null) {
|
||||
view.setTranslationX(wasX);
|
||||
}
|
||||
view.setTag(R.id.spring_was_translation_x_tag, view.getTranslationX());
|
||||
|
||||
float translationX = view.getTranslationX();
|
||||
SpringAnimation springAnimation = new SpringAnimation(view, DynamicAnimation.TRANSLATION_X, translationX)
|
||||
.setSpring(new SpringForce(translationX).setStiffness(600f))
|
||||
.setStartVelocity(-shift * 100)
|
||||
.addEndListener((animation, canceled, value, velocity) -> {
|
||||
if (endCallback != null) endCallback.run();
|
||||
})
|
||||
.start();
|
||||
|
||||
view.setTranslationX(translationX);
|
||||
view.setTag(R.id.spring_tag, null);
|
||||
view.setTag(R.id.spring_was_translation_x_tag, null);
|
||||
});
|
||||
view.setTag(R.id.spring_tag, springAnimation);
|
||||
springAnimation.start();
|
||||
}
|
||||
|
||||
/*public static String ellipsize(String text, int maxLines, int maxWidth, TextPaint paint) {
|
||||
|
@ -3117,7 +3185,11 @@ public class AndroidUtilities {
|
|||
parentFragment.presentFragment(new ThemePreviewActivity(themeInfo));
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
Map<String, Integer> colorsReplacement = new HashMap<>();
|
||||
colorsReplacement.put("info1.**", parentFragment.getThemedColor(Theme.key_dialogTopBackground));
|
||||
colorsReplacement.put("info2.**", parentFragment.getThemedColor(Theme.key_dialogTopBackground));
|
||||
builder.setTopAnimation(R.raw.not_available, AlertsCreator.NEW_DENY_DIALOG_TOP_ICON_SIZE, false, parentFragment.getThemedColor(Theme.key_dialogTopBackground), colorsReplacement);
|
||||
builder.setTopAnimationIsNew(true);
|
||||
builder.setMessage(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme));
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
parentFragment.showDialog(builder.create());
|
||||
|
@ -3163,7 +3235,11 @@ public class AndroidUtilities {
|
|||
return;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
Map<String, Integer> colorsReplacement = new HashMap<>();
|
||||
colorsReplacement.put("info1.**", parentFragment.getThemedColor(Theme.key_dialogTopBackground));
|
||||
colorsReplacement.put("info2.**", parentFragment.getThemedColor(Theme.key_dialogTopBackground));
|
||||
builder.setTopAnimation(R.raw.not_available, AlertsCreator.NEW_DENY_DIALOG_TOP_ICON_SIZE, false, parentFragment.getThemedColor(Theme.key_dialogTopBackground), colorsReplacement);
|
||||
builder.setTopAnimationIsNew(true);
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type));
|
||||
if (parentFragment != null) {
|
||||
|
@ -3229,7 +3305,7 @@ public class AndroidUtilities {
|
|||
if (f == null || !f.exists()) {
|
||||
f = FileLoader.getInstance(message.currentAccount).getPathToMessage(message.messageOwner);
|
||||
}
|
||||
String mimeType = message.type == 9 || message.type == 0 ? message.getMimeType() : null;
|
||||
String mimeType = message.type == MessageObject.TYPE_FILE || message.type == MessageObject.TYPE_TEXT ? message.getMimeType() : null;
|
||||
return openForView(f, message.getFileName(), mimeType, activity, resourcesProvider);
|
||||
}
|
||||
|
||||
|
@ -4243,11 +4319,11 @@ public class AndroidUtilities {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static void scrollToFragmentRow(ActionBarLayout parentLayout, String rowName) {
|
||||
public static void scrollToFragmentRow(INavigationLayout parentLayout, String rowName) {
|
||||
if (parentLayout == null || rowName == null) {
|
||||
return;
|
||||
}
|
||||
BaseFragment openingFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1);
|
||||
BaseFragment openingFragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 1);
|
||||
try {
|
||||
Field listViewField = openingFragment.getClass().getDeclaredField("listView");
|
||||
listViewField.setAccessible(true);
|
||||
|
@ -4304,6 +4380,9 @@ public class AndroidUtilities {
|
|||
}
|
||||
|
||||
public static void updateImageViewImageAnimated(ImageView imageView, Drawable newIcon) {
|
||||
if (imageView.getDrawable() == newIcon) {
|
||||
return;
|
||||
}
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(150);
|
||||
AtomicBoolean changed = new AtomicBoolean();
|
||||
animator.addUpdateListener(animation -> {
|
||||
|
@ -4355,6 +4434,45 @@ public class AndroidUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
public static void updateViewShow(View view, boolean show) {
|
||||
updateViewShow(view, show, true, true);
|
||||
}
|
||||
|
||||
public static void updateViewShow(View view, boolean show, boolean scale, boolean animated) {
|
||||
updateViewShow(view, show, scale, animated, null);
|
||||
}
|
||||
|
||||
public static void updateViewShow(View view, boolean show, boolean scale, boolean animated, Runnable onDone) {
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
if (view.getParent() == null) {
|
||||
animated = false;
|
||||
}
|
||||
|
||||
view.animate().setListener(null).cancel();
|
||||
if (!animated) {
|
||||
view.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
view.setTag(show ? 1 : null);
|
||||
view.setAlpha(1f);
|
||||
view.setScaleX(scale && !show ? 0f : 1f);
|
||||
view.setScaleY(scale && !show ? 0f : 1f);
|
||||
if (onDone != null) {
|
||||
onDone.run();
|
||||
}
|
||||
} else if (show) {
|
||||
if (view.getVisibility() != View.VISIBLE) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
view.setAlpha(0f);
|
||||
view.setScaleX(scale ? 0 : 1);
|
||||
view.setScaleY(scale ? 0 : 1);
|
||||
}
|
||||
view.animate().alpha(1f).scaleY(1f).scaleX(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(340).withEndAction(onDone).start();
|
||||
} else {
|
||||
view.animate().alpha(0).scaleY(scale ? 0 : 1).scaleX(scale ? 0 : 1).setListener(new HideViewAfterAnimation(view)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(340).withEndAction(onDone).start();
|
||||
}
|
||||
}
|
||||
|
||||
public static long getPrefIntOrLong(SharedPreferences preferences, String key, long defaultValue) {
|
||||
try {
|
||||
return preferences.getLong(key, defaultValue);
|
||||
|
@ -4471,4 +4589,29 @@ public class AndroidUtilities {
|
|||
}
|
||||
return (st > 0 || len < text.length()) ? text.subSequence(st, len) : text;
|
||||
}
|
||||
|
||||
// detect Error NO SPaCe left on device :(
|
||||
public static boolean isENOSPC(Exception e) {
|
||||
return (
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
|
||||
e instanceof IOException &&
|
||||
(e.getCause() instanceof ErrnoException &&
|
||||
((ErrnoException) e.getCause()).errno == OsConstants.ENOSPC) ||
|
||||
(e.getMessage() != null && e.getMessage().equalsIgnoreCase("no space left on device"))
|
||||
);
|
||||
}
|
||||
|
||||
public static CharSequence replaceCharSequence(String what, CharSequence from, CharSequence obj) {
|
||||
SpannableStringBuilder spannableStringBuilder;
|
||||
if (from instanceof SpannableStringBuilder) {
|
||||
spannableStringBuilder = (SpannableStringBuilder) from;
|
||||
} else {
|
||||
spannableStringBuilder = new SpannableStringBuilder(from);
|
||||
}
|
||||
int index = TextUtils.indexOf(from, what);
|
||||
if (index >= 0) {
|
||||
spannableStringBuilder.replace(index, index + what.length(), obj);
|
||||
}
|
||||
return spannableStringBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ public enum BotWebViewVibrationEffect {
|
|||
NOTIFICATION_ERROR(new long[] {14,48,14,48,14,48,20}, new int[] {200,0,200,0,255,0,145}, new long[] {40,60,40,60,65,60,40}),
|
||||
NOTIFICATION_SUCCESS(new long[] {14,65,14}, new int[] {175,0,255}, new long[] {50,60,65}),
|
||||
NOTIFICATION_WARNING(new long[] {14,64,14}, new int[] {225,0,175}, new long[] {65,60,40}),
|
||||
SELECTION_CHANGE(new long[] {1}, new int[] {65}, new long[] {30});
|
||||
SELECTION_CHANGE(new long[] {1}, new int[] {65}, new long[] {30}),
|
||||
APP_ERROR(new long[] {30,10,150,10}, new int[] {0,100,0,100}, new long[] {40,60,40,60,65,60,40});
|
||||
|
||||
public final long[] timings;
|
||||
public final int[] amplitudes;
|
||||
|
@ -39,4 +40,12 @@ public enum BotWebViewVibrationEffect {
|
|||
|
||||
return (VibrationEffect) vibrationEffect;
|
||||
}
|
||||
|
||||
public void vibrate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AndroidUtilities.getVibrator().vibrate(getVibrationEffectForOreo());
|
||||
} else {
|
||||
AndroidUtilities.getVibrator().vibrate(fallbackTimings, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ public class BuildVars {
|
|||
public static boolean USE_CLOUD_STRINGS = true;
|
||||
public static boolean CHECK_UPDATES = true;
|
||||
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
|
||||
public static int BUILD_VERSION = 2808;
|
||||
public static String BUILD_VERSION_STRING = "9.0.2";
|
||||
public static int BUILD_VERSION = 2885;
|
||||
public static String BUILD_VERSION_STRING = "9.1.0";
|
||||
public static int APP_ID = 4;
|
||||
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.telegram.ui.GroupCallActivity;
|
|||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -54,6 +55,7 @@ public class ChatObject {
|
|||
public static final int ACTION_EDIT_MESSAGES = 12;
|
||||
public static final int ACTION_DELETE_MESSAGES = 13;
|
||||
public static final int ACTION_MANAGE_CALLS = 14;
|
||||
public static final int ACTION_MANAGE_TOPICS = 15;
|
||||
|
||||
public final static int VIDEO_FRAME_NO_FRAME = 0;
|
||||
public final static int VIDEO_FRAME_REQUESTING = 1;
|
||||
|
@ -76,6 +78,14 @@ public class ChatObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean isForum(int currentAccount, long dialogId) {
|
||||
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
|
||||
if (chat != null) {
|
||||
return chat.forum;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class Call {
|
||||
public final static int RECORD_TYPE_AUDIO = 0,
|
||||
RECORD_TYPE_VIDEO_PORTAIT = 1,
|
||||
|
@ -1402,6 +1412,7 @@ public class ChatObject {
|
|||
case ACTION_EMBED_LINKS:
|
||||
case ACTION_SEND_POLLS:
|
||||
case ACTION_VIEW:
|
||||
case ACTION_MANAGE_TOPICS:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1417,6 +1428,7 @@ public class ChatObject {
|
|||
case ACTION_EDIT_MESSAGES:
|
||||
case ACTION_DELETE_MESSAGES:
|
||||
case ACTION_BLOCK_USERS:
|
||||
case ACTION_MANAGE_TOPICS:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1446,6 +1458,8 @@ public class ChatObject {
|
|||
return rights.send_polls;
|
||||
case ACTION_VIEW:
|
||||
return rights.view_messages;
|
||||
case ACTION_MANAGE_TOPICS:
|
||||
return rights.manage_topics;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1474,6 +1488,9 @@ public class ChatObject {
|
|||
case ACTION_PIN:
|
||||
value = chat.admin_rights.pin_messages;
|
||||
break;
|
||||
case ACTION_MANAGE_TOPICS:
|
||||
value = chat.admin_rights.manage_topics;
|
||||
break;
|
||||
case ACTION_CHANGE_INFO:
|
||||
value = chat.admin_rights.change_info;
|
||||
break;
|
||||
|
@ -1556,7 +1573,7 @@ public class ChatObject {
|
|||
}
|
||||
|
||||
public static boolean canSendAsPeers(TLRPC.Chat chat) {
|
||||
return ChatObject.isChannel(chat) && chat.megagroup && (!TextUtils.isEmpty(chat.username) || chat.has_geo || chat.has_link);
|
||||
return ChatObject.isChannel(chat) && chat.megagroup && (ChatObject.isPublic(chat) || chat.has_geo || chat.has_link);
|
||||
}
|
||||
|
||||
public static boolean isChannel(TLRPC.Chat chat) {
|
||||
|
@ -1575,6 +1592,10 @@ public class ChatObject {
|
|||
return isChannel(chat) && !isMegagroup(chat);
|
||||
}
|
||||
|
||||
public static boolean isForum(TLRPC.Chat chat) {
|
||||
return chat != null && chat.forum;
|
||||
}
|
||||
|
||||
public static boolean isMegagroup(int currentAccount, long chatId) {
|
||||
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId);
|
||||
return ChatObject.isChannel(chat) && chat.megagroup;
|
||||
|
@ -1664,6 +1685,33 @@ public class ChatObject {
|
|||
return canUserDoAction(chat, ACTION_PIN) || ChatObject.isChannel(chat) && !chat.megagroup && chat.admin_rights != null && chat.admin_rights.edit_messages;
|
||||
}
|
||||
|
||||
public static boolean canCreateTopic(TLRPC.Chat chat) {
|
||||
return canUserDoAction(chat, ACTION_MANAGE_TOPICS);
|
||||
}
|
||||
|
||||
public static boolean canManageTopics(TLRPC.Chat chat) {
|
||||
return canUserDoAdminAction(chat, ACTION_MANAGE_TOPICS);
|
||||
}
|
||||
|
||||
public static boolean canManageTopic(int currentAccount, TLRPC.Chat chat, TLRPC.TL_forumTopic topic) {
|
||||
return canManageTopics(chat) || isMyTopic(currentAccount, topic);
|
||||
}
|
||||
public static boolean canManageTopic(int currentAccount, TLRPC.Chat chat, int topicId) {
|
||||
return canManageTopics(chat) || isMyTopic(currentAccount, chat, topicId);
|
||||
}
|
||||
|
||||
public static boolean isMyTopic(int currentAccount, TLRPC.TL_forumTopic topic) {
|
||||
return topic != null && (topic.my || topic.from_id instanceof TLRPC.TL_peerUser && topic.from_id.user_id == UserConfig.getInstance(currentAccount).clientUserId);
|
||||
}
|
||||
|
||||
public static boolean isMyTopic(int currentAccount, TLRPC.Chat chat, int topicId) {
|
||||
return chat != null && chat.forum && isMyTopic(currentAccount, chat.id, topicId);
|
||||
}
|
||||
|
||||
public static boolean isMyTopic(int currentAccount, long chatId, int topicId) {
|
||||
return isMyTopic(currentAccount, MessagesController.getInstance(currentAccount).getTopicsController().findTopic(chatId, topicId));
|
||||
}
|
||||
|
||||
public static boolean isChannel(long chatId, int currentAccount) {
|
||||
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId);
|
||||
return chat instanceof TLRPC.TL_channel || chat instanceof TLRPC.TL_channelForbidden;
|
||||
|
@ -1697,6 +1745,7 @@ public class ChatObject {
|
|||
currentBannedRights += bannedRights.invite_users ? 1 : 0;
|
||||
currentBannedRights += bannedRights.change_info ? 1 : 0;
|
||||
currentBannedRights += bannedRights.pin_messages ? 1 : 0;
|
||||
currentBannedRights += bannedRights.manage_topics ? 1 : 0;
|
||||
currentBannedRights += bannedRights.until_date;
|
||||
return currentBannedRights;
|
||||
}
|
||||
|
@ -1709,6 +1758,53 @@ public class ChatObject {
|
|||
return hasPhoto(chat) ? chat.photo : null;
|
||||
}
|
||||
|
||||
public static String getPublicUsername(TLRPC.Chat chat) {
|
||||
return getPublicUsername(chat, false);
|
||||
}
|
||||
|
||||
public static String getPublicUsername(TLRPC.Chat chat, boolean editable) {
|
||||
if (chat == null) {
|
||||
return null;
|
||||
}
|
||||
if (!TextUtils.isEmpty(chat.username) && !editable) {
|
||||
return chat.username;
|
||||
}
|
||||
if (chat.usernames != null) {
|
||||
for (int i = 0; i < chat.usernames.size(); ++i) {
|
||||
TLRPC.TL_username u = chat.usernames.get(i);
|
||||
if (u != null && (u.active && !editable || u.editable) && !TextUtils.isEmpty(u.username)) {
|
||||
return u.username;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(chat.username) && editable && (chat.usernames == null || chat.usernames.size() <= 0)) {
|
||||
return chat.username;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean hasPublicLink(TLRPC.Chat chat, String username) {
|
||||
if (chat == null) {
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.isEmpty(chat.username)) {
|
||||
return chat.username.equalsIgnoreCase(username);
|
||||
}
|
||||
if (chat.usernames != null) {
|
||||
for (int i = 0; i < chat.usernames.size(); ++i) {
|
||||
TLRPC.TL_username u = chat.usernames.get(i);
|
||||
if (u != null && u.active && !TextUtils.isEmpty(u.username) && u.username.equalsIgnoreCase(username)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isPublic(TLRPC.Chat chat) {
|
||||
return !TextUtils.isEmpty(getPublicUsername(chat));
|
||||
}
|
||||
|
||||
public static class VideoParticipant {
|
||||
|
||||
public TLRPC.TL_groupCallParticipant participant;
|
||||
|
|
|
@ -242,7 +242,7 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
|
|||
} else {
|
||||
innerMessage = String.format("\uD83C\uDFAE %s", message.messageOwner.media.game.title);
|
||||
}
|
||||
} else if (message.type == 14) {
|
||||
} else if (message.type == MessageObject.TYPE_MUSIC) {
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
innerMessage = String.format("\uD83C\uDFA7 \u2068%s - %s\u2069", message.getMusicAuthor(), message.getMusicTitle());
|
||||
} else {
|
||||
|
@ -299,7 +299,7 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
|
|||
messageString = "\uD83D\uDCCA " + mediaPoll.poll.question;
|
||||
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
|
||||
messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title;
|
||||
} else if (message.type == 14) {
|
||||
} else if (message.type == MessageObject.TYPE_MUSIC) {
|
||||
messageString = String.format("\uD83C\uDFA7 %s - %s", message.getMusicAuthor(), message.getMusicTitle());
|
||||
} else {
|
||||
messageString = message.messageText;
|
||||
|
@ -326,7 +326,7 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
|
|||
if (dialog != null && dialog.unread_count > 0) {
|
||||
rv.setTextViewText(R.id.shortcut_widget_item_badge, String.format("%d", dialog.unread_count));
|
||||
rv.setViewVisibility(R.id.shortcut_widget_item_badge, View.VISIBLE);
|
||||
if (accountInstance.getMessagesController().isDialogMuted(dialog.id)) {
|
||||
if (accountInstance.getMessagesController().isDialogMuted(dialog.id, 0)) {
|
||||
rv.setBoolean(R.id.shortcut_widget_item_badge, "setEnabled", false);
|
||||
rv.setInt(R.id.shortcut_widget_item_badge, "setBackgroundResource", R.drawable.widget_badge_muted_background);
|
||||
} else {
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.telegram.SQLite.SQLitePreparedStatement;
|
|||
import org.telegram.tgnet.NativeByteBuffer;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.Components.Bulletin;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -1248,6 +1249,8 @@ public class DownloadController extends BaseController implements NotificationCe
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
|
||||
if (reason == 0) {
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.formatString("MessageNotFound", R.string.MessageNotFound));
|
||||
} else if (reason == -1) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -78,7 +78,7 @@ class FeedRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory, N
|
|||
String name;
|
||||
|
||||
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.feed_widget_item);
|
||||
if (messageObject.type == 0) {
|
||||
if (messageObject.type == MessageObject.TYPE_TEXT) {
|
||||
rv.setTextViewText(R.id.feed_widget_item_text, messageObject.messageText);
|
||||
rv.setViewVisibility(R.id.feed_widget_item_text, View.VISIBLE);
|
||||
} else {
|
||||
|
@ -143,7 +143,7 @@ class FeedRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory, N
|
|||
if (classGuid == 0) {
|
||||
classGuid = ConnectionsManager.generateClassGuid();
|
||||
}
|
||||
accountInstance.getMessagesController().loadMessages(dialogId, 0, false, 20, 0, 0, true, 0, classGuid, 0, 0, 0, 0, 0, 1);
|
||||
accountInstance.getMessagesController().loadMessages(dialogId, 0, false, 20, 0, 0, true, 0, classGuid, 0, 0, 0, 0, 0, 1, false);
|
||||
});
|
||||
try {
|
||||
countDownLatch.await();
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.telegram.tgnet.ConnectionsManager;
|
|||
import org.telegram.tgnet.NativeByteBuffer;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -525,7 +526,11 @@ public class FileLoadOperation {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
} else {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
totalTime += System.currentTimeMillis() - time;
|
||||
});
|
||||
|
@ -853,7 +858,11 @@ public class FileLoadOperation {
|
|||
}
|
||||
file.close();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
} else {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,7 +922,7 @@ public class FileLoadOperation {
|
|||
}
|
||||
preloadStream.seek(preloadStreamFileOffset);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
FileLog.e(e, false);
|
||||
}
|
||||
if (!isPreloadVideoOperation && preloadedBytesRanges == null) {
|
||||
cacheFilePreload = null;
|
||||
|
@ -1006,8 +1015,12 @@ public class FileLoadOperation {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
requestedBytesCount = downloadedBytes = 0;
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
} else {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isPreloadVideoOperation && downloadedBytes != 0 && totalBytesCount > 0) {
|
||||
|
@ -1020,7 +1033,13 @@ public class FileLoadOperation {
|
|||
fileOutputStream.seek(downloadedBytes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e, false);
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
onFail(true, -1);
|
||||
return false;
|
||||
} else {
|
||||
FileLog.e(e, false);
|
||||
}
|
||||
}
|
||||
if (fileOutputStream == null) {
|
||||
onFail(true, 0);
|
||||
|
@ -1046,7 +1065,13 @@ public class FileLoadOperation {
|
|||
delegate.saveFilePath(pathSaveData, null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
onFail(true, 0);
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
onFail(true, -1);
|
||||
} else {
|
||||
FileLog.e(e, false);
|
||||
onFail(true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1473,7 +1498,7 @@ public class FileLoadOperation {
|
|||
protected boolean processRequestResult(RequestInfo requestInfo, TLRPC.TL_error error) {
|
||||
if (state != stateDownloading) {
|
||||
if (BuildVars.DEBUG_VERSION && state == stateFinished) {
|
||||
FileLog.e(new Exception("trying to write to finished file " + fileName + " offset " + requestInfo.offset + " " + totalBytesCount));
|
||||
FileLog.e(new FileLog.IgnoreSentException("trying to write to finished file " + fileName + " offset " + requestInfo.offset + " " + totalBytesCount));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1692,8 +1717,12 @@ public class FileLoadOperation {
|
|||
startDownloadRequest();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
onFail(false, 0);
|
||||
FileLog.e(e);
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
onFail(false, -1);
|
||||
} else {
|
||||
FileLog.e(e);
|
||||
onFail(false, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (error.text.contains("FILE_MIGRATE_")) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.util.SparseArray;
|
|||
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -736,6 +737,8 @@ public class FileLoader extends BaseController {
|
|||
|
||||
if (document != null && parentObject instanceof MessageObject && reason == 0) {
|
||||
getDownloadController().onDownloadFail((MessageObject) parentObject, reason);
|
||||
} else if (reason == -1) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.util.Log;
|
|||
|
||||
import org.telegram.messenger.time.FastDateFormat;
|
||||
import org.telegram.messenger.video.MediaCodecVideoConvertor;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -228,7 +229,7 @@ public class FileLog {
|
|||
}
|
||||
|
||||
private static boolean needSent(Throwable e) {
|
||||
if (e instanceof InterruptedException || e instanceof MediaCodecVideoConvertor.ConversionCanceledException) {
|
||||
if (e instanceof InterruptedException || e instanceof MediaCodecVideoConvertor.ConversionCanceledException || e instanceof IgnoreSentException) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -247,6 +248,9 @@ public class FileLog {
|
|||
getInstance().streamWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (AndroidUtilities.isENOSPC(e)) {
|
||||
LaunchActivity.checkFreeDiscSpaceStatic(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -294,4 +298,12 @@ public class FileLog {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class IgnoreSentException extends Exception{
|
||||
|
||||
public IgnoreSentException(String e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,10 +43,8 @@ public class FilePathDatabase {
|
|||
cacheFile = new File(filesDir, DATABASE_NAME + ".db");
|
||||
shmCacheFile = new File(filesDir, DATABASE_NAME + ".db-shm");
|
||||
|
||||
|
||||
boolean createTable = false;
|
||||
|
||||
|
||||
if (!cacheFile.exists()) {
|
||||
createTable = true;
|
||||
}
|
||||
|
@ -145,20 +143,22 @@ public class FilePathDatabase {
|
|||
long time = System.currentTimeMillis();
|
||||
|
||||
dispatchQueue.postRunnable(() -> {
|
||||
SQLiteCursor cursor = null;
|
||||
try {
|
||||
cursor = database.queryFinalized("SELECT path FROM paths WHERE document_id = " + documentId + " AND dc_id = " + dc + " AND type = " + type);
|
||||
if (cursor.next()) {
|
||||
res[0] = cursor.stringValue(0);
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]);
|
||||
if (database != null) {
|
||||
SQLiteCursor cursor = null;
|
||||
try {
|
||||
cursor = database.queryFinalized("SELECT path FROM paths WHERE document_id = " + documentId + " AND dc_id = " + dc + " AND type = " + type);
|
||||
if (cursor.next()) {
|
||||
res[0] = cursor.stringValue(0);
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]);
|
||||
}
|
||||
}
|
||||
} catch (SQLiteException e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.dispose();
|
||||
}
|
||||
}
|
||||
} catch (SQLiteException e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.dispose();
|
||||
}
|
||||
}
|
||||
syncLatch.countDown();
|
||||
|
@ -169,6 +169,9 @@ public class FilePathDatabase {
|
|||
}
|
||||
return res[0];
|
||||
} else {
|
||||
if (database == null) {
|
||||
return null;
|
||||
}
|
||||
SQLiteCursor cursor = null;
|
||||
String res = null;
|
||||
try {
|
||||
|
@ -195,6 +198,9 @@ public class FilePathDatabase {
|
|||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("put file path id=" + id + " dc=" + dc + " type=" + type + " path=" + path);
|
||||
}
|
||||
if (database == null) {
|
||||
return;
|
||||
}
|
||||
SQLitePreparedStatement state = null;
|
||||
SQLitePreparedStatement deleteState = null;
|
||||
try {
|
||||
|
@ -266,7 +272,7 @@ public class FilePathDatabase {
|
|||
dispatchQueue.postRunnable(() -> {
|
||||
try {
|
||||
database.executeFast("DELETE FROM paths WHERE 1").stepThis().dispose();
|
||||
} catch (SQLiteException e) {
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1519,7 +1519,7 @@ public class ImageLoader {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
FileLog.e(e, !(e instanceof FileNotFoundException));
|
||||
}
|
||||
}
|
||||
Thread.interrupted();
|
||||
|
@ -1535,12 +1535,18 @@ public class ImageLoader {
|
|||
}
|
||||
|
||||
private void loadLastFrame(RLottieDrawable lottieDrawable, int w, int h, boolean lastFrame) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Bitmap bitmap;
|
||||
Canvas canvas;
|
||||
if (lastFrame) {
|
||||
canvas.scale(2f, 2f, w / 2f, h / 2f);
|
||||
bitmap = Bitmap.createBitmap((int) (w * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE), (int) (h * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE), Bitmap.Config.ARGB_8888);
|
||||
canvas = new Canvas(bitmap);
|
||||
canvas.scale(2f, 2f, w * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE / 2f, h * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE / 2f);
|
||||
} else {
|
||||
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
canvas = new Canvas(bitmap);
|
||||
}
|
||||
|
||||
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
lottieDrawable.setOnFrameReadyRunnable(() -> {
|
||||
lottieDrawable.setOnFrameReadyRunnable(null);
|
||||
|
@ -1553,8 +1559,13 @@ public class ImageLoader {
|
|||
}
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setFilterBitmap(true);
|
||||
canvas.drawBitmap(currentBitmap, 0, 0, paint);
|
||||
bitmapDrawable = new BitmapDrawable(bitmap);
|
||||
if (lastFrame) {
|
||||
canvas.drawBitmap(currentBitmap, (bitmap.getWidth() - currentBitmap.getWidth()) / 2f, (bitmap.getHeight() - currentBitmap.getHeight()) / 2f, paint);
|
||||
bitmapDrawable = new ImageReceiver.ReactionLastFrame(bitmap);
|
||||
} else {
|
||||
canvas.drawBitmap(currentBitmap, 0, 0, paint);
|
||||
bitmapDrawable = new BitmapDrawable(bitmap);
|
||||
}
|
||||
}
|
||||
onPostExecute(bitmapDrawable);
|
||||
lottieDrawable.recycle();
|
||||
|
|
|
@ -83,6 +83,17 @@ public class ImageLocation {
|
|||
return getForPhoto(photoSize, (TLRPC.Photo) object);
|
||||
} else if (object instanceof TLRPC.Document) {
|
||||
return getForDocument(photoSize, (TLRPC.Document) object);
|
||||
} else if (object instanceof TLRPC.Message) {
|
||||
return getForMessage(photoSize, (TLRPC.Message) object);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ImageLocation getForMessage(TLRPC.PhotoSize photoSize, TLRPC.Message message) {
|
||||
if (photoSize instanceof TLRPC.TL_photoStrippedSize || photoSize instanceof TLRPC.TL_photoPathSize) {
|
||||
ImageLocation imageLocation = new ImageLocation();
|
||||
imageLocation.photoSize = photoSize;
|
||||
return imageLocation;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import androidx.annotation.Keep;
|
|||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.Components.AnimatedFileDrawable;
|
||||
import org.telegram.ui.Components.AvatarDrawable;
|
||||
import org.telegram.ui.Components.LoadingStickerDrawable;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.RecyclableDrawable;
|
||||
|
@ -177,6 +178,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
|
||||
private int currentLayerNum;
|
||||
private int currentOpenedLayerFlags;
|
||||
private int isLastFrame;
|
||||
|
||||
private SetImageBackup setImageBackup;
|
||||
|
||||
|
@ -486,6 +488,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
if (staticThumbDrawable instanceof SvgHelper.SvgDrawable) {
|
||||
((SvgHelper.SvgDrawable) staticThumbDrawable).setParent(this);
|
||||
}
|
||||
updateDrawableRadius(staticThumbDrawable);
|
||||
|
||||
ImageLoader.getInstance().cancelLoadingForImageReceiver(this, true);
|
||||
invalidate();
|
||||
|
@ -883,15 +886,19 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
if (drawable == null) {
|
||||
return;
|
||||
}
|
||||
if ((hasRoundRadius() || gradientShader != null) && drawable instanceof BitmapDrawable) {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||
if (bitmapDrawable instanceof RLottieDrawable) {
|
||||
if ((hasRoundRadius() || gradientShader != null) && (drawable instanceof BitmapDrawable || drawable instanceof AvatarDrawable)) {
|
||||
if (drawable instanceof AvatarDrawable) {
|
||||
((AvatarDrawable) drawable).setRoundRadius(roundRadius[0]);
|
||||
} else {
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||
if (bitmapDrawable instanceof RLottieDrawable) {
|
||||
|
||||
} else if (bitmapDrawable instanceof AnimatedFileDrawable) {
|
||||
AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable;
|
||||
animatedFileDrawable.setRoundRadius(roundRadius);
|
||||
} else if (bitmapDrawable.getBitmap() != null) {
|
||||
setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
|
||||
} else if (bitmapDrawable instanceof AnimatedFileDrawable) {
|
||||
AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable;
|
||||
animatedFileDrawable.setRoundRadius(roundRadius);
|
||||
} else if (bitmapDrawable.getBitmap() != null) {
|
||||
setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setDrawableShader(drawable, null);
|
||||
|
@ -1027,6 +1034,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
RectF drawRegion;
|
||||
ColorFilter colorFilter;
|
||||
int[] roundRadius;
|
||||
boolean reactionLastFrame = false;
|
||||
if (backgroundThreadDrawHolder != null) {
|
||||
imageX = backgroundThreadDrawHolder.imageX;
|
||||
imageY = backgroundThreadDrawHolder.imageY;
|
||||
|
@ -1116,12 +1124,17 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
bitmapW = bitmap.getWidth();
|
||||
bitmapH = bitmap.getHeight();
|
||||
}
|
||||
reactionLastFrame = bitmapDrawable instanceof ReactionLastFrame;
|
||||
}
|
||||
float realImageW = imageW - sideClip * 2;
|
||||
float realImageH = imageH - sideClip * 2;
|
||||
float scaleW = imageW == 0 ? 1.0f : (bitmapW / realImageW);
|
||||
float scaleH = imageH == 0 ? 1.0f : (bitmapH / realImageH);
|
||||
|
||||
if (reactionLastFrame) {
|
||||
scaleW /= ReactionLastFrame.LAST_FRAME_SCALE;
|
||||
scaleH /= ReactionLastFrame.LAST_FRAME_SCALE;
|
||||
}
|
||||
if (shader != null && backgroundThreadDrawHolder == null) {
|
||||
if (isAspectFit) {
|
||||
float scale = Math.max(scaleW, scaleH);
|
||||
|
@ -1192,7 +1205,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
if (isVisible) {
|
||||
shaderMatrix.reset();
|
||||
shaderMatrix.setTranslate((int) (drawRegion.left + sideClip), (int) (drawRegion.top + sideClip));
|
||||
if (reactionLastFrame) {
|
||||
shaderMatrix.setTranslate((int) (drawRegion.left + sideClip) - (drawRegion.width() * ReactionLastFrame.LAST_FRAME_SCALE - drawRegion.width()) / 2f, (int) (drawRegion.top + sideClip) - (drawRegion.height() * ReactionLastFrame.LAST_FRAME_SCALE - drawRegion.height()) / 2f);
|
||||
} else {
|
||||
shaderMatrix.setTranslate((int) (drawRegion.left + sideClip), (int) (drawRegion.top + sideClip));
|
||||
}
|
||||
if (orientation == 90) {
|
||||
shaderMatrix.preRotate(90);
|
||||
shaderMatrix.preTranslate(0, -drawRegion.width());
|
||||
|
@ -1242,7 +1259,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
if (isRoundRect) {
|
||||
try {
|
||||
if (roundRadius[0] == 0) {
|
||||
canvas.drawRect(roundRect, roundPaint);
|
||||
if (reactionLastFrame) {
|
||||
AndroidUtilities.rectTmp.set(roundRect);
|
||||
AndroidUtilities.rectTmp.inset(-(drawRegion.width() * ReactionLastFrame.LAST_FRAME_SCALE - drawRegion.width()) / 2f, -(drawRegion.height() * ReactionLastFrame.LAST_FRAME_SCALE - drawRegion.height()) / 2f);
|
||||
canvas.drawRect(AndroidUtilities.rectTmp, roundPaint);
|
||||
} else {
|
||||
canvas.drawRect(roundRect, roundPaint);
|
||||
}
|
||||
} else {
|
||||
canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint);
|
||||
}
|
||||
|
@ -2211,7 +2234,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
if (currentThumbDrawable != null) {
|
||||
updateDrawableRadius(currentThumbDrawable);
|
||||
} else if (staticThumbDrawable != null) {
|
||||
}
|
||||
if (staticThumbDrawable != null) {
|
||||
updateDrawableRadius(staticThumbDrawable);
|
||||
}
|
||||
}
|
||||
|
@ -2922,4 +2946,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReactionLastFrame extends BitmapDrawable {
|
||||
|
||||
public final static float LAST_FRAME_SCALE = 1.2f;
|
||||
|
||||
public ReactionLastFrame(Bitmap bitmap) {
|
||||
super(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1063,6 +1063,10 @@ public class LocaleController {
|
|||
}
|
||||
|
||||
public static String formatPluralStringComma(String key, int plural) {
|
||||
return formatPluralStringComma(key, plural, ',');
|
||||
}
|
||||
|
||||
public static String formatPluralStringComma(String key, int plural, char symbol) {
|
||||
try {
|
||||
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
|
||||
return "LOC_ERR:" + key;
|
||||
|
@ -1071,7 +1075,7 @@ public class LocaleController {
|
|||
param = key + "_" + param;
|
||||
StringBuilder stringBuilder = new StringBuilder(String.format(Locale.US, "%d", plural));
|
||||
for (int a = stringBuilder.length() - 3; a > 0; a -= 3) {
|
||||
stringBuilder.insert(a, ',');
|
||||
stringBuilder.insert(a, symbol);
|
||||
}
|
||||
|
||||
String value = BuildVars.USE_CLOUD_STRINGS ? getInstance().localeValues.get(param) : null;
|
||||
|
|
|
@ -52,6 +52,7 @@ import android.provider.OpenableColumns;
|
|||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.TextureView;
|
||||
|
@ -520,6 +521,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
public static ArrayList<AlbumEntry> allPhotoAlbums = new ArrayList<>();
|
||||
private static Runnable broadcastPhotosRunnable;
|
||||
|
||||
public boolean isSilent = false;
|
||||
private boolean isPaused = false;
|
||||
private VideoPlayer audioPlayer = null;
|
||||
private VideoPlayer emojiSoundPlayer = null;
|
||||
|
@ -1044,7 +1046,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
private void setPlayerVolume() {
|
||||
try {
|
||||
float volume;
|
||||
if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK) {
|
||||
if (isSilent) {
|
||||
volume = 0;
|
||||
} else if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK) {
|
||||
volume = VOLUME_NORMAL;
|
||||
} else {
|
||||
volume = VOLUME_DUCK;
|
||||
|
@ -2126,12 +2130,13 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
return;
|
||||
}
|
||||
//TODO topics
|
||||
if (!playlistEndReached[0]) {
|
||||
loadingPlaylist = true;
|
||||
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid, 0);
|
||||
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0);
|
||||
} else if (playlistMergeDialogId != 0 && !playlistEndReached[1]) {
|
||||
loadingPlaylist = true;
|
||||
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid, 0);
|
||||
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2443,6 +2448,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isPiPShown() {
|
||||
return pipRoundVideoView != null;
|
||||
}
|
||||
|
||||
public void setCurrentVideoVisible(boolean visible) {
|
||||
if (currentAspectRatioFrameLayout == null) {
|
||||
return;
|
||||
|
@ -2479,6 +2488,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
|
||||
public void setTextureView(TextureView textureView, AspectRatioFrameLayout aspectRatioFrameLayout, FrameLayout container, boolean set) {
|
||||
setTextureView(textureView, aspectRatioFrameLayout, container, set, false);
|
||||
}
|
||||
|
||||
public void setTextureView(TextureView textureView, AspectRatioFrameLayout aspectRatioFrameLayout, FrameLayout container, boolean set, boolean forcePip) {
|
||||
if (textureView == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -2494,6 +2507,16 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
isDrawingWasReady = aspectRatioFrameLayout != null && aspectRatioFrameLayout.isDrawingReady();
|
||||
currentTextureView = textureView;
|
||||
if (forcePip && pipRoundVideoView == null) {
|
||||
try {
|
||||
pipRoundVideoView = new PipRoundVideoView();
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true));
|
||||
}, 350);
|
||||
} catch (Exception e) {
|
||||
pipRoundVideoView = null;
|
||||
}
|
||||
}
|
||||
if (pipRoundVideoView != null) {
|
||||
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
||||
} else {
|
||||
|
@ -2839,6 +2862,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
|
||||
private static long volumeBarLastTimeShown;
|
||||
public void checkVolumeBarUI() {
|
||||
if (isSilent) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final long now = System.currentTimeMillis();
|
||||
if (Math.abs(now - volumeBarLastTimeShown) < 5000) {
|
||||
|
@ -2874,9 +2900,14 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
|
||||
public boolean playMessage(final MessageObject messageObject) {
|
||||
return playMessage(messageObject, false);
|
||||
}
|
||||
|
||||
public boolean playMessage(final MessageObject messageObject, boolean silent) {
|
||||
if (messageObject == null) {
|
||||
return false;
|
||||
}
|
||||
isSilent = silent;
|
||||
checkVolumeBarUI();
|
||||
if ((audioPlayer != null || videoPlayer != null) && isSamePlayingMessage(messageObject)) {
|
||||
if (isPaused) {
|
||||
|
@ -2958,6 +2989,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
int[] playCount = isVideo && messageObject.getDuration() <= 30 ? new int[]{1} : null;
|
||||
clearPlaylist();
|
||||
videoPlayer = new VideoPlayer();
|
||||
videoPlayer.setLooping(silent);
|
||||
int tag = ++playerNum;
|
||||
videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
|
||||
@Override
|
||||
|
@ -3332,6 +3364,18 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
return true;
|
||||
}
|
||||
|
||||
public void updateSilent(boolean value) {
|
||||
isSilent = value;
|
||||
if (videoPlayer != null) {
|
||||
videoPlayer.setLooping(value);
|
||||
}
|
||||
setPlayerVolume();
|
||||
checkVolumeBarUI();
|
||||
if (playingMessageObject != null) {
|
||||
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject != null ? playingMessageObject.getId() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
public AudioInfo getAudioInfo() {
|
||||
return audioInfo;
|
||||
}
|
||||
|
@ -3413,7 +3457,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
audioVolumeAnimator.removeAllListeners();
|
||||
audioVolumeAnimator.cancel();
|
||||
}
|
||||
if (!messageObject.isVoice()) {
|
||||
if (!messageObject.isVoice() && !messageObject.isRoundVideo()) {
|
||||
audioVolumeAnimator = ValueAnimator.ofFloat(audioVolume, 1f);
|
||||
audioVolumeAnimator.addUpdateListener(audioVolumeUpdateListener);
|
||||
audioVolumeAnimator.setDuration(300);
|
||||
|
@ -3604,7 +3648,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
}
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(messageObject1.messageOwner);
|
||||
MessagesStorage.getInstance(messageObject1.currentAccount).putMessages(messagesRes, messageObject1.getDialogId(), -1, 0, false, messageObject.scheduled);
|
||||
MessagesStorage.getInstance(messageObject1.currentAccount).putMessages(messagesRes, messageObject1.getDialogId(), -1, 0, false, messageObject.scheduled, 0);
|
||||
ArrayList<MessageObject> arrayList = new ArrayList<>();
|
||||
arrayList.add(messageObject1);
|
||||
NotificationCenter.getInstance(messageObject1.currentAccount).postNotificationName(NotificationCenter.replaceMessagesObjects, messageObject1.getDialogId(), arrayList);
|
||||
|
|
|
@ -65,7 +65,6 @@ import org.telegram.ui.Components.Bulletin;
|
|||
import org.telegram.ui.Components.ChatThemeBottomSheet;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsUtils;
|
||||
import org.telegram.ui.Components.StickerSetBulletinLayout;
|
||||
import org.telegram.ui.Components.StickersArchiveAlert;
|
||||
|
@ -258,6 +257,7 @@ public class MediaDataController extends BaseController {
|
|||
|
||||
private boolean loadingPremiumGiftStickers;
|
||||
private boolean loadingGenericAnimations;
|
||||
private boolean loadingDefaultTopicIcons;
|
||||
|
||||
private long loadFeaturedHash[] = new long[2];
|
||||
private int loadFeaturedDate[] = new int[2];
|
||||
|
@ -598,12 +598,17 @@ public class MediaDataController extends BaseController {
|
|||
c.dispose();
|
||||
}
|
||||
}
|
||||
processLoadedReactions(reactions, hash, date, true);
|
||||
List<TLRPC.TL_availableReaction> finalReactions = reactions;
|
||||
int finalHash = hash;
|
||||
int finalDate = date;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
processLoadedReactions(finalReactions, finalHash, finalDate, true);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
TLRPC.TL_messages_getAvailableReactions req = new TLRPC.TL_messages_getAvailableReactions();
|
||||
req.hash = force ? 0 : reactionsUpdateHash;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
int date = (int) (System.currentTimeMillis() / 1000);
|
||||
if (response instanceof TLRPC.TL_messages_availableReactionsNotModified) {
|
||||
processLoadedReactions(null, 0, date, false);
|
||||
|
@ -611,7 +616,7 @@ public class MediaDataController extends BaseController {
|
|||
TLRPC.TL_messages_availableReactions r = (TLRPC.TL_messages_availableReactions) response;
|
||||
processLoadedReactions(r.reactions, r.hash, date, false);
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2048,7 +2053,7 @@ public class MediaDataController extends BaseController {
|
|||
private void processLoadStickersResponse(int type, TLRPC.TL_messages_allStickers res, Runnable onDone) {
|
||||
ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = new ArrayList<>();
|
||||
if (res.sets.isEmpty()) {
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash, onDone);
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash2, onDone);
|
||||
} else {
|
||||
LongSparseArray<TLRPC.TL_messages_stickerSet> newStickerSets = new LongSparseArray<>();
|
||||
for (int a = 0; a < res.sets.size(); a++) {
|
||||
|
@ -2063,7 +2068,7 @@ public class MediaDataController extends BaseController {
|
|||
newStickerArray.add(oldSet);
|
||||
|
||||
if (newStickerSets.size() == res.sets.size()) {
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash);
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash2);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -2087,7 +2092,7 @@ public class MediaDataController extends BaseController {
|
|||
a1--;
|
||||
}
|
||||
}
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash);
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash2);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -2140,7 +2145,7 @@ public class MediaDataController extends BaseController {
|
|||
MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, true);
|
||||
}
|
||||
}
|
||||
if (loadingGenericAnimations /*|| System.currentTimeMillis() - getUserConfig().lastUpdatedGenericAnimations < 86400000*/) {
|
||||
if (loadingGenericAnimations || System.currentTimeMillis() - getUserConfig().lastUpdatedGenericAnimations < 86400000) {
|
||||
return;
|
||||
}
|
||||
loadingGenericAnimations = true;
|
||||
|
@ -2162,6 +2167,39 @@ public class MediaDataController extends BaseController {
|
|||
}));
|
||||
}
|
||||
|
||||
public void checkDefaultTopicIcons() {
|
||||
if (getUserConfig().defaultTopicIcons != null) {
|
||||
String packName = getUserConfig().defaultTopicIcons;
|
||||
TLRPC.TL_messages_stickerSet set = getStickerSetByName(packName);
|
||||
if (set == null) {
|
||||
set = getStickerSetByEmojiOrName(packName);
|
||||
}
|
||||
if (set == null) {
|
||||
MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, true);
|
||||
}
|
||||
}
|
||||
if (loadingDefaultTopicIcons || System.currentTimeMillis() - getUserConfig().lastUpdatedDefaultTopicIcons < 86400000) {
|
||||
return;
|
||||
}
|
||||
loadingDefaultTopicIcons = true;
|
||||
|
||||
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
|
||||
req.stickerset = new TLRPC.TL_inputStickerSetEmojiDefaultTopicIcons();
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response instanceof TLRPC.TL_messages_stickerSet) {
|
||||
TLRPC.TL_messages_stickerSet stickerSet = (TLRPC.TL_messages_stickerSet) response;
|
||||
getUserConfig().defaultTopicIcons = stickerSet.set.short_name;
|
||||
getUserConfig().lastUpdatedDefaultTopicIcons = System.currentTimeMillis();
|
||||
getUserConfig().saveConfig(false);
|
||||
|
||||
processLoadedDiceStickers(getUserConfig().defaultTopicIcons, false, stickerSet, false, (int) (System.currentTimeMillis() / 1000));
|
||||
for (int i = 0; i < stickerSet.documents.size(); i++) {
|
||||
preloadImage(ImageLocation.getForDocument(stickerSet.documents.get(i)), null);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void loadStickersByEmojiOrName(String name, boolean isEmoji, boolean cache) {
|
||||
if (loadingDiceStickerSets.contains(name) || isEmoji && diceStickerSetsByEmoji.get(name) != null) {
|
||||
return;
|
||||
|
@ -2366,7 +2404,7 @@ public class MediaDataController extends BaseController {
|
|||
if (type == TYPE_FEATURED || type == TYPE_FEATURED_EMOJIPACKS) {
|
||||
final boolean emoji = type == TYPE_FEATURED_EMOJIPACKS;
|
||||
TLRPC.TL_messages_allStickers response = new TLRPC.TL_messages_allStickers();
|
||||
response.hash = loadFeaturedHash[emoji ? 1 : 0];
|
||||
response.hash2 = loadFeaturedHash[emoji ? 1 : 0];
|
||||
for (int a = 0, size = featuredStickerSets[emoji ? 1 : 0].size(); a < size; a++) {
|
||||
response.sets.add(featuredStickerSets[emoji ? 1 : 0].get(a).set);
|
||||
}
|
||||
|
@ -2482,9 +2520,12 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
|
||||
public static long getStickerSetId(TLRPC.Document document) {
|
||||
if (document == null) {
|
||||
return -1;
|
||||
}
|
||||
for (int a = 0; a < document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker || attribute instanceof TLRPC.TL_documentAttributeCustomEmoji) {
|
||||
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetID) {
|
||||
return attribute.stickerset.id;
|
||||
}
|
||||
|
@ -3142,6 +3183,10 @@ public class MediaDataController extends BaseController {
|
|||
req.from_id = MessagesController.getInputPeer(chat);
|
||||
req.flags |= 1;
|
||||
}
|
||||
if (replyMessageId != 0) {
|
||||
req.top_msg_id = replyMessageId;
|
||||
req.flags |= 2;
|
||||
}
|
||||
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
|
||||
mergeReqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (lastMergeDialogId == mergeDialogId) {
|
||||
|
@ -3281,14 +3326,14 @@ public class MediaDataController extends BaseController {
|
|||
public final static int MEDIA_TYPES_COUNT = 8;
|
||||
|
||||
|
||||
public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, int fromCache, int classGuid, int requestIndex) {
|
||||
public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, int topicId, int fromCache, int classGuid, int requestIndex) {
|
||||
boolean isChannel = DialogObject.isChatDialog(dialogId) && ChatObject.isChannel(-dialogId, currentAccount);
|
||||
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid);
|
||||
}
|
||||
if ((fromCache != 0 || DialogObject.isEncryptedDialog(dialogId))) {
|
||||
loadMediaDatabase(dialogId, count, max_id, min_id, type, classGuid, isChannel, fromCache, requestIndex);
|
||||
if (fromCache != 0 || DialogObject.isEncryptedDialog(dialogId)) {
|
||||
loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, classGuid, isChannel, fromCache, requestIndex);
|
||||
} else {
|
||||
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
|
||||
req.limit = count;
|
||||
|
@ -3318,6 +3363,10 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
req.q = "";
|
||||
req.peer = getMessagesController().getInputPeer(dialogId);
|
||||
if (topicId != 0) {
|
||||
req.top_msg_id = topicId;
|
||||
req.flags |= 2;
|
||||
}
|
||||
if (req.peer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -3332,20 +3381,25 @@ public class MediaDataController extends BaseController {
|
|||
topReached = res.messages.size() == 0;
|
||||
}
|
||||
|
||||
processLoadedMedia(res, dialogId, count, max_id, min_id, type, 0, classGuid, isChannel, topReached, requestIndex);
|
||||
processLoadedMedia(res, dialogId, count, max_id, min_id, type, topicId, 0, classGuid, isChannel, topReached, requestIndex);
|
||||
}
|
||||
});
|
||||
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
|
||||
}
|
||||
}
|
||||
|
||||
public void getMediaCounts(long dialogId, int classGuid) {
|
||||
public void getMediaCounts(long dialogId, int topicId, int classGuid) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
try {
|
||||
int[] counts = new int[]{-1, -1, -1, -1, -1, -1, -1, -1};
|
||||
int[] countsFinal = new int[]{-1, -1, -1, -1, -1, -1, -1, -1};
|
||||
int[] old = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
|
||||
SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT type, count, old FROM media_counts_v2 WHERE uid = %d", dialogId));
|
||||
SQLiteCursor cursor;
|
||||
if (topicId != 0) {
|
||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT type, count, old FROM media_counts_topics WHERE uid = %d AND topic_id = %d", dialogId, topicId));
|
||||
} else {
|
||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT type, count, old FROM media_counts_v2 WHERE uid = %d", dialogId));
|
||||
}
|
||||
while (cursor.next()) {
|
||||
int type = cursor.intValue(0);
|
||||
if (type >= 0 && type < MEDIA_TYPES_COUNT) {
|
||||
|
@ -3364,14 +3418,18 @@ public class MediaDataController extends BaseController {
|
|||
counts[a] = 0;
|
||||
}
|
||||
cursor.dispose();
|
||||
putMediaCountDatabase(dialogId, a, counts[a]);
|
||||
putMediaCountDatabase(dialogId, topicId, a, counts[a]);
|
||||
}
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, counts));
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, counts));
|
||||
} else {
|
||||
boolean missing = false;
|
||||
TLRPC.TL_messages_getSearchCounters req = new TLRPC.TL_messages_getSearchCounters();
|
||||
req.peer = getMessagesController().getInputPeer(dialogId);
|
||||
if (topicId != 0) {
|
||||
req.top_msg_id = topicId;
|
||||
req.flags |= 1;
|
||||
}
|
||||
for (int a = 0; a < counts.length; a++) {
|
||||
if (req.peer == null) {
|
||||
counts[a] = 0;
|
||||
|
@ -3434,15 +3492,15 @@ public class MediaDataController extends BaseController {
|
|||
continue;
|
||||
}
|
||||
counts[type] = searchCounter.count;
|
||||
putMediaCountDatabase(dialogId, type, counts[type]);
|
||||
putMediaCountDatabase(dialogId, topicId, type, counts[type]);
|
||||
}
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, counts));
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, counts));
|
||||
});
|
||||
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
|
||||
}
|
||||
if (!missing) {
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, countsFinal));
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, countsFinal));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -3451,9 +3509,9 @@ public class MediaDataController extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
public void getMediaCount(long dialogId, int type, int classGuid, boolean fromCache) {
|
||||
public void getMediaCount(long dialogId, int topicId, int type, int classGuid, boolean fromCache) {
|
||||
if (fromCache || DialogObject.isEncryptedDialog(dialogId)) {
|
||||
getMediaCountDatabase(dialogId, type, classGuid);
|
||||
getMediaCountDatabase(dialogId, topicId, type, classGuid);
|
||||
} else {
|
||||
TLRPC.TL_messages_getSearchCounters req = new TLRPC.TL_messages_getSearchCounters();
|
||||
if (type == MEDIA_PHOTOVIDEO) {
|
||||
|
@ -3469,6 +3527,10 @@ public class MediaDataController extends BaseController {
|
|||
} else if (type == MEDIA_GIF) {
|
||||
req.filters.add(new TLRPC.TL_inputMessagesFilterGif());
|
||||
}
|
||||
if (topicId != 0) {
|
||||
req.top_msg_id = topicId;
|
||||
req.flags |= 1;
|
||||
}
|
||||
req.peer = getMessagesController().getInputPeer(dialogId);
|
||||
if (req.peer == null) {
|
||||
return;
|
||||
|
@ -3478,7 +3540,7 @@ public class MediaDataController extends BaseController {
|
|||
TLRPC.Vector res = (TLRPC.Vector) response;
|
||||
if (!res.objects.isEmpty()) {
|
||||
TLRPC.TL_messages_searchCounter counter = (TLRPC.TL_messages_searchCounter) res.objects.get(0);
|
||||
processLoadedMediaCount(counter.count, dialogId, type, classGuid, false, 0);
|
||||
processLoadedMediaCount(counter.count, dialogId, topicId, type, classGuid, false, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -3551,20 +3613,24 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int count, int max_id, int min_id, int type, int fromCache, int classGuid, boolean isChannel, boolean topReached, int requestIndex) {
|
||||
private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int count, int max_id, int min_id, int type, int topicId, int fromCache, int classGuid, boolean isChannel, boolean topReached, int requestIndex) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("process load media did " + dialogId + " count = " + count + " max_id=" + max_id + " min_id=" + min_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid);
|
||||
int messagesCount = 0;
|
||||
if (res != null && res.messages != null) {
|
||||
messagesCount = res.messages.size();
|
||||
}
|
||||
FileLog.d("process load media messagesCount " + messagesCount + " did " + dialogId + " topicId " + topicId + " count = " + count + " max_id=" + max_id + " min_id=" + min_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid);
|
||||
}
|
||||
if (fromCache != 0 && ((res.messages.isEmpty() && min_id == 0) || (res.messages.size() <= 1 && min_id != 0)) && !DialogObject.isEncryptedDialog(dialogId)) {
|
||||
if (fromCache == 2) {
|
||||
return;
|
||||
}
|
||||
loadMedia(dialogId, count, max_id, min_id, type, 0, classGuid, requestIndex);
|
||||
loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex);
|
||||
} else {
|
||||
if (fromCache == 0) {
|
||||
ImageLoader.saveMessagesThumbs(res.messages);
|
||||
getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true);
|
||||
putMediaDatabase(dialogId, type, res.messages, max_id, min_id, topReached);
|
||||
putMediaDatabase(dialogId, topicId, type, res.messages, max_id, min_id, topReached);
|
||||
}
|
||||
|
||||
Utilities.searchQueue.postRunnable(() -> {
|
||||
|
@ -3592,31 +3658,40 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private void processLoadedMediaCount(int count, long dialogId, int type, int classGuid, boolean fromCache, int old) {
|
||||
private void processLoadedMediaCount(int count, long dialogId, int topicId, int type, int classGuid, boolean fromCache, int old) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
boolean isEncryptedDialog = DialogObject.isEncryptedDialog(dialogId);
|
||||
boolean reload = fromCache && (count == -1 || count == 0 && type == 2) && !isEncryptedDialog;
|
||||
if (reload || old == 1 && !isEncryptedDialog) {
|
||||
getMediaCount(dialogId, type, classGuid, false);
|
||||
getMediaCount(dialogId, topicId, type, classGuid, false);
|
||||
}
|
||||
if (!reload) {
|
||||
if (!fromCache) {
|
||||
putMediaCountDatabase(dialogId, type, count);
|
||||
putMediaCountDatabase(dialogId, topicId, type, count);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.mediaCountDidLoad, dialogId, (fromCache && count == -1 ? 0 : count), fromCache, type);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.mediaCountDidLoad, dialogId, topicId, (fromCache && count == -1 ? 0 : count), fromCache, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void putMediaCountDatabase(long uid, int type, int count) {
|
||||
private void putMediaCountDatabase(long uid, int topicId, int type, int count) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
try {
|
||||
SQLitePreparedStatement state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)");
|
||||
SQLitePreparedStatement state2;
|
||||
if (topicId != 0) {
|
||||
state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_counts_topics VALUES(?, ?, ?, ?, ?)");
|
||||
} else {
|
||||
state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)");
|
||||
}
|
||||
int pointer = 1;
|
||||
state2.requery();
|
||||
state2.bindLong(1, uid);
|
||||
state2.bindInteger(2, type);
|
||||
state2.bindInteger(3, count);
|
||||
state2.bindInteger(4, 0);
|
||||
state2.bindLong(pointer++, uid);
|
||||
if (topicId != 0) {
|
||||
state2.bindInteger(pointer++, topicId);
|
||||
}
|
||||
state2.bindInteger(pointer++, type);
|
||||
state2.bindInteger(pointer++, count);
|
||||
state2.bindInteger(pointer++, 0);
|
||||
state2.step();
|
||||
state2.dispose();
|
||||
} catch (Exception e) {
|
||||
|
@ -3625,12 +3700,17 @@ public class MediaDataController extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
private void getMediaCountDatabase(long dialogId, int type, int classGuid) {
|
||||
private void getMediaCountDatabase(long dialogId, int topicId, int type, int classGuid) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
try {
|
||||
int count = -1;
|
||||
int old = 0;
|
||||
SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", dialogId, type));
|
||||
SQLiteCursor cursor;
|
||||
if (topicId != 0) {
|
||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_topics WHERE uid = %d AND topic_id = %d AND type = %d LIMIT 1", dialogId, topicId, type));
|
||||
} else {
|
||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", dialogId, type));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
count = cursor.intValue(0);
|
||||
old = cursor.intValue(1);
|
||||
|
@ -3644,17 +3724,17 @@ public class MediaDataController extends BaseController {
|
|||
cursor.dispose();
|
||||
|
||||
if (count != -1) {
|
||||
putMediaCountDatabase(dialogId, type, count);
|
||||
putMediaCountDatabase(dialogId, topicId, type, count);
|
||||
}
|
||||
}
|
||||
processLoadedMediaCount(count, dialogId, type, classGuid, true, old);
|
||||
processLoadedMediaCount(count, dialogId, topicId, type, classGuid, true, old);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, int classGuid, boolean isChannel, int fromCache, int requestIndex) {
|
||||
private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, int topicId, int classGuid, boolean isChannel, int fromCache, int requestIndex) {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -3669,23 +3749,41 @@ public class MediaDataController extends BaseController {
|
|||
SQLiteDatabase database = getMessagesStorage().getDatabase();
|
||||
boolean isEnd = false;
|
||||
boolean reverseMessages = false;
|
||||
|
||||
if (!DialogObject.isEncryptedDialog(uid)) {
|
||||
if (min_id == 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_v2 WHERE uid = %d AND type = %d AND start IN (0, 1)", uid, type));
|
||||
if (topicId != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_topics WHERE uid = %d AND topic_id = %d AND type = %d AND start IN (0, 1)", uid, topicId, type));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_v2 WHERE uid = %d AND type = %d AND start IN (0, 1)", uid, type));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
isEnd = cursor.intValue(0) == 1;
|
||||
} else {
|
||||
cursor.dispose();
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_v4 WHERE uid = %d AND type = %d AND mid > 0", uid, type));
|
||||
if (topicId != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_topics WHERE uid = %d AND topic_id = %d AND type = %d AND mid > 0", uid, topicId, type));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_v4 WHERE uid = %d AND type = %d AND mid > 0", uid, type));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
int mid = cursor.intValue(0);
|
||||
if (mid != 0) {
|
||||
SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)");
|
||||
SQLitePreparedStatement state;
|
||||
if (topicId != 0) {
|
||||
state = database.executeFast("REPLACE INTO media_holes_topics VALUES(?, ?, ?, ?, ?)");
|
||||
} else {
|
||||
state = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)");
|
||||
}
|
||||
int pointer = 1;
|
||||
state.requery();
|
||||
state.bindLong(1, uid);
|
||||
state.bindInteger(2, type);
|
||||
state.bindInteger(3, 0);
|
||||
state.bindInteger(4, mid);
|
||||
state.bindLong(pointer++, uid);
|
||||
if (topicId != 0) {
|
||||
state.bindInteger(pointer++, topicId);
|
||||
}
|
||||
state.bindInteger(pointer++, type);
|
||||
state.bindInteger(pointer++, 0);
|
||||
state.bindInteger(pointer++, mid);
|
||||
state.step();
|
||||
state.dispose();
|
||||
}
|
||||
|
@ -3697,57 +3795,106 @@ public class MediaDataController extends BaseController {
|
|||
int holeMessageId = 0;
|
||||
if (max_id != 0) {
|
||||
int startHole = 0;
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND start <= %d ORDER BY end DESC LIMIT 1", uid, type, max_id));
|
||||
if (topicId != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_topics WHERE uid = %d AND topic_id = %d AND type = %d AND start <= %d ORDER BY end DESC LIMIT 1", uid, topicId, type, max_id));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND start <= %d ORDER BY end DESC LIMIT 1", uid, type, max_id));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
startHole = cursor.intValue(0);
|
||||
holeMessageId = cursor.intValue(1);
|
||||
}
|
||||
cursor.dispose();
|
||||
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad));
|
||||
isEnd = false;
|
||||
if (topicId != 0) {
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, holeMessageId, type, countToLoad));
|
||||
isEnd = false;
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, type, countToLoad));
|
||||
}
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad));
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad));
|
||||
isEnd = false;
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad));
|
||||
}
|
||||
}
|
||||
} else if (min_id != 0) {
|
||||
int startHole = 0;
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND end >= %d ORDER BY end ASC LIMIT 1", uid, type, min_id));
|
||||
if (topicId != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_topics WHERE uid = %d AND topic_id = %d AND type = %d AND end >= %d ORDER BY end ASC LIMIT 1", uid, topicId, type, min_id));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND end >= %d ORDER BY end ASC LIMIT 1", uid, type, min_id));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
startHole = cursor.intValue(0);
|
||||
holeMessageId = cursor.intValue(1);
|
||||
}
|
||||
cursor.dispose();
|
||||
reverseMessages = true;
|
||||
if (startHole > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, startHole, type, countToLoad));
|
||||
if (topicId != 0) {
|
||||
if (startHole > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, startHole, type, countToLoad));
|
||||
} else {
|
||||
isEnd = true;
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, type, countToLoad));
|
||||
}
|
||||
} else {
|
||||
isEnd = true;
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, type, countToLoad));
|
||||
if (startHole > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, startHole, type, countToLoad));
|
||||
} else {
|
||||
isEnd = true;
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, type, countToLoad));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM media_holes_v2 WHERE uid = %d AND type = %d", uid, type));
|
||||
if (topicId != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM media_holes_topics WHERE uid = %d AND topic_id = %d AND type = %d", uid, topicId, type));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM media_holes_v2 WHERE uid = %d AND type = %d", uid, type));
|
||||
}
|
||||
if (cursor.next()) {
|
||||
holeMessageId = cursor.intValue(0);
|
||||
}
|
||||
cursor.dispose();
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad));
|
||||
if (topicId != 0) {
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, holeMessageId, type, countToLoad));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, type, countToLoad));
|
||||
}
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad));
|
||||
if (holeMessageId > 1) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isEnd = true;
|
||||
if (max_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, countToLoad));
|
||||
} else if (min_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d AND type = %d ORDER BY m.mid DESC LIMIT %d", uid, min_id, type, countToLoad));
|
||||
if (topicId != 0) {
|
||||
if (max_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_topics as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.topic_id = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, topicId, max_id, type, countToLoad));
|
||||
} else if (min_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_topics as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.topic_id = %d AND m.mid < %d AND type = %d ORDER BY m.mid DESC LIMIT %d", uid, topicId, min_id, type, countToLoad));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_topics as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.topic_id = %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, topicId, type, countToLoad));
|
||||
}
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, type, countToLoad));
|
||||
if (max_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, countToLoad));
|
||||
} else if (min_id != 0) {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d AND type = %d ORDER BY m.mid DESC LIMIT %d", uid, min_id, type, countToLoad));
|
||||
} else {
|
||||
cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, type, countToLoad));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (cursor.next()) {
|
||||
NativeByteBuffer data = cursor.byteBufferValue(0);
|
||||
if (data != null) {
|
||||
|
@ -3793,7 +3940,7 @@ public class MediaDataController extends BaseController {
|
|||
} finally {
|
||||
Runnable task = this;
|
||||
AndroidUtilities.runOnUIThread(() -> getMessagesStorage().completeTaskForGuid(task, classGuid));
|
||||
processLoadedMedia(res, uid, count, max_id, min_id, type, fromCache, classGuid, isChannel, topReached, requestIndex);
|
||||
processLoadedMedia(res, uid, count, max_id, min_id, type, topicId, fromCache, classGuid, isChannel, topReached, requestIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -3802,27 +3949,37 @@ public class MediaDataController extends BaseController {
|
|||
messagesStorage.bindTaskToGuid(runnable, classGuid);
|
||||
}
|
||||
|
||||
private void putMediaDatabase(long uid, int type, ArrayList<TLRPC.Message> messages, int max_id, int min_id, boolean topReached) {
|
||||
private void putMediaDatabase(long uid, int topicId, int type, ArrayList<TLRPC.Message> messages, int max_id, int min_id, boolean topReached) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
try {
|
||||
if (min_id == 0 && (messages.isEmpty() || topReached)) {
|
||||
getMessagesStorage().doneHolesInMedia(uid, max_id, type);
|
||||
getMessagesStorage().doneHolesInMedia(uid, max_id, type, topicId);
|
||||
if (messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
getMessagesStorage().getDatabase().beginTransaction();
|
||||
SQLitePreparedStatement state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)");
|
||||
SQLitePreparedStatement state2;
|
||||
if (topicId != 0) {
|
||||
state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_topics VALUES(?, ?, ?, ?, ?, ?)");
|
||||
} else {
|
||||
state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)");
|
||||
}
|
||||
|
||||
for (TLRPC.Message message : messages) {
|
||||
if (canAddMessageToMedia(message)) {
|
||||
state2.requery();
|
||||
NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize());
|
||||
message.serializeToStream(data);
|
||||
state2.bindInteger(1, message.id);
|
||||
state2.bindLong(2, uid);
|
||||
state2.bindInteger(3, message.date);
|
||||
state2.bindInteger(4, type);
|
||||
state2.bindByteBuffer(5, data);
|
||||
int pointer = 1;
|
||||
state2.bindInteger(pointer++, message.id);
|
||||
state2.bindLong(pointer++, uid);
|
||||
if (topicId != 0) {
|
||||
state2.bindInteger(pointer++, topicId);
|
||||
}
|
||||
state2.bindInteger(pointer++, message.date);
|
||||
state2.bindInteger(pointer++, type);
|
||||
state2.bindByteBuffer(pointer++, data);
|
||||
state2.step();
|
||||
data.reuse();
|
||||
}
|
||||
|
@ -3831,11 +3988,11 @@ public class MediaDataController extends BaseController {
|
|||
if (!topReached || max_id != 0 || min_id != 0) {
|
||||
int minId = (topReached && min_id == 0) ? 1 : messages.get(messages.size() - 1).id;
|
||||
if (min_id != 0) {
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, messages.get(0).id, type);
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, messages.get(0).id, type, topicId);
|
||||
} else if (max_id != 0) {
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, max_id, type);
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, max_id, type, topicId);
|
||||
} else {
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, Integer.MAX_VALUE, type);
|
||||
getMessagesStorage().closeHolesInMedia(uid, minId, Integer.MAX_VALUE, type, topicId);
|
||||
}
|
||||
}
|
||||
getMessagesStorage().getDatabase().commitTransaction();
|
||||
|
@ -4932,7 +5089,7 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadReplyMessagesForMessages(ArrayList<MessageObject> messages, long dialogId, boolean scheduled, Runnable callback) {
|
||||
public void loadReplyMessagesForMessages(ArrayList<MessageObject> messages, long dialogId, boolean scheduled, int threadMessageId, Runnable callback) {
|
||||
if (DialogObject.isEncryptedDialog(dialogId)) {
|
||||
ArrayList<Long> replyMessages = new ArrayList<>();
|
||||
LongSparseArray<ArrayList<MessageObject>> replyMessageRandomOwners = new LongSparseArray<>();
|
||||
|
@ -5020,6 +5177,9 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
if (messageObject.getId() > 0 && messageObject.isReply()) {
|
||||
int messageId = messageObject.messageOwner.reply_to.reply_to_msg_id;
|
||||
if (messageId == threadMessageId) {
|
||||
continue;
|
||||
}
|
||||
long channelId = 0;
|
||||
if (messageObject.messageOwner.reply_to.reply_to_peer_id != null) {
|
||||
if (messageObject.messageOwner.reply_to.reply_to_peer_id.channel_id != 0) {
|
||||
|
@ -5209,10 +5369,12 @@ public class MediaDataController extends BaseController {
|
|||
try {
|
||||
getMessagesStorage().getDatabase().beginTransaction();
|
||||
SQLitePreparedStatement state;
|
||||
SQLitePreparedStatement topicState = null;
|
||||
if (scheduled) {
|
||||
state = getMessagesStorage().getDatabase().executeFast("UPDATE scheduled_messages_v2 SET replydata = ?, reply_to_message_id = ? WHERE mid = ? AND uid = ?");
|
||||
} else {
|
||||
state = getMessagesStorage().getDatabase().executeFast("UPDATE messages_v2 SET replydata = ?, reply_to_message_id = ? WHERE mid = ? AND uid = ?");
|
||||
topicState = getMessagesStorage().getDatabase().executeFast("UPDATE messages_topics SET replydata = ?, reply_to_message_id = ? WHERE mid = ? AND uid = ?");
|
||||
}
|
||||
for (int a = 0; a < result.size(); a++) {
|
||||
TLRPC.Message message = result.get(a);
|
||||
|
@ -5227,17 +5389,26 @@ public class MediaDataController extends BaseController {
|
|||
message.serializeToStream(data);
|
||||
for (int b = 0; b < messageObjects.size(); b++) {
|
||||
MessageObject messageObject = messageObjects.get(b);
|
||||
state.requery();
|
||||
state.bindByteBuffer(1, data);
|
||||
state.bindInteger(2, message.id);
|
||||
state.bindInteger(3, messageObject.getId());
|
||||
state.bindLong(4, messageObject.getDialogId());
|
||||
state.step();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
SQLitePreparedStatement localState = i == 0 ? state : topicState;
|
||||
if (localState == null) {
|
||||
continue;
|
||||
}
|
||||
localState.requery();
|
||||
localState.bindByteBuffer(1, data);
|
||||
localState.bindInteger(2, message.id);
|
||||
localState.bindInteger(3, messageObject.getId());
|
||||
localState.bindLong(4, messageObject.getDialogId());
|
||||
localState.step();
|
||||
}
|
||||
}
|
||||
data.reuse();
|
||||
}
|
||||
}
|
||||
state.dispose();
|
||||
if (topicState != null) {
|
||||
topicState.dispose();
|
||||
}
|
||||
getMessagesStorage().getDatabase().commitTransaction();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
|
@ -5931,13 +6102,17 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
|
||||
saveDraft(dialogId, threadId, draftMessage, replyToMessage, false);
|
||||
if (threadId == 0) {
|
||||
|
||||
if (threadId == 0 || ChatObject.isForum(currentAccount, dialogId)) {
|
||||
if (!DialogObject.isEncryptedDialog(dialogId)) {
|
||||
TLRPC.TL_messages_saveDraft req = new TLRPC.TL_messages_saveDraft();
|
||||
req.peer = getMessagesController().getInputPeer(dialogId);
|
||||
if (req.peer == null) {
|
||||
return;
|
||||
}
|
||||
if (threadId != 0) {
|
||||
req.top_msg_id = threadId;
|
||||
}
|
||||
req.message = draftMessage.message;
|
||||
req.no_webpage = draftMessage.no_webpage;
|
||||
req.reply_to_msg_id = draftMessage.reply_to_msg_id;
|
||||
|
@ -6025,7 +6200,7 @@ public class MediaDataController extends BaseController {
|
|||
serializedData.cleanup();
|
||||
}
|
||||
editor.commit();
|
||||
if (fromServer && threadId == 0) {
|
||||
if (fromServer && (threadId == 0 || getMessagesController().isForum(dialogId))) {
|
||||
if (draft != null && draft.reply_to_msg_id != 0 && replyToMessage == null) {
|
||||
TLRPC.User user = null;
|
||||
TLRPC.Chat chat = null;
|
||||
|
@ -7056,7 +7231,9 @@ public class MediaDataController extends BaseController {
|
|||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < previewItems.size(); i++) {
|
||||
previewItems.get(i).chatTheme.loadPreviewColors(0);
|
||||
if (previewItems.get(i).chatTheme != null) {
|
||||
previewItems.get(i).chatTheme.loadPreviewColors(0);
|
||||
}
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
defaultEmojiThemes.clear();
|
||||
|
|
|
@ -12,6 +12,7 @@ public class MessageCustomParamsHelper {
|
|||
!message.voiceTranscriptionOpen &&
|
||||
!message.voiceTranscriptionFinal &&
|
||||
!message.voiceTranscriptionRated &&
|
||||
!message.voiceTranscriptionForce &&
|
||||
message.voiceTranscriptionId == 0 &&
|
||||
!message.premiumEffectWasPlayed;
|
||||
}
|
||||
|
@ -20,6 +21,7 @@ public class MessageCustomParamsHelper {
|
|||
toMessage.voiceTranscription = fromMessage.voiceTranscription;
|
||||
toMessage.voiceTranscriptionOpen = fromMessage.voiceTranscriptionOpen;
|
||||
toMessage.voiceTranscriptionFinal = fromMessage.voiceTranscriptionFinal;
|
||||
toMessage.voiceTranscriptionForce = fromMessage.voiceTranscriptionForce;
|
||||
toMessage.voiceTranscriptionRated = fromMessage.voiceTranscriptionRated;
|
||||
toMessage.voiceTranscriptionId = fromMessage.voiceTranscriptionId;
|
||||
toMessage.premiumEffectWasPlayed = fromMessage.premiumEffectWasPlayed;
|
||||
|
@ -66,11 +68,13 @@ public class MessageCustomParamsHelper {
|
|||
private Params_v1(TLRPC.Message message) {
|
||||
this.message = message;
|
||||
flags += message.voiceTranscription != null ? 1 : 0;
|
||||
flags += message.voiceTranscriptionForce ? 2 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeToStream(AbstractSerializedData stream) {
|
||||
stream.writeInt32(VERSION);
|
||||
flags = message.voiceTranscriptionForce ? (flags | 2) : (flags &~ 2);
|
||||
stream.writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
stream.writeString(message.voiceTranscription);
|
||||
|
@ -89,6 +93,7 @@ public class MessageCustomParamsHelper {
|
|||
if ((flags & 1) != 0) {
|
||||
message.voiceTranscription = stream.readString(exception);
|
||||
}
|
||||
message.voiceTranscriptionForce = (flags & 2) != 0;
|
||||
message.voiceTranscriptionOpen = stream.readBool(exception);
|
||||
message.voiceTranscriptionFinal = stream.readBool(exception);
|
||||
message.voiceTranscriptionRated = stream.readBool(exception);
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
package org.telegram.messenger;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
@ -30,6 +28,7 @@ import android.text.style.URLSpan;
|
|||
import android.text.util.Linkify;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
|
@ -43,6 +42,9 @@ import org.telegram.ui.ActionBar.Theme;
|
|||
import org.telegram.ui.Cells.ChatMessageCell;
|
||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||
import org.telegram.ui.Components.EmojiView;
|
||||
import org.telegram.ui.Components.Forum.ForumBubbleDrawable;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
|
||||
import org.telegram.ui.Components.Reactions.ReactionsUtils;
|
||||
import org.telegram.ui.Components.TextStyleSpan;
|
||||
|
@ -60,6 +62,8 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect;
|
|||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.StringReader;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
|
@ -80,13 +84,20 @@ public class MessageObject {
|
|||
public static final int MESSAGE_SEND_STATE_SEND_ERROR = 2;
|
||||
public static final int MESSAGE_SEND_STATE_EDITING = 3;
|
||||
|
||||
public static final int TYPE_TEXT = 0;
|
||||
public static final int TYPE_PHOTO = 1;
|
||||
public static final int TYPE_VOICE = 2;
|
||||
public static final int TYPE_VIDEO = 3;
|
||||
public static final int TYPE_GEO = 4; // TL_messageMediaGeo, TL_messageMediaVenue, TL_messageMediaGeoLive
|
||||
public static final int TYPE_ROUND_VIDEO = 5;
|
||||
public static final int TYPE_GIF = 8;
|
||||
public static final int TYPE_FILE = 9;
|
||||
public static final int TYPE_ACTION_PHOTO = 11;
|
||||
public static final int TYPE_CONTACT = 12;
|
||||
public static final int TYPE_STICKER = 13;
|
||||
public static final int TYPE_MUSIC = 14;
|
||||
public static final int TYPE_ANIMATED_STICKER = 15;
|
||||
public static final int TYPE_PHONE_CALL = 16;
|
||||
public static final int TYPE_POLL = 17;
|
||||
public static final int TYPE_GIFT_PREMIUM = 18;
|
||||
public static final int TYPE_EMOJIS = 19;
|
||||
|
@ -104,9 +115,12 @@ public class MessageObject {
|
|||
public TLRPC.Message messageOwner;
|
||||
public TLRPC.Document emojiAnimatedSticker;
|
||||
public Long emojiAnimatedStickerId;
|
||||
public boolean isTopicMainMessage;
|
||||
private boolean emojiAnimatedStickerLoading;
|
||||
public String emojiAnimatedStickerColor;
|
||||
public CharSequence messageText;
|
||||
public CharSequence messageTextShort;
|
||||
public CharSequence messageTextForReply;
|
||||
public CharSequence linkDescription;
|
||||
public CharSequence caption;
|
||||
public CharSequence youtubeDescription;
|
||||
|
@ -158,6 +172,8 @@ public class MessageObject {
|
|||
public int sponsoredChannelPost;
|
||||
public TLRPC.ChatInvite sponsoredChatInvite;
|
||||
public String sponsoredChatInviteHash;
|
||||
public boolean sponsoredShowPeerPhoto;
|
||||
public boolean sponsoredRecommended;
|
||||
|
||||
public String botStartParam;
|
||||
|
||||
|
@ -231,6 +247,7 @@ public class MessageObject {
|
|||
// forwarding preview params
|
||||
public boolean hideSendersName;
|
||||
public TLRPC.Peer sendAsPeer;
|
||||
public ForumBubbleDrawable[] topicIconDrawable = new ForumBubbleDrawable[1];
|
||||
|
||||
static final String[] excludeWords = new String[]{
|
||||
" vs. ",
|
||||
|
@ -250,6 +267,8 @@ public class MessageObject {
|
|||
};
|
||||
public Drawable customAvatarDrawable;
|
||||
|
||||
private byte[] randomWaveform;
|
||||
|
||||
public static boolean hasUnreadReactions(TLRPC.Message message) {
|
||||
if (message == null) {
|
||||
return false;
|
||||
|
@ -281,6 +300,36 @@ public class MessageObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static int getTopicId(TLRPC.Message message) {
|
||||
if (message != null && message.action instanceof TLRPC.TL_messageActionTopicCreate) {
|
||||
return message.id;
|
||||
}
|
||||
if (message == null || message.reply_to == null || !message.reply_to.forum_topic) {
|
||||
return 0;
|
||||
}
|
||||
if (message instanceof TLRPC.TL_messageService && !(message.action instanceof TLRPC.TL_messageActionPinMessage)) {
|
||||
int topicId = message.reply_to.reply_to_msg_id;
|
||||
if (topicId == 0) {
|
||||
topicId = message.reply_to.reply_to_top_id;
|
||||
}
|
||||
return topicId;
|
||||
} else {
|
||||
int topicId = message.reply_to.reply_to_top_id;
|
||||
if (topicId == 0) {
|
||||
topicId = message.reply_to.reply_to_msg_id;
|
||||
}
|
||||
return topicId;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTopicActionMessage(MessageObject message) {
|
||||
if (message == null || message.messageOwner == null) {
|
||||
return false;
|
||||
}
|
||||
return message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate ||
|
||||
message.messageOwner.action instanceof TLRPC.TL_messageActionTopicEdit;
|
||||
}
|
||||
|
||||
public int getEmojiOnlyCount() {
|
||||
return emojiOnlyCount;
|
||||
}
|
||||
|
@ -315,7 +364,7 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
if (changed) {
|
||||
MessagesStorage.getInstance(currentAccount).markMessageReactionsAsRead(messageOwner.dialog_id, messageOwner.id, true);
|
||||
MessagesStorage.getInstance(currentAccount).markMessageReactionsAsRead(messageOwner.dialog_id, getTopicId(messageOwner), messageOwner.id, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1190,13 +1239,12 @@ public class MessageObject {
|
|||
}
|
||||
if (emojiAnimatedSticker == null && emojiAnimatedStickerId == null) {
|
||||
generateLayout(null);
|
||||
} else if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
} else if (isAnimatedSticker()) {
|
||||
type = TYPE_ANIMATED_STICKER;
|
||||
} else {
|
||||
type = 1000;
|
||||
if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
} else if (isAnimatedSticker()) {
|
||||
type = TYPE_ANIMATED_STICKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2153,6 +2201,112 @@ public class MessageObject {
|
|||
spannableStringBuilder.replace(i, i + "**new**".length(), newReactions);
|
||||
}
|
||||
messageText = spannableStringBuilder;
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeUsernames) {
|
||||
TLRPC.TL_channelAdminLogEventActionChangeUsernames log = (TLRPC.TL_channelAdminLogEventActionChangeUsernames) event.action;
|
||||
|
||||
ArrayList<String> oldUsernames = log.prev_value;
|
||||
ArrayList<String> newUsernames = log.new_value;
|
||||
|
||||
messageText = null;
|
||||
|
||||
if (oldUsernames != null && newUsernames != null) {
|
||||
if (newUsernames.size() + 1 == oldUsernames.size()) {
|
||||
String removed = null;
|
||||
for (int i = 0; i < oldUsernames.size(); ++i) {
|
||||
String username = oldUsernames.get(i);
|
||||
if (!newUsernames.contains(username)) {
|
||||
if (removed == null) {
|
||||
removed = username;
|
||||
} else {
|
||||
removed = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed != null) {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogDeactivatedUsername", R.string.EventLogDeactivatedUsername, "@" + removed),
|
||||
"un1", fromUser
|
||||
);
|
||||
}
|
||||
} else if (oldUsernames.size() + 1 == newUsernames.size()) {
|
||||
String added = null;
|
||||
for (int i = 0; i < newUsernames.size(); ++i) {
|
||||
String username = newUsernames.get(i);
|
||||
if (!oldUsernames.contains(username)) {
|
||||
if (added == null) {
|
||||
added = username;
|
||||
} else {
|
||||
added = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (added != null) {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogActivatedUsername", R.string.EventLogActivatedUsername, "@" + added),
|
||||
"un1", fromUser
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messageText == null) {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogChangeUsernames", R.string.EventLogChangeUsernames, getUsernamesString(oldUsernames), getUsernamesString(newUsernames)),
|
||||
"un1", fromUser
|
||||
);
|
||||
}
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionToggleForum) {
|
||||
TLRPC.TL_channelAdminLogEventActionToggleForum toggleForum = (TLRPC.TL_channelAdminLogEventActionToggleForum) event.action;
|
||||
if (toggleForum.new_value) {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogSwitchToForum", R.string.EventLogSwitchToForum),
|
||||
"un1", fromUser
|
||||
);
|
||||
} else {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogSwitchToGroup", R.string.EventLogSwitchToGroup),
|
||||
"un1", fromUser
|
||||
);
|
||||
}
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionCreateTopic) {
|
||||
TLRPC.TL_channelAdminLogEventActionCreateTopic createTopic = (TLRPC.TL_channelAdminLogEventActionCreateTopic) event.action;
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogCreateTopic", R.string.EventLogCreateTopic),
|
||||
"un1", fromUser
|
||||
);
|
||||
messageText = replaceWithLink(messageText, "un2", createTopic.topic);
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionEditTopic) {
|
||||
TLRPC.TL_channelAdminLogEventActionEditTopic editTopic = (TLRPC.TL_channelAdminLogEventActionEditTopic) event.action;
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogEditTopic", R.string.EventLogEditTopic),
|
||||
"un1", fromUser
|
||||
);
|
||||
messageText = replaceWithLink(messageText, "un2", editTopic.prev_topic);
|
||||
messageText = replaceWithLink(messageText, "un3", editTopic.new_topic);
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteTopic) {
|
||||
TLRPC.TL_channelAdminLogEventActionDeleteTopic deleteTopic = (TLRPC.TL_channelAdminLogEventActionDeleteTopic) event.action;
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.getString("EventLogDeleteTopic", R.string.EventLogDeleteTopic),
|
||||
"un1", fromUser
|
||||
);
|
||||
messageText = replaceWithLink(messageText, "un2", deleteTopic.topic);
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionPinTopic) {
|
||||
TLRPC.TL_channelAdminLogEventActionPinTopic pinTopic = (TLRPC.TL_channelAdminLogEventActionPinTopic) event.action;
|
||||
if (pinTopic.new_topic instanceof TLRPC.TL_forumTopic && ((TLRPC.TL_forumTopic)pinTopic.new_topic).pinned) {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogPinTopic", R.string.EventLogPinTopic),
|
||||
"un1", fromUser
|
||||
);
|
||||
messageText = replaceWithLink(messageText, "un2", pinTopic.new_topic);
|
||||
} else {
|
||||
messageText = replaceWithLink(
|
||||
LocaleController.formatString("EventLogUnpinTopic", R.string.EventLogUnpinTopic),
|
||||
"un1", fromUser
|
||||
);
|
||||
messageText = replaceWithLink(messageText, "un2", pinTopic.new_topic);
|
||||
}
|
||||
} else {
|
||||
messageText = "unsupported " + event.action;
|
||||
}
|
||||
|
@ -2266,6 +2420,21 @@ public class MessageObject {
|
|||
return LocaleController.getString("NoReactions", R.string.NoReactions);
|
||||
}
|
||||
|
||||
private String getUsernamesString(ArrayList<String> usernames) {
|
||||
if (usernames == null || usernames.size() == 0) {
|
||||
return LocaleController.getString("UsernameEmpty", R.string.UsernameEmpty).toLowerCase();
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < usernames.size(); ++i) {
|
||||
sb.append("@");
|
||||
sb.append(usernames.get(i));
|
||||
if (i < usernames.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getUserName(TLObject object, ArrayList<TLRPC.MessageEntity> entities, int offset) {
|
||||
String name;
|
||||
String username;
|
||||
|
@ -2286,7 +2455,7 @@ public class MessageObject {
|
|||
} else {
|
||||
TLRPC.Chat chat = (TLRPC.Chat) object;
|
||||
name = chat.title;
|
||||
username = chat.username;
|
||||
username = ChatObject.getPublicUsername(chat);
|
||||
id = -chat.id;
|
||||
}
|
||||
if (offset >= 0) {
|
||||
|
@ -2355,8 +2524,8 @@ public class MessageObject {
|
|||
fromUser = MessagesController.getInstance(currentAccount).getUser(messageOwner.from_id.user_id);
|
||||
}
|
||||
TLRPC.TL_game game = null;
|
||||
if (replyMessageObject != null && replyMessageObject.getMedia(messageOwner) != null && replyMessageObject.getMedia(messageOwner).game != null) {
|
||||
game = replyMessageObject.getMedia(messageOwner).game;
|
||||
if (replyMessageObject != null && getMedia(replyMessageObject) != null && getMedia(replyMessageObject).game != null) {
|
||||
game = getMedia(replyMessageObject).game;
|
||||
}
|
||||
if (game == null) {
|
||||
if (fromUser != null && fromUser.id == UserConfig.getInstance(currentAccount).getClientUserId()) {
|
||||
|
@ -2395,11 +2564,11 @@ public class MessageObject {
|
|||
currency = "<error>";
|
||||
FileLog.e(e);
|
||||
}
|
||||
if (replyMessageObject != null && replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice) {
|
||||
if (replyMessageObject != null && getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaInvoice) {
|
||||
if (messageOwner.action.recurring_init) {
|
||||
messageText = LocaleController.formatString(R.string.PaymentSuccessfullyPaidRecurrent, currency, name, replyMessageObject.getMedia(messageOwner).title);
|
||||
messageText = LocaleController.formatString(R.string.PaymentSuccessfullyPaidRecurrent, currency, name, getMedia(replyMessageObject).title);
|
||||
} else {
|
||||
messageText = LocaleController.formatString("PaymentSuccessfullyPaid", R.string.PaymentSuccessfullyPaid, currency, name, replyMessageObject.getMedia(messageOwner).title);
|
||||
messageText = LocaleController.formatString("PaymentSuccessfullyPaid", R.string.PaymentSuccessfullyPaid, currency, name, getMedia(replyMessageObject).title);
|
||||
}
|
||||
} else {
|
||||
if (messageOwner.action.recurring_init) {
|
||||
|
@ -2438,24 +2607,24 @@ public class MessageObject {
|
|||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedRound", R.string.ActionPinnedRound), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if ((replyMessageObject.isSticker() || replyMessageObject.isAnimatedSticker()) && !replyMessageObject.isAnimatedEmoji()) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedSticker", R.string.ActionPinnedSticker), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaDocument) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedFile", R.string.ActionPinnedFile), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGeo) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaGeo) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedGeo", R.string.ActionPinnedGeo), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGeoLive) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaGeoLive) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedGeoLive", R.string.ActionPinnedGeoLive), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaContact) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaContact) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedContact", R.string.ActionPinnedContact), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaPoll) {
|
||||
if (((TLRPC.TL_messageMediaPoll) replyMessageObject.getMedia(messageOwner)).poll.quiz) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaPoll) {
|
||||
if (((TLRPC.TL_messageMediaPoll) getMedia(replyMessageObject)).poll.quiz) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedQuiz", R.string.ActionPinnedQuiz), "un1", fromUser != null ? fromUser : chat);
|
||||
} else {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedPoll", R.string.ActionPinnedPoll), "un1", fromUser != null ? fromUser : chat);
|
||||
}
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionPinnedPhoto", R.string.ActionPinnedPhoto), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (replyMessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) {
|
||||
messageText = replaceWithLink(LocaleController.formatString("ActionPinnedGame", R.string.ActionPinnedGame, "\uD83C\uDFAE " + replyMessageObject.getMedia(messageOwner).game.title), "un1", fromUser != null ? fromUser : chat);
|
||||
} else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaGame) {
|
||||
messageText = replaceWithLink(LocaleController.formatString("ActionPinnedGame", R.string.ActionPinnedGame, "\uD83C\uDFAE " + getMedia(replyMessageObject).game.title), "un1", fromUser != null ? fromUser : chat);
|
||||
messageText = Emoji.replaceEmoji(messageText, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
|
||||
} else if (replyMessageObject.messageText != null && replyMessageObject.messageText.length() > 0) {
|
||||
CharSequence mess = AnimatedEmojiSpan.cloneSpans(replyMessageObject.messageText);
|
||||
|
@ -3256,6 +3425,68 @@ public class MessageObject {
|
|||
generatePinMessageText(fromUser, chat);
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear) {
|
||||
messageText = LocaleController.getString("HistoryCleared", R.string.HistoryCleared);
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate) {
|
||||
messageText = LocaleController.getString("TopicCreated", R.string.TopicCreated);
|
||||
|
||||
TLRPC.TL_messageActionTopicCreate createAction = (TLRPC.TL_messageActionTopicCreate) messageOwner.action;
|
||||
TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic();
|
||||
forumTopic.icon_emoji_id = createAction.icon_emoji_id;
|
||||
forumTopic.title = createAction.title;
|
||||
forumTopic.icon_color = createAction.icon_color;
|
||||
|
||||
messageTextShort = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicWasCreatedAction", R.string.TopicWasCreatedAction), ForumUtilities.getTopicSpannedName(forumTopic, null));
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionTopicEdit) {
|
||||
TLRPC.TL_messageActionTopicEdit editAction = (TLRPC.TL_messageActionTopicEdit) messageOwner.action;
|
||||
|
||||
String name = null;
|
||||
if (fromUser != null) {
|
||||
name = ContactsController.formatName(fromUser.first_name, fromUser.last_name);
|
||||
} else if (fromChat != null) {
|
||||
name = fromChat.title;
|
||||
}
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
} else {
|
||||
name = "DELETED";
|
||||
}
|
||||
|
||||
if ((messageOwner.action.flags & 4) > 0) {
|
||||
if (((TLRPC.TL_messageActionTopicEdit) messageOwner.action).closed) {
|
||||
messageText = LocaleController.formatString("TopicClosed2", R.string.TopicClosed2, name);
|
||||
messageTextShort = LocaleController.getString("TopicClosed", R.string.TopicClosed);
|
||||
} else {
|
||||
messageText = LocaleController.formatString("TopicRestarted2", R.string.TopicRestarted2, name);
|
||||
messageTextShort = LocaleController.getString("TopicRestarted", R.string.TopicRestarted);
|
||||
}
|
||||
} else {
|
||||
if ((messageOwner.action.flags & 2) != 0 && (messageOwner.action.flags & 1) != 0) {
|
||||
TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic();
|
||||
forumTopic.icon_emoji_id = editAction.icon_emoji_id;
|
||||
forumTopic.title = editAction.title;
|
||||
forumTopic.icon_color = ForumBubbleDrawable.serverSupportedColor[0];
|
||||
|
||||
CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable);
|
||||
CharSequence str = AndroidUtilities.replaceCharSequence("%1$s", LocaleController.getString("TopicChangeIconAndTitleTo", R.string.TopicChangeIconAndTitleTo), name);
|
||||
messageText = AndroidUtilities.replaceCharSequence("%2$s", str, topicName);
|
||||
messageTextShort = LocaleController.getString("TopicRenamed", R.string.TopicRenamed);
|
||||
messageTextForReply = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicChangeIconAndTitleToInReply", R.string.TopicChangeIconAndTitleToInReply), topicName);
|
||||
} else if ((messageOwner.action.flags & 2) != 0) {
|
||||
TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic();
|
||||
forumTopic.icon_emoji_id = editAction.icon_emoji_id;
|
||||
forumTopic.title = "";
|
||||
forumTopic.icon_color = ForumBubbleDrawable.serverSupportedColor[0];
|
||||
CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable);
|
||||
CharSequence str = AndroidUtilities.replaceCharSequence("%1$s", LocaleController.getString("TopicIconChangedTo", R.string.TopicIconChangedTo), name);
|
||||
messageText = AndroidUtilities.replaceCharSequence("%2$s", str, topicName);
|
||||
messageTextShort = LocaleController.getString("TopicIconChanged", R.string.TopicIconChanged);
|
||||
messageTextForReply = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicIconChangedToInReply", R.string.TopicIconChangedToInReply), topicName);
|
||||
} else if ((messageOwner.action.flags & 1) != 0) {
|
||||
CharSequence str = AndroidUtilities.replaceCharSequence("%1$s", LocaleController.getString("TopicRenamedTo", R.string.TopicRenamedTo), name);
|
||||
messageText = AndroidUtilities.replaceCharSequence("%2$s", str, editAction.title);
|
||||
messageTextShort = LocaleController.getString("TopicRenamed", R.string.TopicRenamed);
|
||||
messageTextForReply = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicRenamedToInReply", R.string.TopicRenamedToInReply), editAction.title);
|
||||
}
|
||||
}
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
|
||||
generateGameMessageText(fromUser);
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) {
|
||||
|
@ -3412,6 +3643,8 @@ public class MessageObject {
|
|||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
if (getMedia(messageOwner).ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) {
|
||||
messageText = LocaleController.getString("AttachDestructingPhoto", R.string.AttachDestructingPhoto);
|
||||
} else if (getGroupId() != 0) {
|
||||
messageText = LocaleController.getString("Album", R.string.Album);
|
||||
} else {
|
||||
messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto);
|
||||
}
|
||||
|
@ -3483,6 +3716,13 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
|
||||
public static TLRPC.MessageMedia getMedia(MessageObject messageObject) {
|
||||
if (messageObject == null || messageObject.messageOwner == null) {
|
||||
return null;
|
||||
}
|
||||
return getMedia(messageObject.messageOwner);
|
||||
}
|
||||
|
||||
public static TLRPC.MessageMedia getMedia(TLRPC.Message messageOwner) {
|
||||
if (messageOwner.media != null && messageOwner.media.extended_media instanceof TLRPC.TL_messageExtendedMedia) {
|
||||
return ((TLRPC.TL_messageExtendedMedia) messageOwner.media.extended_media).media;
|
||||
|
@ -3508,7 +3748,7 @@ public class MessageObject {
|
|||
isRoundVideoCached = 0;
|
||||
if (messageOwner instanceof TLRPC.TL_message || messageOwner instanceof TLRPC.TL_messageForwarded_old2) {
|
||||
if (isRestrictedMessage) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
} else if (emojiAnimatedSticker != null || emojiAnimatedStickerId != null) {
|
||||
if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
|
@ -3518,9 +3758,9 @@ public class MessageObject {
|
|||
} else if (!isDice() && emojiOnlyCount >= 1 && !hasUnwrappedEmoji) {
|
||||
type = TYPE_EMOJIS;
|
||||
} else if (isMediaEmpty()) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
if (TextUtils.isEmpty(messageText) && eventId == 0) {
|
||||
messageText = "Empty message";
|
||||
messageText = LocaleController.getString("EventLogOriginalCaptionEmpty", R.string.EventLogOriginalCaptionEmpty);
|
||||
}
|
||||
} else if (hasExtendedMediaPreview()) {
|
||||
type = TYPE_EXTENDED_MEDIA_PREVIEW;
|
||||
|
@ -3551,43 +3791,43 @@ public class MessageObject {
|
|||
} else if (isVoice()) {
|
||||
type = TYPE_VOICE;
|
||||
} else if (isMusic()) {
|
||||
type = 14;
|
||||
type = TYPE_MUSIC;
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaContact) {
|
||||
type = 12;
|
||||
type = TYPE_CONTACT;
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaPoll) {
|
||||
type = TYPE_POLL;
|
||||
checkedVotes = new ArrayList<>();
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) {
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document != null && document.mime_type != null) {
|
||||
if (isGifDocument(document, hasValidGroupId())) {
|
||||
type = 8;
|
||||
type = TYPE_GIF;
|
||||
} else if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
} else if (isAnimatedSticker()) {
|
||||
type = TYPE_ANIMATED_STICKER;
|
||||
} else {
|
||||
type = 9;
|
||||
type = TYPE_FILE;
|
||||
}
|
||||
} else {
|
||||
type = 9;
|
||||
type = TYPE_FILE;
|
||||
}
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
}
|
||||
} else if (messageOwner instanceof TLRPC.TL_messageService) {
|
||||
if (messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
|
||||
type = 0;
|
||||
type = TYPE_TEXT;
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) {
|
||||
contentType = 1;
|
||||
type = TYPE_GIFT_PREMIUM;
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
|
||||
contentType = 1;
|
||||
type = 11;
|
||||
type = TYPE_ACTION_PHOTO;
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageEncryptedAction) {
|
||||
if (messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
|
||||
contentType = 1;
|
||||
|
@ -3600,7 +3840,7 @@ public class MessageObject {
|
|||
contentType = -1;
|
||||
type = -1;
|
||||
} else if (messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) {
|
||||
type = 16;
|
||||
type = TYPE_PHONE_CALL;
|
||||
} else {
|
||||
contentType = 1;
|
||||
type = 10;
|
||||
|
@ -3613,7 +3853,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean checkLayout() {
|
||||
if (type != 0 && type != TYPE_EMOJIS || messageOwner.peer_id == null || messageText == null || messageText.length() == 0) {
|
||||
if (type != TYPE_TEXT && type != TYPE_EMOJIS || messageOwner.peer_id == null || messageText == null || messageText.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (layoutCreated) {
|
||||
|
@ -3990,30 +4230,33 @@ public class MessageObject {
|
|||
public static CharSequence replaceWithLink(CharSequence source, String param, TLObject object) {
|
||||
int start = TextUtils.indexOf(source, param);
|
||||
if (start >= 0) {
|
||||
String name;
|
||||
CharSequence name;
|
||||
String id;
|
||||
TLObject spanObject = null;
|
||||
if (object instanceof TLRPC.User) {
|
||||
name = UserObject.getUserName((TLRPC.User) object);
|
||||
name = UserObject.getUserName((TLRPC.User) object).replace('\n', ' ');
|
||||
id = "" + ((TLRPC.User) object).id;
|
||||
} else if (object instanceof TLRPC.Chat) {
|
||||
name = ((TLRPC.Chat) object).title;
|
||||
name = ((TLRPC.Chat) object).title.replace('\n', ' ');
|
||||
id = "" + -((TLRPC.Chat) object).id;
|
||||
} else if (object instanceof TLRPC.TL_game) {
|
||||
TLRPC.TL_game game = (TLRPC.TL_game) object;
|
||||
name = game.title;
|
||||
name = game.title.replace('\n', ' ');
|
||||
id = "game";
|
||||
} else if (object instanceof TLRPC.TL_chatInviteExported) {
|
||||
TLRPC.TL_chatInviteExported invite = (TLRPC.TL_chatInviteExported) object;
|
||||
name = invite.link;
|
||||
name = invite.link.replace('\n', ' ');
|
||||
id = "invite";
|
||||
spanObject = invite;
|
||||
} else if (object instanceof TLRPC.ForumTopic) {
|
||||
name = ForumUtilities.getTopicSpannedName((TLRPC.ForumTopic) object, null);
|
||||
id = "topic";
|
||||
spanObject = object;
|
||||
} else {
|
||||
name = "";
|
||||
id = "0";
|
||||
}
|
||||
name = name.replace('\n', ' ');
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new String[]{name}));
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new CharSequence[]{name}));
|
||||
URLSpanNoUnderlineBold span = new URLSpanNoUnderlineBold("" + id);
|
||||
span.setObject(spanObject);
|
||||
builder.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
@ -4218,7 +4461,14 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean isVoiceTranscriptionOpen() {
|
||||
return isVoice() && messageOwner != null && messageOwner.voiceTranscriptionOpen && messageOwner.voiceTranscription != null && (messageOwner.voiceTranscriptionFinal || TranscribeButton.isTranscribing(this)) && UserConfig.getInstance(currentAccount).isPremium();
|
||||
return (
|
||||
UserConfig.getInstance(currentAccount).isPremium() &&
|
||||
messageOwner != null &&
|
||||
(isVoice() || isRoundVideo() && TranscribeButton.isVideoTranscriptionOpen(this)) &&
|
||||
messageOwner.voiceTranscriptionOpen &&
|
||||
messageOwner.voiceTranscription != null &&
|
||||
(messageOwner.voiceTranscriptionFinal || TranscribeButton.isTranscribing(this))
|
||||
);
|
||||
}
|
||||
|
||||
public void generateCaption() {
|
||||
|
@ -4821,15 +5071,18 @@ public class MessageObject {
|
|||
return true;
|
||||
}
|
||||
if (!isOut()) {
|
||||
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice && !hasExtendedMedia()) {
|
||||
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice && !hasExtendedMedia() || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
return true;
|
||||
}
|
||||
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null;
|
||||
if (ChatObject.isChannel(chat) && chat.megagroup) {
|
||||
return chat.username != null && chat.username.length() > 0 && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaContact) && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGeo);
|
||||
return ChatObject.isPublic(chat) && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaContact) && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGeo);
|
||||
}
|
||||
}
|
||||
} else if (messageOwner.from_id instanceof TLRPC.TL_peerChannel || messageOwner.post) {
|
||||
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && !isOutOwner()) {
|
||||
return true;
|
||||
}
|
||||
if (isSupergroup()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4883,7 +5136,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public void generateLayout(TLRPC.User fromUser) {
|
||||
if (type != 0 && type != TYPE_EMOJIS || messageOwner.peer_id == null || TextUtils.isEmpty(messageText)) {
|
||||
if (type != TYPE_TEXT && type != TYPE_EMOJIS || messageOwner.peer_id == null || TextUtils.isEmpty(messageText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5205,7 +5458,7 @@ public class MessageObject {
|
|||
if (customAvatarDrawable != null) {
|
||||
return true;
|
||||
}
|
||||
if (isSponsored() && isFromChat()) {
|
||||
if (isSponsored() && (isFromChat() || sponsoredShowPeerPhoto)) {
|
||||
return true;
|
||||
}
|
||||
return !isSponsored() && (isFromUser() || isFromGroup() || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null);
|
||||
|
@ -5249,6 +5502,25 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean peersEqual(TLRPC.Peer a, TLRPC.Peer b) {
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a instanceof TLRPC.TL_peerChat && b instanceof TLRPC.TL_peerChat) {
|
||||
return a.chat_id == b.chat_id;
|
||||
}
|
||||
if (a instanceof TLRPC.TL_peerChannel && b instanceof TLRPC.TL_peerChannel) {
|
||||
return a.channel_id == b.channel_id;
|
||||
}
|
||||
if (a instanceof TLRPC.TL_peerUser && b instanceof TLRPC.TL_peerUser) {
|
||||
return a.user_id == b.user_id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getFromChatId() {
|
||||
return getFromChatId(messageOwner);
|
||||
}
|
||||
|
@ -5552,7 +5824,7 @@ public class MessageObject {
|
|||
for (int a = 0; a < document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker ||
|
||||
attribute instanceof TLRPC.TL_documentAttributeCustomEmoji) {
|
||||
attribute instanceof TLRPC.TL_documentAttributeCustomEmoji) {
|
||||
return "video/webm".equals(document.mime_type);
|
||||
}
|
||||
}
|
||||
|
@ -5937,7 +6209,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public int getApproximateHeight() {
|
||||
if (type == 0) {
|
||||
if (type == TYPE_TEXT) {
|
||||
int height = textHeight + (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage ? AndroidUtilities.dp(100) : 0);
|
||||
if (isReply()) {
|
||||
height += AndroidUtilities.dp(42);
|
||||
|
@ -5947,17 +6219,17 @@ public class MessageObject {
|
|||
return AndroidUtilities.getPhotoSize();
|
||||
} else if (type == TYPE_VOICE) {
|
||||
return AndroidUtilities.dp(72);
|
||||
} else if (type == 12) {
|
||||
} else if (type == TYPE_CONTACT) {
|
||||
return AndroidUtilities.dp(71);
|
||||
} else if (type == 9) {
|
||||
} else if (type == TYPE_FILE) {
|
||||
return AndroidUtilities.dp(100);
|
||||
} else if (type == 4) {
|
||||
} else if (type == TYPE_GEO) {
|
||||
return AndroidUtilities.dp(114);
|
||||
} else if (type == 14) {
|
||||
} else if (type == TYPE_MUSIC) {
|
||||
return AndroidUtilities.dp(82);
|
||||
} else if (type == 10) {
|
||||
return AndroidUtilities.dp(30);
|
||||
} else if (type == 11 || type == TYPE_GIFT_PREMIUM) {
|
||||
} else if (type == TYPE_ACTION_PHOTO || type == TYPE_GIFT_PREMIUM) {
|
||||
return AndroidUtilities.dp(50);
|
||||
} else if (type == TYPE_ROUND_VIDEO) {
|
||||
return AndroidUtilities.roundMessageSize;
|
||||
|
@ -6460,7 +6732,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public boolean canForwardMessage() {
|
||||
return !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16 && !isSponsored() && !messageOwner.noforwards;
|
||||
return !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != MessageObject.TYPE_PHONE_CALL && !isSponsored() && !messageOwner.noforwards;
|
||||
}
|
||||
|
||||
public boolean canEditMedia() {
|
||||
|
@ -6754,14 +7026,14 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!mediaExists && type == 8 || type == TYPE_VIDEO || type == 9 || type == TYPE_VOICE || type == 14 || type == TYPE_ROUND_VIDEO) {
|
||||
if (!mediaExists && type == TYPE_GIF || type == TYPE_VIDEO || type == TYPE_FILE || type == TYPE_VOICE || type == TYPE_MUSIC || type == TYPE_ROUND_VIDEO) {
|
||||
if (messageOwner.attachPath != null && messageOwner.attachPath.length() > 0) {
|
||||
File f = new File(messageOwner.attachPath);
|
||||
attachPathExists = f.exists();
|
||||
}
|
||||
if (!attachPathExists) {
|
||||
File file = FileLoader.getInstance(currentAccount).getPathToMessage(messageOwner, useFileDatabaseQueue);
|
||||
if (type == 3 && needDrawBluredPreview()) {
|
||||
if (type == TYPE_VIDEO && needDrawBluredPreview()) {
|
||||
mediaExists = new File(file.getAbsolutePath() + ".enc").exists();
|
||||
}
|
||||
if (!mediaExists) {
|
||||
|
@ -6777,13 +7049,13 @@ public class MessageObject {
|
|||
} else {
|
||||
mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, false, useFileDatabaseQueue).exists();
|
||||
}
|
||||
} else if (type == 0) {
|
||||
} else if (type == MessageObject.TYPE_TEXT) {
|
||||
TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, AndroidUtilities.getPhotoSize());
|
||||
if (currentPhotoObject == null) {
|
||||
return;
|
||||
}
|
||||
mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(currentPhotoObject, null, true, useFileDatabaseQueue).exists();
|
||||
} else if (type == 11) {
|
||||
} else if (type == MessageObject.TYPE_ACTION_PHOTO) {
|
||||
TLRPC.Photo photo = messageOwner.action.photo;
|
||||
if (photo == null || photo.video_sizes.isEmpty()) {
|
||||
return;
|
||||
|
@ -7004,10 +7276,12 @@ public class MessageObject {
|
|||
int maxReactionsCount = MessagesController.getInstance(currentAccount).getMaxUserReactionsCount();
|
||||
|
||||
if (!choosenReactions.isEmpty() && (choosenReactions.contains(newReaction) || fromDoubleTap)) {
|
||||
newReaction.chosen = false;
|
||||
newReaction.count--;
|
||||
if (newReaction.count <= 0) {
|
||||
messageOwner.reactions.results.remove(newReaction);
|
||||
if (newReaction != null) {
|
||||
newReaction.chosen = false;
|
||||
newReaction.count--;
|
||||
if (newReaction.count <= 0) {
|
||||
messageOwner.reactions.results.remove(newReaction);
|
||||
}
|
||||
}
|
||||
if (messageOwner.reactions.can_see_list) {
|
||||
for (int i = 0; i < messageOwner.reactions.recent_reactions.size(); i++) {
|
||||
|
@ -7093,4 +7367,29 @@ public class MessageObject {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte[] getWaveform() {
|
||||
if (getDocument() == null) {
|
||||
return null;
|
||||
}
|
||||
for (int a = 0; a < getDocument().attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = getDocument().attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
|
||||
if (attribute.waveform == null || attribute.waveform.length == 0) {
|
||||
MediaController.getInstance().generateWaveform(this);
|
||||
}
|
||||
return attribute.waveform;
|
||||
}
|
||||
}
|
||||
if (isRoundVideo()) {
|
||||
if (randomWaveform == null) {
|
||||
randomWaveform = new byte[120];
|
||||
for (int i = 0; i < randomWaveform.length; ++i) {
|
||||
randomWaveform[i] = (byte) (255 * Math.random());
|
||||
}
|
||||
}
|
||||
return randomWaveform;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,6 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
@ -262,6 +261,8 @@ public class NotificationCenter {
|
|||
public static final int userEmojiStatusUpdated = totalEvents++;
|
||||
public static final int requestPermissions = totalEvents++;
|
||||
public static final int permissionsGranted = totalEvents++;
|
||||
public static int topicsDidLoaded = totalEvents++;
|
||||
public static int chatSwithcedToForum = totalEvents++;
|
||||
|
||||
private SparseArray<ArrayList<NotificationCenterDelegate>> observers = new SparseArray<>();
|
||||
private SparseArray<ArrayList<NotificationCenterDelegate>> removeAfterBroadcast = new SparseArray<>();
|
||||
|
|
|
@ -69,6 +69,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class NotificationsController extends BaseController {
|
||||
|
||||
|
@ -91,6 +92,7 @@ public class NotificationsController extends BaseController {
|
|||
public ArrayList<MessageObject> popupReplyMessages = new ArrayList<>();
|
||||
private HashSet<Long> openedInBubbleDialogs = new HashSet<>();
|
||||
private long openedDialogId = 0;
|
||||
private int openedTopicId = 0;
|
||||
private int lastButtonId = 5000;
|
||||
private int total_unread_count = 0;
|
||||
private int personalCount = 0;
|
||||
|
@ -132,6 +134,8 @@ public class NotificationsController extends BaseController {
|
|||
public static final int SETTING_SOUND_ON = 0;
|
||||
public static final int SETTING_SOUND_OFF = 1;
|
||||
|
||||
NotificationsSettingsFacade dialogsNotificationsFacade;
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= 26 && ApplicationLoader.applicationContext != null) {
|
||||
notificationManager = NotificationManagerCompat.from(ApplicationLoader.applicationContext);
|
||||
|
@ -210,6 +214,8 @@ public class NotificationsController extends BaseController {
|
|||
FileLog.e(e);
|
||||
}
|
||||
};
|
||||
|
||||
dialogsNotificationsFacade = new NotificationsSettingsFacade(currentAccount);
|
||||
}
|
||||
|
||||
public static void checkOtherNotificationsChannel() {
|
||||
|
@ -247,37 +253,49 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void muteUntil(long did, int selectedTimeInSeconds) {
|
||||
public static String getSharedPrefKey(long dialog_id, int topicId) {
|
||||
String str = Long.toString(dialog_id);
|
||||
if (topicId != 0) {
|
||||
str += "_" + topicId;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public void muteUntil(long did, int topicId, int selectedTimeInSeconds) {
|
||||
if (did != 0) {
|
||||
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
long flags;
|
||||
boolean override = topicId != 0;
|
||||
boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did);
|
||||
|
||||
String sharedPrefKey = NotificationsController.getSharedPrefKey(did, topicId);
|
||||
if (selectedTimeInSeconds == Integer.MAX_VALUE) {
|
||||
if (!defaultEnabled) {
|
||||
editor.remove("notify2_" + did);
|
||||
if (!defaultEnabled && !override) {
|
||||
editor.remove("notify2_" + sharedPrefKey);
|
||||
flags = 0;
|
||||
} else {
|
||||
editor.putInt("notify2_" + did, 2);
|
||||
editor.putInt("notify2_" + sharedPrefKey, 2);
|
||||
flags = 1;
|
||||
}
|
||||
} else {
|
||||
editor.putInt("notify2_" + did, 3);
|
||||
editor.putInt("notifyuntil_" + did, getConnectionsManager().getCurrentTime() + selectedTimeInSeconds);
|
||||
editor.putInt("notify2_" + sharedPrefKey, 3);
|
||||
editor.putInt("notifyuntil_" + sharedPrefKey, getConnectionsManager().getCurrentTime() + selectedTimeInSeconds);
|
||||
flags = ((long) selectedTimeInSeconds << 32) | 1;
|
||||
}
|
||||
NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(did);
|
||||
MessagesStorage.getInstance(currentAccount).setDialogFlags(did, flags);
|
||||
editor.commit();
|
||||
TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
if (selectedTimeInSeconds != Integer.MAX_VALUE || defaultEnabled) {
|
||||
dialog.notify_settings.mute_until = selectedTimeInSeconds;
|
||||
editor.apply();
|
||||
if (topicId == 0) {
|
||||
NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(did);
|
||||
MessagesStorage.getInstance(currentAccount).setDialogFlags(did, flags);
|
||||
TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
if (selectedTimeInSeconds != Integer.MAX_VALUE || defaultEnabled) {
|
||||
dialog.notify_settings.mute_until = selectedTimeInSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(did);
|
||||
NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(did, topicId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,6 +305,7 @@ public class NotificationsController extends BaseController {
|
|||
channelGroupsCreated = false;
|
||||
notificationsQueue.postRunnable(() -> {
|
||||
openedDialogId = 0;
|
||||
openedTopicId = 0;
|
||||
total_unread_count = 0;
|
||||
personalCount = 0;
|
||||
pushMessages.clear();
|
||||
|
@ -348,8 +367,11 @@ public class NotificationsController extends BaseController {
|
|||
inChatSoundEnabled = value;
|
||||
}
|
||||
|
||||
public void setOpenedDialogId(long dialog_id) {
|
||||
notificationsQueue.postRunnable(() -> openedDialogId = dialog_id);
|
||||
public void setOpenedDialogId(long dialog_id, int topicId) {
|
||||
notificationsQueue.postRunnable(() -> {
|
||||
openedDialogId = dialog_id;
|
||||
openedTopicId = topicId;
|
||||
});
|
||||
}
|
||||
|
||||
public void setOpenedInBubble(long dialogId, boolean opened) {
|
||||
|
@ -765,7 +787,8 @@ public class NotificationsController extends BaseController {
|
|||
MessageObject messageObject = messageObjects.get(a);
|
||||
if (messageObject.messageOwner != null && (messageObject.isImportedForward() ||
|
||||
messageObject.messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL ||
|
||||
messageObject.messageOwner.silent && (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined))) {
|
||||
messageObject.messageOwner.silent && (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined)) ||
|
||||
MessageObject.isTopicActionMessage(messageObject)) {
|
||||
continue;
|
||||
}
|
||||
int mid = messageObject.getId();
|
||||
|
@ -820,6 +843,7 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
|
||||
long originalDialogId = dialogId;
|
||||
int topicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
if (dialogId == openedDialogId && ApplicationLoader.isScreenOn) {
|
||||
if (!isFcm) {
|
||||
playInChatSound();
|
||||
|
@ -840,10 +864,10 @@ public class NotificationsController extends BaseController {
|
|||
boolean isChat = DialogObject.isChatDialog(dialogId);
|
||||
int index = settingsCache.indexOfKey(dialogId);
|
||||
boolean value;
|
||||
if (index >= 0) {
|
||||
if (index >= 0 && topicId == 0) {
|
||||
value = settingsCache.valueAt(index);
|
||||
} else {
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId);
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId, topicId);
|
||||
if (notifyOverride == -1) {
|
||||
value = isGlobalNotificationsEnabled(dialogId, isChannel);
|
||||
/*if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
||||
|
@ -882,7 +906,7 @@ public class NotificationsController extends BaseController {
|
|||
if (messageObject.isReactionPush) {
|
||||
SparseBooleanArray sparseBooleanArray = new SparseBooleanArray();
|
||||
sparseBooleanArray.put(mid, true);
|
||||
getMessagesController().checkUnreadReactions(dialogId, sparseBooleanArray);
|
||||
getMessagesController().checkUnreadReactions(dialogId, MessageObject.getTopicId(messageObject.messageOwner), sparseBooleanArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -914,6 +938,7 @@ public class NotificationsController extends BaseController {
|
|||
} else if (added) {
|
||||
MessageObject messageObject = messageObjects.get(0);
|
||||
long dialog_id = messageObject.getDialogId();
|
||||
int topicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
Boolean isChannel;
|
||||
if (messageObject.isFcmMessage()) {
|
||||
isChannel = messageObject.localChannel;
|
||||
|
@ -922,7 +947,7 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
int old_unread_count = total_unread_count;
|
||||
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id);
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId);
|
||||
boolean canAddValue;
|
||||
if (notifyOverride == -1) {
|
||||
canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel);
|
||||
|
@ -982,20 +1007,28 @@ public class NotificationsController extends BaseController {
|
|||
long dialogId = dialogsToUpdate.keyAt(b);
|
||||
Integer currentCount = pushDialogs.get(dialogId);
|
||||
int newCount = dialogsToUpdate.get(dialogId);
|
||||
|
||||
boolean forum = false;
|
||||
if (DialogObject.isChatDialog(dialogId)) {
|
||||
TLRPC.Chat chat = getMessagesController().getChat(-dialogId);
|
||||
if (chat == null || chat.min || ChatObject.isNotInChat(chat)) {
|
||||
newCount = 0;
|
||||
}
|
||||
if (chat != null) {
|
||||
forum = chat.forum;
|
||||
}
|
||||
}
|
||||
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId);
|
||||
|
||||
boolean canAddValue;
|
||||
if (notifyOverride == -1) {
|
||||
canAddValue = isGlobalNotificationsEnabled(dialogId);
|
||||
if (!forum) {
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId, 0);
|
||||
if (notifyOverride == -1) {
|
||||
canAddValue = isGlobalNotificationsEnabled(dialogId);
|
||||
} else {
|
||||
canAddValue = notifyOverride != 2;
|
||||
}
|
||||
} else {
|
||||
canAddValue = notifyOverride != 2;
|
||||
canAddValue = true;
|
||||
}
|
||||
|
||||
if (notifyCheck && !canAddValue) {
|
||||
|
@ -1123,15 +1156,16 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
long dialog_id = messageObject.getDialogId();
|
||||
long original_dialog_id = dialog_id;
|
||||
int topicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
if (messageObject.messageOwner.mentioned) {
|
||||
dialog_id = messageObject.getFromChatId();
|
||||
}
|
||||
int index = settingsCache.indexOfKey(dialog_id);
|
||||
boolean value;
|
||||
if (index >= 0) {
|
||||
if (index >= 0 && topicId == 0) {
|
||||
value = settingsCache.valueAt(index);
|
||||
} else {
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id);
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId);
|
||||
if (notifyOverride == -1) {
|
||||
value = isGlobalNotificationsEnabled(dialog_id);
|
||||
} else {
|
||||
|
@ -1161,7 +1195,7 @@ public class NotificationsController extends BaseController {
|
|||
if (index >= 0) {
|
||||
value = settingsCache.valueAt(index);
|
||||
} else {
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id);
|
||||
int notifyOverride = getNotifyOverride(preferences, dialog_id, 0);
|
||||
if (notifyOverride == -1) {
|
||||
value = isGlobalNotificationsEnabled(dialog_id);
|
||||
} else {
|
||||
|
@ -1190,16 +1224,17 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
long dialogId = messageObject.getDialogId();
|
||||
long originalDialogId = dialogId;
|
||||
int topicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
long randomId = messageObject.messageOwner.random_id;
|
||||
if (messageObject.messageOwner.mentioned) {
|
||||
dialogId = messageObject.getFromChatId();
|
||||
}
|
||||
int index = settingsCache.indexOfKey(dialogId);
|
||||
boolean value;
|
||||
if (index >= 0) {
|
||||
if (index >= 0 && topicId == 0) {
|
||||
value = settingsCache.valueAt(index);
|
||||
} else {
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId);
|
||||
int notifyOverride = getNotifyOverride(preferences, dialogId, topicId);
|
||||
if (notifyOverride == -1) {
|
||||
value = isGlobalNotificationsEnabled(dialogId);
|
||||
} else {
|
||||
|
@ -2591,10 +2626,10 @@ public class NotificationsController extends BaseController {
|
|||
&& (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty);
|
||||
}
|
||||
|
||||
private int getNotifyOverride(SharedPreferences preferences, long dialog_id) {
|
||||
int notifyOverride = preferences.getInt("notify2_" + dialog_id, -1);
|
||||
private int getNotifyOverride(SharedPreferences preferences, long dialog_id, int topicId) {
|
||||
int notifyOverride = dialogsNotificationsFacade.getProperty(NotificationsSettingsFacade.PROPERTY_NOTIFY, dialog_id, topicId, -1);
|
||||
if (notifyOverride == 3) {
|
||||
int muteUntil = preferences.getInt("notifyuntil_" + dialog_id, 0);
|
||||
int muteUntil = dialogsNotificationsFacade.getProperty(NotificationsSettingsFacade.PROPERTY_NOTIFY_UNTIL, dialog_id, topicId, 0);
|
||||
if (muteUntil >= getConnectionsManager().getCurrentTime()) {
|
||||
notifyOverride = 2;
|
||||
}
|
||||
|
@ -2654,7 +2689,7 @@ public class NotificationsController extends BaseController {
|
|||
|
||||
try {
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
int notifyOverride = getNotifyOverride(preferences, openedDialogId);
|
||||
int notifyOverride = getNotifyOverride(preferences, openedDialogId, openedTopicId);
|
||||
if (notifyOverride == 2) {
|
||||
return;
|
||||
}
|
||||
|
@ -2733,11 +2768,11 @@ public class NotificationsController extends BaseController {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void deleteNotificationChannel(long dialogId) {
|
||||
deleteNotificationChannel(dialogId, -1);
|
||||
public void deleteNotificationChannel(long dialogId, int topicId) {
|
||||
deleteNotificationChannel(dialogId, topicId, -1);
|
||||
}
|
||||
|
||||
private void deleteNotificationChannelInternal(long dialogId, int what) {
|
||||
private void deleteNotificationChannelInternal(long dialogId, int topicId, int what) {
|
||||
if (Build.VERSION.SDK_INT < 26) {
|
||||
return;
|
||||
}
|
||||
|
@ -2746,6 +2781,9 @@ public class NotificationsController extends BaseController {
|
|||
SharedPreferences.Editor editor = preferences.edit();
|
||||
if (what == 0 || what == -1) {
|
||||
String key = "org.telegram.key" + dialogId;
|
||||
if (topicId != 0) {
|
||||
key += ".topic" + topicId;
|
||||
}
|
||||
String channelId = preferences.getString(key, null);
|
||||
if (channelId != null) {
|
||||
editor.remove(key).remove(key + "_s");
|
||||
|
@ -2780,11 +2818,11 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void deleteNotificationChannel(long dialogId, int what) {
|
||||
public void deleteNotificationChannel(long dialogId, int topicId, int what) {
|
||||
if (Build.VERSION.SDK_INT < 26) {
|
||||
return;
|
||||
}
|
||||
notificationsQueue.postRunnable(() -> deleteNotificationChannelInternal(dialogId, what));
|
||||
notificationsQueue.postRunnable(() -> deleteNotificationChannelInternal(dialogId, topicId, what));
|
||||
}
|
||||
|
||||
public void deleteNotificationChannelGlobal(int type) {
|
||||
|
@ -3079,7 +3117,7 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
|
||||
@TargetApi(26)
|
||||
private String validateChannelId(long dialogId, String name, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int type) {
|
||||
private String validateChannelId(long dialogId, int topicId, String name, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int type) {
|
||||
ensureGroupsCreated();
|
||||
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
|
@ -3126,7 +3164,8 @@ public class NotificationsController extends BaseController {
|
|||
if (isInApp) {
|
||||
name = LocaleController.formatString("NotificationsChatInApp", R.string.NotificationsChatInApp, name);
|
||||
}
|
||||
key = (isInApp ? "org.telegram.keyia" : "org.telegram.key") + dialogId;
|
||||
//TODO notifications
|
||||
key = (isInApp ? "org.telegram.keyia" : "org.telegram.key") + dialogId + "_" + topicId;
|
||||
}
|
||||
key += "_" + soundHash;
|
||||
String channelId = preferences.getString(key, null);
|
||||
|
@ -3178,8 +3217,8 @@ public class NotificationsController extends BaseController {
|
|||
updateServerNotificationsSettings(type);
|
||||
}
|
||||
} else {
|
||||
editor.putInt("notify2_" + dialogId, 2);
|
||||
updateServerNotificationsSettings(dialogId, true);
|
||||
editor.putInt("notify2_" + NotificationsController.getSharedPrefKey(dialogId, 0), 2);
|
||||
updateServerNotificationsSettings(dialogId, 0,true);
|
||||
}
|
||||
edited = true;
|
||||
} else if (channelImportance != importance) {
|
||||
|
@ -3352,6 +3391,8 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
|
||||
long dialog_id = lastMessageObject.getDialogId();
|
||||
int topicId = MessageObject.getTopicId(lastMessageObject.messageOwner);
|
||||
|
||||
boolean isChannel = false;
|
||||
long override_dialog_id = dialog_id;
|
||||
if (lastMessageObject.messageOwner.mentioned) {
|
||||
|
@ -3383,7 +3424,7 @@ public class NotificationsController extends BaseController {
|
|||
int ledColor = 0xff0000ff;
|
||||
int importance = 0;
|
||||
|
||||
int notifyOverride = getNotifyOverride(preferences, override_dialog_id);
|
||||
int notifyOverride = getNotifyOverride(preferences, override_dialog_id, topicId);
|
||||
boolean value;
|
||||
if (notifyOverride == -1) {
|
||||
value = isGlobalNotificationsEnabled(dialog_id, isChannel);
|
||||
|
@ -3531,7 +3572,7 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
if (!notifyDisabled && !preferences.getBoolean("sound_enabled_" + dialog_id, true)) {
|
||||
if (!notifyDisabled && !preferences.getBoolean("sound_enabled_" + getSharedPrefKey(dialog_id, topicId), true)) {
|
||||
notifyDisabled = true;
|
||||
}
|
||||
|
||||
|
@ -3546,18 +3587,21 @@ public class NotificationsController extends BaseController {
|
|||
int customVibrate;
|
||||
int customImportance;
|
||||
Integer customLedColor;
|
||||
if (preferences.getBoolean("custom_" + dialog_id, false)) {
|
||||
customVibrate = preferences.getInt("vibrate_" + dialog_id, 0);
|
||||
customImportance = preferences.getInt("priority_" + dialog_id, 3);
|
||||
long soundDocumentId = preferences.getLong("sound_document_id_" + dialog_id, 0);
|
||||
String key = getSharedPrefKey(dialog_id, topicId);
|
||||
if (dialogsNotificationsFacade.getProperty("custom_", dialog_id, topicId, false)) {
|
||||
customVibrate = dialogsNotificationsFacade.getProperty("vibrate_", dialog_id, topicId, 0);
|
||||
customImportance = dialogsNotificationsFacade.getProperty("priority_", dialog_id, topicId, 3);
|
||||
long soundDocumentId = dialogsNotificationsFacade.getProperty("sound_document_id_" , dialog_id, topicId, 0L);
|
||||
if (soundDocumentId != 0) {
|
||||
customIsInternalSound = true;
|
||||
customSoundPath = getMediaDataController().ringtoneDataStore.getSoundPath(soundDocumentId);
|
||||
} else {
|
||||
customSoundPath = preferences.getString("sound_path_" + dialog_id, null);
|
||||
customSoundPath = dialogsNotificationsFacade.getPropertyString("sound_path_" , dialog_id, topicId, null);
|
||||
}
|
||||
if (preferences.contains("color_" + dialog_id)) {
|
||||
customLedColor = preferences.getInt("color_" + dialog_id, 0);
|
||||
|
||||
int color = dialogsNotificationsFacade.getProperty("color_", dialog_id, topicId, 0);
|
||||
if (color != 0) {
|
||||
customLedColor = color;
|
||||
} else {
|
||||
customLedColor = null;
|
||||
}
|
||||
|
@ -3858,7 +3902,7 @@ public class NotificationsController extends BaseController {
|
|||
mBuilder.addAction(R.drawable.ic_ab_reply, LocaleController.getString("Reply", R.string.Reply), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 2, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
}
|
||||
}
|
||||
showExtraNotifications(mBuilder, detailText, dialog_id, chatName, vibrationPattern, ledColor, sound, configImportance, isDefault, isInApp, notifyDisabled, chatType);
|
||||
showExtraNotifications(mBuilder, detailText, dialog_id, topicId, chatName, vibrationPattern, ledColor, sound, configImportance, isDefault, isInApp, notifyDisabled, chatType);
|
||||
scheduleNotificationRepeat();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
|
@ -3878,7 +3922,7 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private void resetNotificationSound(NotificationCompat.Builder notificationBuilder, long dialogId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
|
||||
private void resetNotificationSound(NotificationCompat.Builder notificationBuilder, long dialogId, int topicId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
|
||||
Uri defaultSound = Settings.System.DEFAULT_RINGTONE_URI;
|
||||
if (defaultSound != null && sound != null && !TextUtils.equals(defaultSound.toString(), sound.toString())) {
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
|
@ -3903,21 +3947,21 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
getNotificationsController().deleteNotificationChannelGlobalInternal(chatType, -1);
|
||||
} else {
|
||||
editor.putString("sound_" + dialogId, ringtoneName);
|
||||
editor.putString("sound_path_" + dialogId, newSound);
|
||||
deleteNotificationChannelInternal(dialogId, -1);
|
||||
editor.putString("sound_" + NotificationsController.getSharedPrefKey(dialogId, topicId), ringtoneName);
|
||||
editor.putString("sound_path_" + NotificationsController.getSharedPrefKey(dialogId, topicId), newSound);
|
||||
deleteNotificationChannelInternal(dialogId, topicId, -1);
|
||||
}
|
||||
editor.commit();
|
||||
sound = Settings.System.DEFAULT_RINGTONE_URI;
|
||||
notificationBuilder.setChannelId(validateChannelId(dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
|
||||
notificationBuilder.setChannelId(validateChannelId(dialogId, topicId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
|
||||
notificationManager.notify(notificationId, notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private void showExtraNotifications(NotificationCompat.Builder notificationBuilder, String summary, long lastDialogId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
|
||||
private void showExtraNotifications(NotificationCompat.Builder notificationBuilder, String summary, long lastDialogId, int lastTopicId, String chatName, long[] vibrationPattern, int ledColor, Uri sound, int importance, boolean isDefault, boolean isInApp, boolean isSilent, int chatType) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
notificationBuilder.setChannelId(validateChannelId(lastDialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
|
||||
notificationBuilder.setChannelId(validateChannelId(lastDialogId, lastTopicId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType));
|
||||
}
|
||||
Notification mainNotification = notificationBuilder.build();
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
|
@ -3930,11 +3974,12 @@ public class NotificationsController extends BaseController {
|
|||
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
|
||||
ArrayList<Long> sortedDialogs = new ArrayList<>();
|
||||
ArrayList<DialogKey> sortedDialogs = new ArrayList<>();
|
||||
LongSparseArray<ArrayList<MessageObject>> messagesByDialogs = new LongSparseArray<>();
|
||||
for (int a = 0; a < pushMessages.size(); a++) {
|
||||
MessageObject messageObject = pushMessages.get(a);
|
||||
long dialog_id = messageObject.getDialogId();
|
||||
int topicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
int dismissDate = preferences.getInt("dismissDate" + dialog_id, 0);
|
||||
if (messageObject.messageOwner.date <= dismissDate) {
|
||||
continue;
|
||||
|
@ -3944,7 +3989,7 @@ public class NotificationsController extends BaseController {
|
|||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
messagesByDialogs.put(dialog_id, arrayList);
|
||||
sortedDialogs.add(dialog_id);
|
||||
sortedDialogs.add(new DialogKey(dialog_id, topicId));
|
||||
}
|
||||
arrayList.add(messageObject);
|
||||
}
|
||||
|
@ -3958,18 +4003,20 @@ public class NotificationsController extends BaseController {
|
|||
class NotificationHolder {
|
||||
int id;
|
||||
long dialogId;
|
||||
int topicId;
|
||||
String name;
|
||||
TLRPC.User user;
|
||||
TLRPC.Chat chat;
|
||||
NotificationCompat.Builder notification;
|
||||
|
||||
NotificationHolder(int i, long li, String n, TLRPC.User u, TLRPC.Chat c, NotificationCompat.Builder builder) {
|
||||
NotificationHolder(int i, long li, int topicId, String n, TLRPC.User u, TLRPC.Chat c, NotificationCompat.Builder builder) {
|
||||
id = i;
|
||||
name = n;
|
||||
user = u;
|
||||
chat = c;
|
||||
notification = builder;
|
||||
dialogId = li;
|
||||
this.topicId = topicId;
|
||||
}
|
||||
|
||||
void call() {
|
||||
|
@ -3980,7 +4027,7 @@ public class NotificationsController extends BaseController {
|
|||
notificationManager.notify(id, notification.build());
|
||||
} catch (SecurityException e) {
|
||||
FileLog.e(e);
|
||||
resetNotificationSound(notification, dialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
|
||||
resetNotificationSound(notification, dialogId, lastTopicId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4001,7 +4048,9 @@ public class NotificationsController extends BaseController {
|
|||
if (holders.size() >= maxCount) {
|
||||
break;
|
||||
}
|
||||
long dialogId = sortedDialogs.get(b);
|
||||
DialogKey dialogKey = sortedDialogs.get(b);
|
||||
long dialogId = dialogKey.dialogId;
|
||||
int topicId = dialogKey.topicId;
|
||||
ArrayList<MessageObject> messageObjects = messagesByDialogs.get(dialogId);
|
||||
int maxId = messageObjects.get(0).getId();
|
||||
|
||||
|
@ -4017,7 +4066,6 @@ public class NotificationsController extends BaseController {
|
|||
for (int i = 0; i < messageObjects.size(); i++) {
|
||||
if (maxDate < messageObjects.get(i).messageOwner.date) {
|
||||
maxDate = messageObjects.get(i).messageOwner.date;
|
||||
|
||||
}
|
||||
}
|
||||
TLRPC.Chat chat = null;
|
||||
|
@ -4074,6 +4122,14 @@ public class NotificationsController extends BaseController {
|
|||
if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) {
|
||||
photoPath = chat.photo.photo_small;
|
||||
}
|
||||
|
||||
if (topicId != 0) {
|
||||
TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(chat.id, topicId);
|
||||
if (topic != null) {
|
||||
name = topic.title + " in " + name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -4144,6 +4200,7 @@ public class NotificationsController extends BaseController {
|
|||
Intent replyIntent = new Intent(ApplicationLoader.applicationContext, WearReplyReceiver.class);
|
||||
replyIntent.putExtra("dialog_id", dialogId);
|
||||
replyIntent.putExtra("max_id", maxId);
|
||||
replyIntent.putExtra("topic_id", topicId);
|
||||
replyIntent.putExtra("currentAccount", currentAccount);
|
||||
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
RemoteInput remoteInputWear = new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(LocaleController.getString("Reply", R.string.Reply)).build();
|
||||
|
@ -4211,6 +4268,10 @@ public class NotificationsController extends BaseController {
|
|||
int rowsMid = 0;
|
||||
for (int a = messageObjects.size() - 1; a >= 0; a--) {
|
||||
MessageObject messageObject = messageObjects.get(a);
|
||||
int messageTopicId = MessageObject.getTopicId(messageObject.messageOwner);
|
||||
if (topicId != messageTopicId) {
|
||||
continue;
|
||||
}
|
||||
String message = getShortStringForMessage(messageObject, senderName, preview);
|
||||
if (dialogId == selfUserId) {
|
||||
senderName[0] = name;
|
||||
|
@ -4247,8 +4308,8 @@ public class NotificationsController extends BaseController {
|
|||
} else {
|
||||
uid = dialogId;
|
||||
}
|
||||
Person person = personCache.get(uid);
|
||||
String personName = "";
|
||||
Person person = personCache.get(uid + ((long) topicId << 16));
|
||||
CharSequence personName = "";
|
||||
if (senderName[0] == null) {
|
||||
if (waitingForPasscode) {
|
||||
if (DialogObject.isChatDialog(dialogId)) {
|
||||
|
@ -4266,6 +4327,7 @@ public class NotificationsController extends BaseController {
|
|||
} else {
|
||||
personName = senderName[0];
|
||||
}
|
||||
|
||||
if (person == null || !TextUtils.equals(person.getName(), personName)) {
|
||||
Person.Builder personBuilder = new Person.Builder().setName(personName);
|
||||
if (preview[0] && !DialogObject.isEncryptedDialog(dialogId) && Build.VERSION.SDK_INT >= 28) {
|
||||
|
@ -4291,10 +4353,11 @@ public class NotificationsController extends BaseController {
|
|||
personCache.put(uid, person);
|
||||
}
|
||||
|
||||
|
||||
if (!DialogObject.isEncryptedDialog(dialogId)) {
|
||||
boolean setPhoto = false;
|
||||
if (preview[0] && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice()) {
|
||||
if (!waitingForPasscode && !messageObject.isSecretMedia() && (messageObject.type == 1 || messageObject.isSticker())) {
|
||||
if (!waitingForPasscode && !messageObject.isSecretMedia() && (messageObject.type == MessageObject.TYPE_PHOTO || messageObject.isSticker())) {
|
||||
File attach = getFileLoader().getPathToMessage(messageObject.messageOwner);
|
||||
NotificationCompat.MessagingStyle.Message msg = new NotificationCompat.MessagingStyle.Message(message, ((long) messageObject.messageOwner.date) * 1000L, person);
|
||||
String mimeType = messageObject.isSticker() ? "image/webp" : "image/jpeg";
|
||||
|
@ -4376,6 +4439,9 @@ public class NotificationsController extends BaseController {
|
|||
} else {
|
||||
intent.putExtra("chatId", -dialogId);
|
||||
}
|
||||
if (topicId != 0) {
|
||||
intent.putExtra("topicId", topicId);
|
||||
}
|
||||
intent.putExtra("currentAccount", currentAccount);
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||
|
||||
|
@ -4489,7 +4555,7 @@ public class NotificationsController extends BaseController {
|
|||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
setNotificationChannel(mainNotification, builder, useSummaryNotification);
|
||||
}
|
||||
holders.add(new NotificationHolder(internalId, dialogId, name, user, chat, builder));
|
||||
holders.add(new NotificationHolder(internalId, dialogId, topicId, name, user, chat, builder));
|
||||
wearNotificationsIds.put(dialogId, internalId);
|
||||
}
|
||||
|
||||
|
@ -4501,7 +4567,7 @@ public class NotificationsController extends BaseController {
|
|||
notificationManager.notify(notificationId, mainNotification);
|
||||
} catch (SecurityException e) {
|
||||
FileLog.e(e);
|
||||
resetNotificationSound(notificationBuilder, lastDialogId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
|
||||
resetNotificationSound(notificationBuilder, lastDialogId, lastTopicId, chatName, vibrationPattern, ledColor, sound, importance, isDefault, isInApp, isSilent, chatType);
|
||||
}
|
||||
} else {
|
||||
if (openedInBubbleDialogs.isEmpty()) {
|
||||
|
@ -4616,30 +4682,32 @@ public class NotificationsController extends BaseController {
|
|||
public static final int SETTING_MUTE_UNMUTE = 4;
|
||||
public static final int SETTING_MUTE_CUSTOM = 5;
|
||||
|
||||
public void clearDialogNotificationsSettings(long did) {
|
||||
public void clearDialogNotificationsSettings(long did, int topicId) {
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.remove("notify2_" + did).remove("custom_" + did);
|
||||
String prefKey = NotificationsController.getSharedPrefKey(did, topicId);
|
||||
editor.remove("notify2_" + prefKey).remove("custom_" + prefKey);
|
||||
getMessagesStorage().setDialogFlags(did, 0);
|
||||
TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(did);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
}
|
||||
editor.commit();
|
||||
getNotificationsController().updateServerNotificationsSettings(did, true);
|
||||
getNotificationsController().updateServerNotificationsSettings(did, topicId,true);
|
||||
}
|
||||
|
||||
public void setDialogNotificationsSettings(long dialog_id, int setting) {
|
||||
public void setDialogNotificationsSettings(long dialog_id, int topicId, int setting) {
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
TLRPC.Dialog dialog = MessagesController.getInstance(UserConfig.selectedAccount).dialogs_dict.get(dialog_id);
|
||||
if (setting == SETTING_MUTE_UNMUTE) {
|
||||
boolean defaultEnabled = isGlobalNotificationsEnabled(dialog_id);
|
||||
if (defaultEnabled) {
|
||||
editor.remove("notify2_" + dialog_id);
|
||||
editor.remove("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId));
|
||||
} else {
|
||||
editor.putInt("notify2_" + dialog_id, 0);
|
||||
editor.putInt("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId), 0);
|
||||
}
|
||||
//TODO topic
|
||||
getMessagesStorage().setDialogFlags(dialog_id, 0);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
|
@ -4657,11 +4725,11 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
long flags;
|
||||
if (setting == SETTING_MUTE_FOREVER) {
|
||||
editor.putInt("notify2_" + dialog_id, 2);
|
||||
editor.putInt("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId), 2);
|
||||
flags = 1;
|
||||
} else {
|
||||
editor.putInt("notify2_" + dialog_id, 3);
|
||||
editor.putInt("notifyuntil_" + dialog_id, untilTime);
|
||||
editor.putInt("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId), 3);
|
||||
editor.putInt("notifyuntil_" + NotificationsController.getSharedPrefKey(dialog_id, topicId), untilTime);
|
||||
flags = ((long) untilTime << 32) | 1;
|
||||
}
|
||||
NotificationsController.getInstance(UserConfig.selectedAccount).removeNotificationsForDialog(dialog_id);
|
||||
|
@ -4672,14 +4740,14 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
editor.commit();
|
||||
updateServerNotificationsSettings(dialog_id);
|
||||
updateServerNotificationsSettings(dialog_id, topicId);
|
||||
}
|
||||
|
||||
public void updateServerNotificationsSettings(long dialog_id) {
|
||||
updateServerNotificationsSettings(dialog_id, true);
|
||||
public void updateServerNotificationsSettings(long dialog_id, int topicId) {
|
||||
updateServerNotificationsSettings(dialog_id, topicId, true);
|
||||
}
|
||||
|
||||
public void updateServerNotificationsSettings(long dialogId, boolean post) {
|
||||
public void updateServerNotificationsSettings(long dialogId, int topicId, boolean post) {
|
||||
if (post) {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated);
|
||||
}
|
||||
|
@ -4691,23 +4759,23 @@ public class NotificationsController extends BaseController {
|
|||
req.settings = new TLRPC.TL_inputPeerNotifySettings();
|
||||
|
||||
req.settings.flags |= 1;
|
||||
req.settings.show_previews = preferences.getBoolean("content_preview_" + dialogId, true);
|
||||
req.settings.show_previews = preferences.getBoolean("content_preview_" + NotificationsController.getSharedPrefKey(dialogId, topicId), true);
|
||||
|
||||
req.settings.flags |= 2;
|
||||
req.settings.silent = preferences.getBoolean("silent_" + dialogId, false);
|
||||
req.settings.silent = preferences.getBoolean("silent_" + NotificationsController.getSharedPrefKey(dialogId, topicId), false);
|
||||
|
||||
int mute_type = preferences.getInt("notify2_" + dialogId, -1);
|
||||
int mute_type = preferences.getInt("notify2_" + NotificationsController.getSharedPrefKey(dialogId, topicId), -1);
|
||||
if (mute_type != -1) {
|
||||
req.settings.flags |= 4;
|
||||
if (mute_type == 3) {
|
||||
req.settings.mute_until = preferences.getInt("notifyuntil_" + dialogId, 0);
|
||||
req.settings.mute_until = preferences.getInt("notifyuntil_" + NotificationsController.getSharedPrefKey(dialogId, topicId), 0);
|
||||
} else {
|
||||
req.settings.mute_until = mute_type != 2 ? 0 : Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
long soundDocumentId = preferences.getLong("sound_document_id_" + dialogId, 0);
|
||||
String soundPath = preferences.getString("sound_path_" + dialogId, null);
|
||||
long soundDocumentId = preferences.getLong("sound_document_id_" + NotificationsController.getSharedPrefKey(dialogId, topicId), 0);
|
||||
String soundPath = preferences.getString("sound_path_" + NotificationsController.getSharedPrefKey(dialogId, topicId), null);
|
||||
req.settings.flags |= 8;
|
||||
if (soundDocumentId != 0) {
|
||||
TLRPC.TL_notificationSoundRingtone ringtoneSound = new TLRPC.TL_notificationSoundRingtone();
|
||||
|
@ -4718,19 +4786,25 @@ public class NotificationsController extends BaseController {
|
|||
req.settings.sound = new TLRPC.TL_notificationSoundNone();
|
||||
} else {
|
||||
TLRPC.TL_notificationSoundLocal localSound = new TLRPC.TL_notificationSoundLocal();
|
||||
localSound.title = preferences.getString("sound_" + dialogId, null);
|
||||
localSound.title = preferences.getString("sound_" + NotificationsController.getSharedPrefKey(dialogId, topicId), null);
|
||||
localSound.data = soundPath;
|
||||
req.settings.sound = localSound;
|
||||
}
|
||||
} else {
|
||||
req.settings.sound = new TLRPC.TL_notificationSoundDefault();
|
||||
}
|
||||
if (topicId != 0) {
|
||||
TLRPC.TL_inputNotifyForumTopic topicPeer = new TLRPC.TL_inputNotifyForumTopic();
|
||||
topicPeer.peer = getMessagesController().getInputPeer(dialogId);
|
||||
topicPeer.top_msg_id = topicId;
|
||||
req.peer = topicPeer;
|
||||
} else {
|
||||
req.peer = new TLRPC.TL_inputNotifyPeer();
|
||||
((TLRPC.TL_inputNotifyPeer) req.peer).peer = getMessagesController().getInputPeer(dialogId);
|
||||
}
|
||||
|
||||
req.peer = new TLRPC.TL_inputNotifyPeer();
|
||||
|
||||
((TLRPC.TL_inputNotifyPeer) req.peer).peer = getMessagesController().getInputPeer(dialogId);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
|
||||
// FileLog.d("updateServerNotificationsSettings " + dialogId + " " + topicId + " error = " + error);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4842,25 +4916,69 @@ public class NotificationsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public void muteDialog(long dialog_id, boolean mute) {
|
||||
public void muteDialog(long dialog_id, int topicId, boolean mute) {
|
||||
if (mute) {
|
||||
NotificationsController.getInstance(currentAccount).muteUntil(dialog_id, Integer.MAX_VALUE);
|
||||
NotificationsController.getInstance(currentAccount).muteUntil(dialog_id, topicId, Integer.MAX_VALUE);
|
||||
} else {
|
||||
boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id);
|
||||
boolean override = topicId != 0;
|
||||
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
if (defaultEnabled) {
|
||||
editor.remove("notify2_" + dialog_id);
|
||||
if (defaultEnabled && !override) {
|
||||
editor.remove("notify2_" + getSharedPrefKey(dialog_id, topicId));
|
||||
} else {
|
||||
editor.putInt("notify2_" + dialog_id, 0);
|
||||
editor.putInt("notify2_" + getSharedPrefKey(dialog_id, topicId), 0);
|
||||
}
|
||||
if (topicId == 0) {
|
||||
getMessagesStorage().setDialogFlags(dialog_id, 0);
|
||||
TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
}
|
||||
}
|
||||
getMessagesStorage().setDialogFlags(dialog_id, 0);
|
||||
editor.apply();
|
||||
TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
updateServerNotificationsSettings(dialog_id, topicId);
|
||||
}
|
||||
}
|
||||
|
||||
public NotificationsSettingsFacade getNotificationsSettingsFacade() {
|
||||
return dialogsNotificationsFacade;
|
||||
}
|
||||
|
||||
public void loadTopicsNotificationsExceptions(long dialogId, Consumer<HashSet<Integer>> consumer) {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
HashSet<Integer> topics = new HashSet<>();
|
||||
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||
Map<String, ?> values = preferences.getAll();
|
||||
for (Map.Entry<String, ?> entry : values.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.startsWith("notify2_" + dialogId)) {
|
||||
key = key.replace("notify2_" + dialogId, "");
|
||||
|
||||
int topicId = Utilities.parseInt(key);
|
||||
if (topicId != 0) {
|
||||
if (getMessagesController().isDialogMuted(dialogId, topicId) != getMessagesController().isDialogMuted(dialogId, 0)) {
|
||||
topics.add(topicId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateServerNotificationsSettings(dialog_id);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (consumer != null) {
|
||||
consumer.accept(topics);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static class DialogKey {
|
||||
final long dialogId;
|
||||
final int topicId;
|
||||
|
||||
private DialogKey(long dialogId, int topicId) {
|
||||
this.dialogId = dialogId;
|
||||
this.topicId = topicId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
package org.telegram.messenger;
|
||||
|
||||
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
|
||||
import static android.app.NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
|
@ -16,9 +19,6 @@ import android.content.SharedPreferences;
|
|||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
|
||||
import static android.app.NotificationManager.EXTRA_NOTIFICATION_CHANNEL_ID;
|
||||
|
||||
@TargetApi(28)
|
||||
public class NotificationsDisabledReceiver extends BroadcastReceiver {
|
||||
|
||||
|
@ -86,6 +86,8 @@ public class NotificationsDisabledReceiver extends BroadcastReceiver {
|
|||
if (dialogId == 0) {
|
||||
return;
|
||||
}
|
||||
int topicId = 0;
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
String currentChannel = preferences.getString("org.telegram.key" + dialogId, null);
|
||||
if (!channelId.equals(currentChannel)) {
|
||||
return;
|
||||
|
@ -94,12 +96,12 @@ public class NotificationsDisabledReceiver extends BroadcastReceiver {
|
|||
FileLog.d("apply channel " + channelId + " state");
|
||||
}
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("notify2_" + dialogId, state ? 2 : 0);
|
||||
editor.putInt("notify2_" + key, state ? 2 : 0);
|
||||
if (!state) {
|
||||
editor.remove("notifyuntil_" + dialogId);
|
||||
editor.remove("notifyuntil_" + key);
|
||||
}
|
||||
editor.commit();
|
||||
AccountInstance.getInstance(account).getNotificationsController().updateServerNotificationsSettings(dialogId, true);
|
||||
AccountInstance.getInstance(account).getNotificationsController().updateServerNotificationsSettings(dialogId, 0, true);
|
||||
}
|
||||
AccountInstance.getInstance(account).getConnectionsManager().resumeNetworkMaybe();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
|
||||
public class NotificationsSettingsFacade {
|
||||
|
||||
public final static String PROPERTY_NOTIFY = "notify2_";
|
||||
public final static String PROPERTY_CUSTOM = "custom_";
|
||||
public final static String PROPERTY_NOTIFY_UNTIL = "notifyuntil_";
|
||||
public final static String PROPERTY_CONTENT_PREVIEW = "content_preview_";
|
||||
public final static String PROPERTY_SILENT = "silent_";
|
||||
|
||||
private final int currentAccount;
|
||||
|
||||
public NotificationsSettingsFacade(int currentAccount) {
|
||||
this.currentAccount = currentAccount;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDefault(long dialogId, int topicId) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clearPreference(long dialogId, int topicId) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
getPreferences().edit()
|
||||
.remove(PROPERTY_NOTIFY + key)
|
||||
.remove(PROPERTY_CUSTOM + key)
|
||||
.remove(PROPERTY_NOTIFY_UNTIL + key)
|
||||
.remove(PROPERTY_CONTENT_PREVIEW + key)
|
||||
.remove(PROPERTY_SILENT + key)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public int getProperty(String property, long dialogId, int topicId, int defaultValue) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
if (getPreferences().contains(property + key)) {
|
||||
return getPreferences().getInt(property + key, defaultValue);
|
||||
}
|
||||
key = NotificationsController.getSharedPrefKey(dialogId, 0);
|
||||
return getPreferences().getInt(property + key, defaultValue);
|
||||
}
|
||||
|
||||
public long getProperty(String property, long dialogId, int topicId, long defaultValue) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
if (getPreferences().contains(property + key)) {
|
||||
return getPreferences().getLong(property + key, defaultValue);
|
||||
}
|
||||
key = NotificationsController.getSharedPrefKey(dialogId, 0);
|
||||
return getPreferences().getLong(property + key, defaultValue);
|
||||
}
|
||||
|
||||
public boolean getProperty(String property, long dialogId, int topicId, boolean defaultValue) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
if (getPreferences().contains(property + key)) {
|
||||
return getPreferences().getBoolean(property + key, defaultValue);
|
||||
}
|
||||
key = NotificationsController.getSharedPrefKey(dialogId, 0);
|
||||
return getPreferences().getBoolean(property + key, defaultValue);
|
||||
}
|
||||
|
||||
public String getPropertyString(String property, long dialogId, int topicId, String defaultValue) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
if (getPreferences().contains(property + key)) {
|
||||
return getPreferences().getString(property + key, defaultValue);
|
||||
}
|
||||
key = NotificationsController.getSharedPrefKey(dialogId, 0);
|
||||
return getPreferences().getString(property + key, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
public void removeProperty(String property, long dialogId, int topicId) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
getPreferences().edit().remove(property + key).apply();
|
||||
}
|
||||
|
||||
private SharedPreferences getPreferences() {
|
||||
return MessagesController.getNotificationsSettings(currentAccount);
|
||||
}
|
||||
|
||||
public void applyDialogNotificationsSettings(long dialogId, int topicId, TLRPC.PeerNotifySettings notify_settings) {
|
||||
if (notify_settings == null) {
|
||||
return;
|
||||
}
|
||||
Utilities.globalQueue.postRunnable(() -> {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
MessagesController messagesController = MessagesController.getInstance(currentAccount);
|
||||
ConnectionsManager connectionsManager = ConnectionsManager.getInstance(currentAccount);
|
||||
MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount);
|
||||
NotificationsController notificationsController = NotificationsController.getInstance(currentAccount);
|
||||
|
||||
int currentValue = getPreferences().getInt(PROPERTY_NOTIFY + key, -1);
|
||||
int currentValue2 = getPreferences().getInt(PROPERTY_NOTIFY_UNTIL + key, 0);
|
||||
SharedPreferences.Editor editor = getPreferences().edit();
|
||||
boolean updated = false;
|
||||
if ((notify_settings.flags & 2) != 0) {
|
||||
editor.putBoolean(PROPERTY_SILENT + key, notify_settings.silent);
|
||||
} else {
|
||||
editor.remove(PROPERTY_SILENT + key);
|
||||
}
|
||||
|
||||
TLRPC.Dialog dialog = null;
|
||||
if (topicId == 0) {
|
||||
dialog = messagesController.dialogs_dict.get(dialogId);
|
||||
}
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings = notify_settings;
|
||||
}
|
||||
|
||||
if ((notify_settings.flags & 4) != 0) {
|
||||
if (notify_settings.mute_until > connectionsManager.getCurrentTime()) {
|
||||
int until = 0;
|
||||
if (notify_settings.mute_until > connectionsManager.getCurrentTime() + 60 * 60 * 24 * 365) {
|
||||
if (currentValue != 2) {
|
||||
updated = true;
|
||||
editor.putInt(PROPERTY_NOTIFY + key, 2);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings.mute_until = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentValue != 3 || currentValue2 != notify_settings.mute_until) {
|
||||
updated = true;
|
||||
editor.putInt(PROPERTY_NOTIFY + key, 3);
|
||||
editor.putInt(PROPERTY_NOTIFY_UNTIL + key, notify_settings.mute_until);
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings.mute_until = until;
|
||||
}
|
||||
}
|
||||
until = notify_settings.mute_until;
|
||||
}
|
||||
if (topicId == 0) {
|
||||
messagesStorage.setDialogFlags(dialogId, ((long) until << 32) | 1);
|
||||
notificationsController.removeNotificationsForDialog(dialogId);
|
||||
}
|
||||
} else {
|
||||
if (currentValue != 0 && currentValue != 1) {
|
||||
updated = true;
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings.mute_until = 0;
|
||||
}
|
||||
editor.putInt(PROPERTY_NOTIFY + key, 0);
|
||||
}
|
||||
if (topicId == 0) {
|
||||
messagesStorage.setDialogFlags(dialogId, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentValue != -1) {
|
||||
updated = true;
|
||||
if (dialog != null) {
|
||||
dialog.notify_settings.mute_until = 0;
|
||||
}
|
||||
editor.remove(PROPERTY_NOTIFY + key);
|
||||
}
|
||||
if (topicId == 0) {
|
||||
messagesStorage.setDialogFlags(dialogId, 0);
|
||||
}
|
||||
}
|
||||
applySoundSettings(notify_settings.android_sound, editor, dialogId, topicId, 0, false);
|
||||
editor.apply();
|
||||
if (updated) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.notificationsSettingsUpdated);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void applySoundSettings(TLRPC.NotificationSound settings, SharedPreferences.Editor editor, long dialogId, int topicId, int globalType, boolean serverUpdate) {
|
||||
if (settings == null) {
|
||||
return;
|
||||
}
|
||||
String soundPref;
|
||||
String soundPathPref;
|
||||
String soundDocPref;
|
||||
if (dialogId != 0) {
|
||||
String key = NotificationsController.getSharedPrefKey(dialogId, topicId);
|
||||
soundPref = "sound_" + key;
|
||||
soundPathPref = "sound_path_" + key;
|
||||
soundDocPref = "sound_document_id_" + key;
|
||||
} else {
|
||||
if (globalType == NotificationsController.TYPE_GROUP) {
|
||||
soundPref = "GroupSound";
|
||||
soundDocPref = "GroupSoundDocId";
|
||||
soundPathPref = "GroupSoundPath";
|
||||
} else if (globalType == TYPE_PRIVATE) {
|
||||
soundPref = "GlobalSound";
|
||||
soundDocPref = "GlobalSoundDocId";
|
||||
soundPathPref = "GlobalSoundPath";
|
||||
} else {
|
||||
soundPref = "ChannelSound";
|
||||
soundDocPref = "ChannelSoundDocId";
|
||||
soundPathPref = "ChannelSoundPath";
|
||||
}
|
||||
}
|
||||
|
||||
if (settings instanceof TLRPC.TL_notificationSoundDefault) {
|
||||
editor.putString(soundPref, "Default");
|
||||
editor.putString(soundPathPref, "Default");
|
||||
editor.remove(soundDocPref);
|
||||
} else if (settings instanceof TLRPC.TL_notificationSoundNone) {
|
||||
editor.putString(soundPref, "NoSound");
|
||||
editor.putString(soundPathPref, "NoSound");
|
||||
editor.remove(soundDocPref);
|
||||
} else if (settings instanceof TLRPC.TL_notificationSoundLocal) {
|
||||
TLRPC.TL_notificationSoundLocal localSound = (TLRPC.TL_notificationSoundLocal) settings;
|
||||
editor.putString(soundPref, localSound.title);
|
||||
editor.putString(soundPathPref, localSound.data);
|
||||
editor.remove(soundDocPref);
|
||||
} else if (settings instanceof TLRPC.TL_notificationSoundRingtone) {
|
||||
TLRPC.TL_notificationSoundRingtone soundRingtone = (TLRPC.TL_notificationSoundRingtone) settings;
|
||||
editor.putLong(soundDocPref, soundRingtone.id);
|
||||
MediaDataController.getInstance(currentAccount).checkRingtones();
|
||||
if (serverUpdate && dialogId != 0) {
|
||||
editor.putBoolean("custom_" + dialogId, true);
|
||||
}
|
||||
MediaDataController.getInstance(currentAccount).ringtoneDataStore.getDocument(soundRingtone.id);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSettingsForDialog(TLRPC.Dialog dialog, TLRPC.PeerNotifySettings notify_settings) {
|
||||
SharedPreferences.Editor editor = getPreferences().edit();
|
||||
long dialogId = MessageObject.getPeerId(dialog.peer);
|
||||
|
||||
if ((dialog.notify_settings.flags & 2) != 0) {
|
||||
editor.putBoolean(PROPERTY_SILENT + dialogId, dialog.notify_settings.silent);
|
||||
} else {
|
||||
editor.remove(PROPERTY_SILENT + dialogId);
|
||||
}
|
||||
ConnectionsManager connectionsManager = ConnectionsManager.getInstance(currentAccount);
|
||||
if ((dialog.notify_settings.flags & 4) != 0) {
|
||||
if (dialog.notify_settings.mute_until > connectionsManager.getCurrentTime()) {
|
||||
if (dialog.notify_settings.mute_until > connectionsManager.getCurrentTime() + 60 * 60 * 24 * 365) {
|
||||
editor.putInt(PROPERTY_NOTIFY + dialogId, 2);
|
||||
dialog.notify_settings.mute_until = Integer.MAX_VALUE;
|
||||
} else {
|
||||
editor.putInt(PROPERTY_NOTIFY + dialogId, 3);
|
||||
editor.putInt(PROPERTY_NOTIFY_UNTIL + dialogId, dialog.notify_settings.mute_until);
|
||||
}
|
||||
} else {
|
||||
editor.putInt(PROPERTY_NOTIFY + dialogId, 0);
|
||||
}
|
||||
} else {
|
||||
editor.remove(PROPERTY_NOTIFY + dialogId);
|
||||
}
|
||||
|
||||
editor.apply();
|
||||
}
|
||||
}
|
|
@ -264,6 +264,8 @@ public class PushListenerController {
|
|||
long chat_id;
|
||||
long user_id;
|
||||
long dialogId = 0;
|
||||
|
||||
int topicId = 0;
|
||||
boolean scheduled;
|
||||
if (custom.has("channel_id")) {
|
||||
channel_id = custom.getLong("channel_id");
|
||||
|
@ -283,6 +285,9 @@ public class PushListenerController {
|
|||
} else {
|
||||
chat_id = 0;
|
||||
}
|
||||
if (custom.has("topic_id")) {
|
||||
topicId =custom.getInt("topic_id");
|
||||
}
|
||||
if (custom.has("encryption_id")) {
|
||||
dialogId = DialogObject.makeEncryptedDialogId(custom.getInt("encryption_id"));
|
||||
}
|
||||
|
@ -350,7 +355,7 @@ public class PushListenerController {
|
|||
deletedMessages.put(-channel_id, ids);
|
||||
NotificationsController.getInstance(currentAccount).removeDeletedMessagesFromNotifications(deletedMessages, true);
|
||||
|
||||
MessagesController.getInstance(currentAccount).checkUnreadReactions(dialogId, sparseBooleanArray);
|
||||
MessagesController.getInstance(currentAccount).checkUnreadReactions(dialogId, topicId, sparseBooleanArray);
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d(tag + " received " + loc_key + " for dialogId = " + dialogId + " mids = " + TextUtils.join(",", ids));
|
||||
}
|
||||
|
@ -1147,6 +1152,11 @@ public class PushListenerController {
|
|||
messageOwner.from_scheduled = scheduled;
|
||||
|
||||
MessageObject messageObject = new MessageObject(currentAccount, messageOwner, messageText, name, userName, localMessage, channel, supergroup, edited);
|
||||
if (topicId != 0) {
|
||||
messageObject.messageOwner.reply_to = new TLRPC.TL_messageReplyHeader();
|
||||
messageObject.messageOwner.reply_to.forum_topic = true;
|
||||
messageObject.messageOwner.reply_to.reply_to_top_id = topicId;
|
||||
}
|
||||
messageObject.isReactionPush = loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_");
|
||||
ArrayList<MessageObject> arrayList = new ArrayList<>();
|
||||
arrayList.add(messageObject);
|
||||
|
|
|
@ -154,7 +154,7 @@ public class SecretChatHelper extends BaseController {
|
|||
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(newMsg);
|
||||
getMessagesStorage().putMessages(arr, false, true, true, 0, false);
|
||||
getMessagesStorage().putMessages(arr, false, true, true, 0, false, 0);
|
||||
|
||||
return newMsg;
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ public class SecretChatHelper extends BaseController {
|
|||
ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForPhoto(size, newMsg.media.photo), true);
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(newMsg);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false, 0);
|
||||
|
||||
//getMessagesStorage().putSentFile(originalPath, newMsg.media.photo, 3);
|
||||
} else if (newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) {
|
||||
|
@ -568,7 +568,7 @@ public class SecretChatHelper extends BaseController {
|
|||
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(newMsg);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ import java.nio.channels.FileChannel;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
@ -100,6 +101,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
private LongSparseArray<Integer> uploadingMessagesIdDialogs = new LongSparseArray<>();
|
||||
private HashMap<String, MessageObject> waitingForLocation = new HashMap<>();
|
||||
private HashMap<String, Boolean> waitingForCallback = new HashMap<>();
|
||||
private HashMap<String, List<String>> waitingForCallbackMap = new HashMap<>();
|
||||
private HashMap<String, byte[]> waitingForVote = new HashMap<>();
|
||||
private LongSparseArray<Long> voteSendTime = new LongSparseArray();
|
||||
private HashMap<String, ImportingHistory> importingHistoryFiles = new HashMap<>();
|
||||
|
@ -1057,7 +1059,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
ArrayList<TLRPC.Message> messages = new ArrayList<>();
|
||||
messages.add(obj.messageOwner);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, obj.scheduled);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, obj.scheduled, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1068,7 +1070,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
ArrayList<TLRPC.Message> messages = new ArrayList<>();
|
||||
messages.add(message.obj.messageOwner);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, message.obj.scheduled);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, message.obj.scheduled, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1140,7 +1142,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
messageObject.messageOwner.attachPath = cacheFile.toString();
|
||||
ArrayList<TLRPC.Message> messages = new ArrayList<>();
|
||||
messages.add(messageObject.messageOwner);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled, 0);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.updateMessageMedia, messageObject.messageOwner);
|
||||
message.photoSize = photo.sizes.get(photo.sizes.size() - 1);
|
||||
message.locationParent = photo;
|
||||
|
@ -1189,7 +1191,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
ArrayList<TLRPC.Message> messages = new ArrayList<>();
|
||||
messages.add(messageObject.messageOwner);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled);
|
||||
getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled, 0);
|
||||
message.performMediaUpload = true;
|
||||
performSendDelayedMessage(message);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.updateMessageMedia, message.obj.messageOwner);
|
||||
|
@ -1243,7 +1245,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
object.type = -1;
|
||||
object.setType();
|
||||
object.caption = null;
|
||||
if (object.type != 0) {
|
||||
if (object.type != MessageObject.TYPE_TEXT) {
|
||||
object.generateCaption();
|
||||
} else {
|
||||
object.resetLayout();
|
||||
|
@ -1252,7 +1254,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(object.messageOwner);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, object.scheduled);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, object.scheduled, 0);
|
||||
|
||||
ArrayList<MessageObject> arrayList = new ArrayList<>();
|
||||
arrayList.add(object);
|
||||
|
@ -1330,7 +1332,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(prevMessage.messageOwner);
|
||||
getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduled);
|
||||
getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduled, 0);
|
||||
}
|
||||
if (!checkReadyToSendGroups.contains(message)) {
|
||||
checkReadyToSendGroups.add(message);
|
||||
|
@ -1544,7 +1546,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(message);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, false, 0);
|
||||
|
||||
performSendMessageRequest(req, newMsgObj, null, null, null, null, false);
|
||||
}
|
||||
|
@ -1655,6 +1657,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
public int sendMessage(ArrayList<MessageObject> messages, final long peer, boolean forwardFromMyName, boolean hideCaption, boolean notify, int scheduleDate) {
|
||||
return sendMessage(messages, peer, forwardFromMyName, hideCaption, notify, scheduleDate, null);
|
||||
}
|
||||
|
||||
public int sendMessage(ArrayList<MessageObject> messages, final long peer, boolean forwardFromMyName, boolean hideCaption, boolean notify, int scheduleDate, MessageObject replyToTopMsg) {
|
||||
if (messages == null || messages.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1718,9 +1724,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
for (int a = 0; a < messages.size(); a++) {
|
||||
MessageObject msgObj = messages.get(a);
|
||||
if (msgObj.getId() <= 0 || msgObj.needDrawBluredPreview()) {
|
||||
if (msgObj.type == 0 && !TextUtils.isEmpty(msgObj.messageText)) {
|
||||
if (msgObj.type == MessageObject.TYPE_TEXT && !TextUtils.isEmpty(msgObj.messageText)) {
|
||||
TLRPC.WebPage webPage = msgObj.messageOwner.media != null ? msgObj.messageOwner.media.webpage : null;
|
||||
sendMessage(msgObj.messageText.toString(), peer, null, null, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate, null, false);
|
||||
sendMessage(msgObj.messageText.toString(), peer, null, replyToTopMsg, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate, null, false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1990,8 +1996,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
FileLog.d("forward message user_id = " + inputPeer.user_id + " chat_id = " + inputPeer.chat_id + " channel_id = " + inputPeer.channel_id + " access_hash = " + inputPeer.access_hash);
|
||||
}
|
||||
|
||||
if (replyToTopMsg != null) {
|
||||
newMsg.reply_to = new TLRPC.TL_messageReplyHeader();
|
||||
newMsg.reply_to.reply_to_msg_id = replyToTopMsg.getId();
|
||||
if (replyToTopMsg.isTopicMainMessage) {
|
||||
newMsg.reply_to.forum_topic = true;
|
||||
newMsg.reply_to.flags |= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (arr.size() == 100 || a == messages.size() - 1 || a != messages.size() - 1 && messages.get(a + 1).getDialogId() != msgObj.getDialogId()) {
|
||||
getMessagesStorage().putMessages(new ArrayList<>(arr), false, true, false, 0, scheduleDate != 0);
|
||||
getMessagesStorage().putMessages(new ArrayList<>(arr), false, true, false, 0, scheduleDate != 0, 0);
|
||||
getMessagesController().updateInterfaceWithMessages(peer, objArr, scheduleDate != 0);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
getUserConfig().saveConfig(false);
|
||||
|
@ -1999,6 +2014,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
final TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages();
|
||||
req.to_peer = inputPeer;
|
||||
req.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
if (replyToTopMsg != null) {
|
||||
req.top_msg_id = replyToTopMsg.getId();
|
||||
req.flags |= 512;
|
||||
}
|
||||
if (scheduleDate != 0) {
|
||||
req.schedule_date = scheduleDate;
|
||||
req.flags |= 1024;
|
||||
|
@ -2108,7 +2127,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
messageIds.add(oldId);
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj1.dialog_id, false, true);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
messageObjects.add(new MessageObject(msgObj.currentAccount, msgObj.messageOwner, true, true));
|
||||
|
@ -2122,7 +2141,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().updateMessageStateAndId(newMsgObj1.random_id, MessageObject.getPeerId(peer_id), oldId, newMsgObj1.id, 0, false, scheduleDate != 0 ? 1 : 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduleDate != 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduleDate != 0, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
|
||||
getMediaDataController().increasePeerRaiting(peer);
|
||||
|
@ -2316,7 +2335,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
newMsg.attachPath = "";
|
||||
}
|
||||
newMsg.local_id = 0;
|
||||
if ((messageObject.type == 3 || videoEditedInfo != null || messageObject.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||
if ((messageObject.type == MessageObject.TYPE_VIDEO || videoEditedInfo != null || messageObject.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||
messageObject.attachPathExists = true;
|
||||
}
|
||||
if (messageObject.videoEditedInfo != null && videoEditedInfo == null) {
|
||||
|
@ -2355,7 +2374,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(newMsg);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, messageObject.scheduled);
|
||||
getMessagesStorage().putMessages(arr, false, true, false, 0, messageObject.scheduled, MessageObject.getTopicId(newMsg));
|
||||
getMessagesController().getTopicsController().processEditedMessage(newMsg);
|
||||
|
||||
messageObject.type = -1;
|
||||
messageObject.setType();
|
||||
|
@ -2653,6 +2673,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
final String key = dialogId + "_" + msgId + "_" + Utilities.bytesToHex(data) + "_" + 0;
|
||||
waitingForCallback.put(key, true);
|
||||
|
||||
List<String> keys = waitingForCallbackMap.get(dialogId + "_" + msgId);
|
||||
if (keys == null) {
|
||||
waitingForCallbackMap.put(dialogId + "_" + msgId, keys = new ArrayList<>());
|
||||
}
|
||||
keys.add(key);
|
||||
|
||||
if (DialogObject.isUserDialog(dialogId)) {
|
||||
TLRPC.User user = getMessagesController().getUser(dialogId);
|
||||
if (user == null) {
|
||||
|
@ -2679,11 +2705,26 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
req.flags |= 1;
|
||||
req.data = data;
|
||||
}
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> waitingForCallback.remove(key)), ConnectionsManager.RequestFlagFailOnServerErrors);
|
||||
List<String> finalKeys = keys;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
waitingForCallback.remove(key);
|
||||
finalKeys.remove(key);
|
||||
}), ConnectionsManager.RequestFlagFailOnServerErrors);
|
||||
getMessagesController().markDialogAsRead(dialogId, msgId, msgId, 0, false, 0, 0, true, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public void onMessageEdited(TLRPC.Message message) {
|
||||
if (message != null && message.reply_markup != null) {
|
||||
List<String> keys = waitingForCallbackMap.remove(message.dialog_id + "_" + message.id);
|
||||
if (keys != null) {
|
||||
for (String key : keys) {
|
||||
waitingForCallback.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] isSendingVote(MessageObject messageObject) {
|
||||
if (messageObject == null) {
|
||||
return null;
|
||||
|
@ -2828,9 +2869,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
final String key = messageObject.getDialogId() + "_" + messageObject.getId() + "_" + Utilities.bytesToHex(button.data) + "_" + type;
|
||||
waitingForCallback.put(key, true);
|
||||
|
||||
List<String> keys = waitingForCallbackMap.get(messageObject.getDialogId() + "_" + messageObject.getId());
|
||||
if (keys == null) {
|
||||
waitingForCallbackMap.put(messageObject.getDialogId() + "_" + messageObject.getId(), keys = new ArrayList<>());
|
||||
}
|
||||
keys.add(key);
|
||||
|
||||
TLObject[] request = new TLObject[1];
|
||||
List<String> finalKeys = keys;
|
||||
RequestDelegate requestDelegate = (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
waitingForCallback.remove(key);
|
||||
finalKeys.remove(key);
|
||||
if (cacheFinal && response == null) {
|
||||
sendCallback(false, messageObject, button, parentFragment);
|
||||
} else if (response != null) {
|
||||
|
@ -3245,29 +3294,33 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
type = 11;
|
||||
message = retryMessageObject.getDiceEmoji();
|
||||
caption = "";
|
||||
} else if (retryMessageObject.type == 0 || retryMessageObject.isAnimatedEmoji()) {
|
||||
} else if (retryMessageObject.type == MessageObject.TYPE_TEXT || retryMessageObject.isAnimatedEmoji()) {
|
||||
if (retryMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
|
||||
//game = retryMessageObject.messageOwner.media.game;
|
||||
} else {
|
||||
message = newMsg.message;
|
||||
}
|
||||
type = 0;
|
||||
} else if (retryMessageObject.type == 4) {
|
||||
} else if (retryMessageObject.type == MessageObject.TYPE_GEO) {
|
||||
location = newMsg.media;
|
||||
type = 1;
|
||||
} else if (retryMessageObject.type == 1) {
|
||||
} else if (retryMessageObject.type == MessageObject.TYPE_PHOTO) {
|
||||
photo = (TLRPC.TL_photo) newMsg.media.photo;
|
||||
if (retryMessageObject.messageOwner.message != null) {
|
||||
caption = retryMessageObject.messageOwner.message;
|
||||
}
|
||||
type = 2;
|
||||
} else if (retryMessageObject.type == 3 || retryMessageObject.type == 5 || retryMessageObject.videoEditedInfo != null) {
|
||||
} else if (
|
||||
retryMessageObject.type == MessageObject.TYPE_VIDEO ||
|
||||
retryMessageObject.type == MessageObject.TYPE_ROUND_VIDEO ||
|
||||
retryMessageObject.videoEditedInfo != null
|
||||
) {
|
||||
type = 3;
|
||||
document = (TLRPC.TL_document) newMsg.media.document;
|
||||
if (retryMessageObject.messageOwner.message != null) {
|
||||
caption = retryMessageObject.messageOwner.message;
|
||||
}
|
||||
} else if (retryMessageObject.type == 12) {
|
||||
} else if (retryMessageObject.type == MessageObject.TYPE_CONTACT) {
|
||||
user = new TLRPC.TL_userRequest_old2();
|
||||
user.phone = newMsg.media.phone_number;
|
||||
user.first_name = newMsg.media.first_name;
|
||||
|
@ -3279,7 +3332,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
user.restriction_reason.add(reason);
|
||||
user.id = newMsg.media.user_id;
|
||||
type = 6;
|
||||
} else if (retryMessageObject.type == 8 || retryMessageObject.type == 9 || retryMessageObject.type == MessageObject.TYPE_STICKER || retryMessageObject.type == 14 || retryMessageObject.type == MessageObject.TYPE_ANIMATED_STICKER) {
|
||||
} else if (
|
||||
retryMessageObject.type == MessageObject.TYPE_GIF ||
|
||||
retryMessageObject.type == MessageObject.TYPE_FILE ||
|
||||
retryMessageObject.type == MessageObject.TYPE_STICKER ||
|
||||
retryMessageObject.type == MessageObject.TYPE_MUSIC ||
|
||||
retryMessageObject.type == MessageObject.TYPE_ANIMATED_STICKER
|
||||
) {
|
||||
document = (TLRPC.TL_document) newMsg.media.document;
|
||||
type = 7;
|
||||
if (retryMessageObject.messageOwner.message != null) {
|
||||
|
@ -3595,6 +3654,15 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
if (replyToTopMsg != null && replyToTopMsg != replyToMsg) {
|
||||
newMsg.reply_to.reply_to_top_id = replyToTopMsg.getId();
|
||||
newMsg.reply_to.flags |= 2;
|
||||
if (replyToTopMsg.isTopicMainMessage) {
|
||||
newMsg.reply_to.forum_topic = true;
|
||||
newMsg.reply_to.flags |= 8;
|
||||
}
|
||||
} else {
|
||||
if (replyToMsg.isTopicMainMessage) {
|
||||
newMsg.reply_to.forum_topic = true;
|
||||
newMsg.reply_to.flags |= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (linkedToGroup != 0) {
|
||||
|
@ -3690,7 +3758,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
newMsgObj.sendAnimationData = sendAnimationData;
|
||||
newMsgObj.wasJustSent = true;
|
||||
newMsgObj.scheduled = scheduleDate != 0;
|
||||
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||
if (!newMsgObj.isForwarded() && (newMsgObj.type == MessageObject.TYPE_VIDEO || videoEditedInfo != null || newMsgObj.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||
newMsgObj.attachPathExists = true;
|
||||
}
|
||||
if (newMsgObj.videoEditedInfo != null && videoEditedInfo == null) {
|
||||
|
@ -3702,7 +3770,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
objArr.add(newMsgObj);
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<>();
|
||||
arr.add(newMsg);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(arr, false, true, false, 0, scheduleDate != 0);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(arr, false, true, false, 0, scheduleDate != 0, 0);
|
||||
MessagesController.getInstance(currentAccount).updateInterfaceWithMessages(peer, objArr, scheduleDate != 0);
|
||||
if (scheduleDate == 0) {
|
||||
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
|
@ -3744,6 +3812,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
reqSend.silent = newMsg.silent;
|
||||
reqSend.peer = sendToPeer;
|
||||
reqSend.random_id = newMsg.random_id;
|
||||
if (replyToTopMsg != null) {
|
||||
reqSend.top_msg_id = replyToTopMsg.getId();
|
||||
reqSend.flags |= 512;
|
||||
}
|
||||
if (updateStickersOreder) {
|
||||
reqSend.update_stickersets_order = true;
|
||||
}
|
||||
|
@ -4072,6 +4144,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
request = new TLRPC.TL_messages_sendMultiMedia();
|
||||
request.peer = sendToPeer;
|
||||
request.silent = newMsg.silent;
|
||||
if (replyToTopMsg != null) {
|
||||
request.top_msg_id = replyToTopMsg.getId();
|
||||
request.flags |= 512;
|
||||
}
|
||||
if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) {
|
||||
request.flags |= 1;
|
||||
request.reply_to_msg_id = newMsg.reply_to.reply_to_msg_id;
|
||||
|
@ -4104,6 +4180,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
||||
request.peer = sendToPeer;
|
||||
request.silent = newMsg.silent;
|
||||
if (replyToTopMsg != null) {
|
||||
request.top_msg_id = replyToTopMsg.getId();
|
||||
request.flags |= 512;
|
||||
}
|
||||
if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) {
|
||||
request.flags |= 1;
|
||||
request.reply_to_msg_id = newMsg.reply_to.reply_to_msg_id;
|
||||
|
@ -4463,6 +4543,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_forwardMessages reqSend = new TLRPC.TL_messages_forwardMessages();
|
||||
reqSend.to_peer = sendToPeer;
|
||||
reqSend.with_my_score = retryMessageObject.messageOwner.with_my_score;
|
||||
if (replyToTopMsg != null) {
|
||||
reqSend.top_msg_id = replyToTopMsg.getId();
|
||||
reqSend.flags |= 512;
|
||||
}
|
||||
if (params != null && params.containsKey("fwd_id")) {
|
||||
int fwdId = Utilities.parseInt(params.get("fwd_id"));
|
||||
reqSend.drop_author = true;
|
||||
|
@ -4503,6 +4587,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_sendInlineBotResult reqSend = new TLRPC.TL_messages_sendInlineBotResult();
|
||||
reqSend.peer = sendToPeer;
|
||||
reqSend.random_id = newMsg.random_id;
|
||||
if (replyToTopMsg != null) {
|
||||
reqSend.top_msg_id = replyToTopMsg.getId();
|
||||
reqSend.flags |= 512;
|
||||
}
|
||||
if (newMsg.from_id != null) {
|
||||
reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id);
|
||||
}
|
||||
|
@ -4943,7 +5031,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
return;
|
||||
} else if (add) {
|
||||
delayedMessages.remove(key);
|
||||
getMessagesStorage().putMessages(message.messages, false, true, false, 0, message.scheduled);
|
||||
getMessagesStorage().putMessages(message.messages, false, true, false, 0, message.scheduled, 0);
|
||||
getMessagesController().updateInterfaceWithMessages(message.peer, message.messageObjects, message.scheduled);
|
||||
if (!message.scheduled) {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
|
@ -5279,7 +5367,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, MessageObject.getPeerId(newMsgObj.peer_id), oldId, newMsgObj.id, 0, false, scheduled ? 1 : 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled);
|
||||
|
@ -5573,7 +5661,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
messageIds.add(oldId);
|
||||
getMessagesController().deleteMessages(messageIds, null, null, newMsgObj.dialog_id, false, true);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, false, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||
messageObjects.add(new MessageObject(msgObj.currentAccount, msgObj.messageOwner, true, true));
|
||||
|
@ -5590,7 +5678,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, MessageObject.getPeerId(newMsgObj.peer_id), oldId, newMsgObj.id, 0, false, scheduled ? 1 : 0);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled);
|
||||
getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled, 0);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled);
|
||||
|
@ -6525,7 +6613,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(prevMessage.messageOwner);
|
||||
accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduleDate != 0);
|
||||
accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduleDate != 0, 0);
|
||||
instance.sendReadyToSendGroup(message, true, true);
|
||||
}
|
||||
});
|
||||
|
@ -7482,11 +7570,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
if (thumb != null) {
|
||||
int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight());
|
||||
size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted);
|
||||
thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false);
|
||||
if (size != null && size.location != null) {
|
||||
thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false);
|
||||
|
||||
String fileName = size.location.volume_id + "_" + size.location.local_id + ".jpg";
|
||||
File fileDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE);
|
||||
localPath = new File(fileDir, fileName).getAbsolutePath();
|
||||
String fileName = size.location.volume_id + "_" + size.location.local_id + ".jpg";
|
||||
File fileDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE);
|
||||
localPath = new File(fileDir, fileName).getAbsolutePath();
|
||||
}
|
||||
}
|
||||
document = new TLRPC.TL_document();
|
||||
document.file_reference = new byte[0];
|
||||
|
|
|
@ -97,6 +97,7 @@ public class SharedConfig {
|
|||
public static boolean stickersReorderingHintUsed;
|
||||
public static boolean disableVoiceAudioEffects;
|
||||
public static boolean forceDisableTabletMode;
|
||||
public static boolean useLNavigation;
|
||||
private static int lastLocalId = -210000;
|
||||
|
||||
public static String storageCacheDir;
|
||||
|
@ -168,6 +169,8 @@ public class SharedConfig {
|
|||
public static int fastScrollHintCount = 3;
|
||||
public static boolean dontAskManageStorage;
|
||||
|
||||
public static boolean isFloatingDebugActive;
|
||||
|
||||
static {
|
||||
loadConfig();
|
||||
}
|
||||
|
@ -243,7 +246,6 @@ public class SharedConfig {
|
|||
editor.putBoolean("forwardingOptionsHintShown", forwardingOptionsHintShown);
|
||||
editor.putInt("lockRecordAudioVideoHint", lockRecordAudioVideoHint);
|
||||
editor.putString("storageCacheDir", !TextUtils.isEmpty(storageCacheDir) ? storageCacheDir : "");
|
||||
editor.putBoolean("hasEmailLogin", hasEmailLogin);
|
||||
|
||||
if (pendingAppUpdate != null) {
|
||||
try {
|
||||
|
@ -262,6 +264,12 @@ public class SharedConfig {
|
|||
editor.putLong("appUpdateCheckTime", lastUpdateCheckTime);
|
||||
|
||||
editor.apply();
|
||||
|
||||
editor = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Context.MODE_PRIVATE).edit();
|
||||
editor.putBoolean("hasEmailLogin", hasEmailLogin);
|
||||
editor.putBoolean("useLNavigation", useLNavigation);
|
||||
editor.putBoolean("floatingDebugActive", isFloatingDebugActive);
|
||||
editor.apply();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
|
@ -426,6 +434,8 @@ public class SharedConfig {
|
|||
fastScrollHintCount = preferences.getInt("fastScrollHintCount", 3);
|
||||
dontAskManageStorage = preferences.getBoolean("dontAskManageStorage", false);
|
||||
hasEmailLogin = preferences.getBoolean("hasEmailLogin", false);
|
||||
useLNavigation = preferences.getBoolean("useLNavigation", BuildVars.DEBUG_VERSION);
|
||||
isFloatingDebugActive = preferences.getBoolean("floatingDebugActive", false);
|
||||
|
||||
preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
|
||||
|
@ -444,7 +454,7 @@ public class SharedConfig {
|
|||
|
||||
public static void updateTabletConfig() {
|
||||
if (fontSizeIsDefault) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
||||
ivFontSize = preferences.getInt("iv_font_size", fontSize);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import android.graphics.RectF;
|
|||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.xml.sax.Attributes;
|
||||
|
@ -122,6 +123,7 @@ public class SvgHelper {
|
|||
private Theme.ResourcesProvider currentResourcesProvider;
|
||||
private float colorAlpha;
|
||||
private float crossfadeAlpha = 1.0f;
|
||||
SparseArray<Paint> overridePaintByPosition = new SparseArray<>();
|
||||
|
||||
private boolean aspectFill = true;
|
||||
|
||||
|
@ -225,11 +227,15 @@ public class SvgHelper {
|
|||
Object object = commands.get(a);
|
||||
if (object instanceof Matrix) {
|
||||
canvas.save();
|
||||
// canvas.concat((Matrix) object);
|
||||
canvas.concat((Matrix) object);
|
||||
} else if (object == null) {
|
||||
canvas.restore();
|
||||
} else {
|
||||
Paint paint;
|
||||
Paint overridePaint = overridePaintByPosition.get(a);
|
||||
if (overridePaint == null) {
|
||||
overridePaint = this.overridePaint;
|
||||
}
|
||||
if (drawInBackground) {
|
||||
paint = backgroundPaint;
|
||||
} else if (overridePaint != null) {
|
||||
|
@ -352,6 +358,14 @@ public class SvgHelper {
|
|||
public void setPaint(Paint paint) {
|
||||
overridePaint = paint;
|
||||
}
|
||||
|
||||
public void setPaint(Paint paint, int position) {
|
||||
overridePaintByPosition.put(position, paint);
|
||||
}
|
||||
|
||||
public void copyCommandFromPosition(int position) {
|
||||
commands.add(commands.get(position));
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap getBitmap(int res, int width, int height, int color) {
|
||||
|
|
|
@ -0,0 +1,886 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import org.telegram.SQLite.SQLiteCursor;
|
||||
import org.telegram.messenger.support.LongSparseIntArray;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.NativeByteBuffer;
|
||||
import org.telegram.tgnet.RequestDelegate;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TopicsController extends BaseController {
|
||||
|
||||
public static final int TOPIC_FLAG_TITLE = 1;
|
||||
public static final int TOPIC_FLAG_ICON = 2;
|
||||
public static final int TOPIC_FLAG_PIN = 4;
|
||||
public static final int TOPIC_FLAG_CLOSE = 8;
|
||||
|
||||
|
||||
private static final int MAX_PRELOAD_COUNT = 20;
|
||||
|
||||
public static final int LOAD_TYPE_PRELOAD = 0;
|
||||
public static final int LOAD_TYPE_LOAD_NEXT = 1;
|
||||
public static final int LOAD_TYPE_LOAD_UNKNOWN = 2;
|
||||
|
||||
LongSparseArray<ArrayList<TLRPC.TL_forumTopic>> topicsByChatId = new LongSparseArray<>();
|
||||
LongSparseArray<LongSparseArray<TLRPC.TL_forumTopic>> topicsMapByChatId = new LongSparseArray<>();
|
||||
LongSparseIntArray topicsIsLoading = new LongSparseIntArray();
|
||||
LongSparseIntArray endIsReached = new LongSparseIntArray();
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsByTopMsgId = new LongSparseArray<>();
|
||||
|
||||
LongSparseIntArray currentOpenTopicsCounter = new LongSparseIntArray();
|
||||
LongSparseIntArray openedTopicsBuChatId = new LongSparseIntArray();
|
||||
|
||||
public TopicsController(int num) {
|
||||
super(num);
|
||||
}
|
||||
|
||||
public void preloadTopics(long chatId) {
|
||||
loadTopics(chatId, true, LOAD_TYPE_PRELOAD);
|
||||
}
|
||||
|
||||
|
||||
public void loadTopics(long chatId) {
|
||||
loadTopics(chatId, false, LOAD_TYPE_LOAD_NEXT);
|
||||
}
|
||||
|
||||
private void loadTopics(long chatId, boolean fromCache, int loadType) {
|
||||
if (topicsIsLoading.get(chatId, 0) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
||||
FileLog.d("load topics " + chatId + " fromCache=" + fromCache + " loadType=" + loadType);
|
||||
}
|
||||
if (fromCache) {
|
||||
getMessagesStorage().loadTopics(-chatId, topics -> {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
||||
FileLog.d("loaded from cache " + chatId + " topics_count=" + (topics == null ? 0 : topics.size()));
|
||||
}
|
||||
|
||||
topicsIsLoading.put(chatId, 0);
|
||||
processTopics(chatId, topics, null, fromCache, loadType, -1);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
topicsIsLoading.put(chatId, 1);
|
||||
TLRPC.TL_channels_getForumTopics getForumTopics = new TLRPC.TL_channels_getForumTopics();
|
||||
getForumTopics.channel = getMessagesController().getInputChannel(chatId);
|
||||
if (loadType == LOAD_TYPE_PRELOAD) {
|
||||
getForumTopics.limit = MAX_PRELOAD_COUNT;
|
||||
} else if (loadType == LOAD_TYPE_LOAD_NEXT) {
|
||||
getForumTopics.limit = 100;
|
||||
TopicsLoadOffset loadOffsets = getLoadOffset(chatId);
|
||||
getForumTopics.offset_date = loadOffsets.lastMessageDate;
|
||||
getForumTopics.offset_id = loadOffsets.lastMessageId;
|
||||
getForumTopics.offset_topic = loadOffsets.lastTopicId;
|
||||
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
||||
FileLog.d("offset_date=" + loadOffsets.lastMessageDate + " offset_id=" + loadOffsets.lastMessageId + " offset_topic=" + loadOffsets.lastTopicId);
|
||||
}
|
||||
}
|
||||
|
||||
getConnectionsManager().sendRequest(getForumTopics, (response, error) -> {
|
||||
if (response != null) {
|
||||
SparseArray<TLRPC.Message> messagesMap = new SparseArray<>();
|
||||
TLRPC.TL_messages_forumTopics topics = (TLRPC.TL_messages_forumTopics) response;
|
||||
for (int i = 0; i < topics.messages.size(); i++) {
|
||||
messagesMap.put(topics.messages.get(i).id, topics.messages.get(i));
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getMessagesController().putUsers(((TLRPC.TL_messages_forumTopics) response).users, false);
|
||||
getMessagesController().putChats(((TLRPC.TL_messages_forumTopics) response).chats, false);
|
||||
|
||||
topicsIsLoading.put(chatId, 0);
|
||||
processTopics(chatId, topics.topics, messagesMap, false, loadType, ((TLRPC.TL_messages_forumTopics) response).count);
|
||||
getMessagesStorage().putMessages(topics.messages, false, true, false, 0, false, 0);
|
||||
|
||||
getMessagesStorage().saveTopics(-chatId, topicsByChatId.get(chatId), true, true);
|
||||
|
||||
if (!topics.topics.isEmpty() && loadType == LOAD_TYPE_LOAD_NEXT) {
|
||||
TLRPC.TL_forumTopic lastTopic = topics.topics.get(topics.topics.size() - 1);
|
||||
TLRPC.Message lastTopicMessage = messagesMap.get(lastTopic.top_message);
|
||||
saveLoadOffset(chatId, lastTopic.top_message, lastTopicMessage.date, lastTopic.id);
|
||||
} else if (getTopics(chatId) == null || getTopics(chatId).size() < topics.count) {
|
||||
clearLoadingOffset(chatId);
|
||||
loadTopics(chatId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
topicsIsLoading.put(chatId, 0);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.topicsDidLoaded, chatId, false);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void processTopics(long chatId, ArrayList<TLRPC.TL_forumTopic> newTopics, SparseArray<TLRPC.Message> messagesMap, boolean fromCache, int loadType, int totalCount) {
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
|
||||
ArrayList<TLRPC.TL_forumTopic> topicsToReload = null;
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
|
||||
|
||||
if (topics == null) {
|
||||
topics = new ArrayList<>();
|
||||
topicsByChatId.put(chatId, topics);
|
||||
|
||||
}
|
||||
if (topicsMap == null) {
|
||||
topicsMap = new LongSparseArray<>();
|
||||
topicsMapByChatId.put(chatId, topicsMap);
|
||||
}
|
||||
boolean changed = false;
|
||||
if (newTopics != null) {
|
||||
for (int i = 0; i < newTopics.size(); i++) {
|
||||
TLRPC.TL_forumTopic newTopic = newTopics.get(i);
|
||||
if (!topicsMap.containsKey(newTopic.id)) {
|
||||
if (messagesMap != null) {
|
||||
newTopic.topMessage = messagesMap.get(newTopic.top_message);
|
||||
newTopic.topicStartMessage = messagesMap.get(newTopic.id);
|
||||
}
|
||||
if (newTopic.topMessage == null) {
|
||||
if (topicsToReload == null) {
|
||||
topicsToReload = new ArrayList<>();
|
||||
}
|
||||
topicsToReload.add(newTopic);
|
||||
} else {
|
||||
if (newTopic.topicStartMessage == null) {
|
||||
newTopic.topicStartMessage = new TLRPC.TL_message();
|
||||
newTopic.topicStartMessage.message = "";
|
||||
newTopic.topicStartMessage.id = newTopic.id;
|
||||
newTopic.topicStartMessage.peer_id = getMessagesController().getPeer(-chatId);
|
||||
newTopic.topicStartMessage.action = new TLRPC.TL_messageActionTopicCreate();
|
||||
newTopic.topicStartMessage.action.title = newTopic.title;
|
||||
}
|
||||
topics.add(newTopic);
|
||||
topicsMap.put(newTopic.id, newTopic);
|
||||
topicsByTopMsgId.put(messageHash(newTopic.top_message, chatId), newTopic);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
sortTopics(chatId);
|
||||
}
|
||||
|
||||
if (topicsToReload != null) {
|
||||
reloadTopics(chatId, topicsToReload);
|
||||
} else if (loadType == LOAD_TYPE_LOAD_NEXT && topics.size() >= totalCount && totalCount >= 0) {
|
||||
endIsReached.put(chatId, 1);
|
||||
}
|
||||
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.topicsDidLoaded, chatId, true);
|
||||
|
||||
if ((loadType == LOAD_TYPE_PRELOAD || (loadType == LOAD_TYPE_PRELOAD && !fromCache)) && fromCache && topicsByChatId.get(chatId).isEmpty()) {
|
||||
loadTopics(chatId, false, LOAD_TYPE_PRELOAD);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDialogUnreadCount(long chatId) {
|
||||
int[] counters = getForumUnreadCount(chatId);
|
||||
int unread = counters[0];
|
||||
int unread_mentions = counters[1];
|
||||
// getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
// SQLiteDatabase database = getMessagesStorage().getDatabase();
|
||||
// try {
|
||||
// SQLiteCursor cursor = database.queryFinalized("SELECT unread_count, unread_count_i FROM dialogs WHERE did = " + (-chatId));
|
||||
// boolean needUpdate = false;
|
||||
// if (cursor.next()) {
|
||||
// int currentUnreadCount = cursor.intValue(0);
|
||||
// int currentUnreadMentions = cursor.intValue(1);
|
||||
// if ((unread > 0) != (currentUnreadCount > 0) || (unread_mentions > 0) != (currentUnreadMentions > 0)) {
|
||||
// needUpdate = true;
|
||||
// }
|
||||
// Log.d("kek", "update dialog read by topics " + chatId + " " + unread + " " + unread_mentions + " current " + currentUnreadCount + " " + currentUnreadMentions + " update " + needUpdate);
|
||||
// }
|
||||
// cursor.dispose();
|
||||
// if (needUpdate) {
|
||||
// database.executeFast(String.format(Locale.US, "UPDATE dialogs SET unread_count = %d, unread_count_i - %d WHERE did = %d", unread, unread_mentions, -chatId)).stepThis().dispose();
|
||||
// SQLiteCursor cursor2 = database.queryFinalized("SELECT unread_count, unread_count_i FROM dialogs WHERE did = " + (-chatId));
|
||||
// if (cursor2.next()) {
|
||||
// int currentUnreadCount = cursor2.intValue(0);
|
||||
// Log.d("kek", "currentUnreadCount " + currentUnreadCount);
|
||||
// }
|
||||
// cursor2.dispose();
|
||||
// getMessagesStorage().resetAllUnreadCounters(false);
|
||||
// }
|
||||
// } catch (Throwable e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
private long messageHash(int messageId, long chatId) {
|
||||
return chatId + ((long) messageId << 12);
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<TLRPC.TL_forumTopic> getTopics(long chatId) {
|
||||
return topicsByChatId.get(chatId);
|
||||
}
|
||||
|
||||
private void sortTopics(long chatId) {
|
||||
sortTopics(chatId, true);
|
||||
}
|
||||
|
||||
private void sortTopics(long chatId, boolean notify) {
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
|
||||
if (topics != null) {
|
||||
if (openedTopicsBuChatId.get(chatId, 0) > 0) {
|
||||
Collections.sort(topics, Comparator.comparingInt(o -> o.pinned ? -1 : -o.topMessage.date));
|
||||
}
|
||||
if (notify) {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.topicsDidLoaded, chatId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTopicsWithDeletedMessages(long dialogId, ArrayList<Integer> messages) {
|
||||
if (dialogId > 0) {
|
||||
return;
|
||||
}
|
||||
long chatId = -dialogId;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
ArrayList<TLRPC.TL_forumTopic> topicsToUpdate = null;
|
||||
try {
|
||||
SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT topic_id, top_message FROM topics WHERE did = %d AND top_message IN (%s)", dialogId, TextUtils.join(",", messages)));
|
||||
while (cursor.next()) {
|
||||
if (topicsToUpdate == null) {
|
||||
topicsToUpdate = new ArrayList<>();
|
||||
}
|
||||
|
||||
TLRPC.TL_forumTopic topic = new TLRPC.TL_forumTopic();
|
||||
topic.id = cursor.intValue(0);
|
||||
topic.top_message = cursor.intValue(1);
|
||||
topic.from_id = getMessagesController().getPeer(getUserConfig().clientUserId);
|
||||
topic.notify_settings = new TLRPC.TL_peerNotifySettings();
|
||||
topicsToUpdate.add(topic);
|
||||
}
|
||||
cursor.dispose();
|
||||
|
||||
if (topicsToUpdate != null) {
|
||||
for (int i = 0; i < topicsToUpdate.size(); i++) {
|
||||
TLRPC.TL_forumTopic topic = topicsToUpdate.get(i);
|
||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid, data FROM messages_topics WHERE uid = %d AND topic_id = %d ORDER BY mid DESC LIMIT 1", dialogId, topic.id));
|
||||
|
||||
if (cursor.next()) {
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
if (data != null) {
|
||||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||
data.reuse();
|
||||
topicsByTopMsgId.remove(messageHash(topic.top_message, chatId));
|
||||
topic.top_message = message.id;
|
||||
topic.topMessage = message;
|
||||
topic.groupedMessages = null;
|
||||
topicsByTopMsgId.put(messageHash(topic.top_message, chatId), topic);
|
||||
}
|
||||
}
|
||||
cursor.dispose();
|
||||
}
|
||||
|
||||
for (int i = 0; i < topicsToUpdate.size(); i++) {
|
||||
getMessagesStorage().getDatabase().executeFast(String.format(Locale.US, "UPDATE topics SET top_message = %d WHERE did = %d AND topic_id = %d", topicsToUpdate.get(i).top_message, dialogId, topicsToUpdate.get(i).id)).stepThis().dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ArrayList<TLRPC.TL_forumTopic> finalTopicsToUpdate = topicsToUpdate;
|
||||
getMessagesStorage().loadGroupedMessagesForTopics(dialogId, finalTopicsToUpdate);
|
||||
if (finalTopicsToUpdate != null) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
boolean changed = false;
|
||||
ArrayList<TLRPC.TL_forumTopic> topicsToReload = null;
|
||||
|
||||
for (int i = 0; i < finalTopicsToUpdate.size(); i++) {
|
||||
TLRPC.TL_forumTopic fromUpdate = finalTopicsToUpdate.get(i);
|
||||
LongSparseArray<TLRPC.TL_forumTopic> map = topicsMapByChatId.get(chatId);
|
||||
TLRPC.TL_forumTopic toUpdate;
|
||||
if (map != null) {
|
||||
toUpdate = map.get(fromUpdate.id);
|
||||
if (toUpdate != null && fromUpdate.top_message != -1 && fromUpdate.topMessage != null) {
|
||||
topicsByTopMsgId.remove(messageHash(toUpdate.top_message, chatId));
|
||||
toUpdate.top_message = fromUpdate.topMessage.id;
|
||||
toUpdate.topMessage = fromUpdate.topMessage;
|
||||
toUpdate.groupedMessages = fromUpdate.groupedMessages;
|
||||
|
||||
topicsByTopMsgId.put(messageHash(toUpdate.top_message, chatId), toUpdate);
|
||||
changed = true;
|
||||
} else if (fromUpdate.top_message == -1 || fromUpdate.topMessage == null) {
|
||||
if (topicsToReload == null) {
|
||||
topicsToReload = new ArrayList<>();
|
||||
}
|
||||
topicsToReload.add(fromUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
sortTopics(chatId);
|
||||
}
|
||||
if (topicsToReload != null) {
|
||||
reloadTopics(chatId, topicsToReload);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void reloadTopics(long chatId, ArrayList<TLRPC.TL_forumTopic> topicsToReload) {
|
||||
TLRPC.TL_channels_getForumTopicsByID req = new TLRPC.TL_channels_getForumTopicsByID();
|
||||
for (int i = 0; i < topicsToReload.size(); i++) {
|
||||
req.topics.add(topicsToReload.get(i).id);
|
||||
}
|
||||
req.channel = getMessagesController().getInputChannel(chatId);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response != null) {
|
||||
SparseArray<TLRPC.Message> messagesMap = new SparseArray<>();
|
||||
TLRPC.TL_messages_forumTopics topics = (TLRPC.TL_messages_forumTopics) response;
|
||||
for (int i = 0; i < topics.messages.size(); i++) {
|
||||
messagesMap.put(topics.messages.get(i).id, topics.messages.get(i));
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getMessagesController().putUsers(((TLRPC.TL_messages_forumTopics) response).users, false);
|
||||
getMessagesController().putChats(((TLRPC.TL_messages_forumTopics) response).chats, false);
|
||||
|
||||
processTopics(chatId, topics.topics, messagesMap, false, LOAD_TYPE_LOAD_UNKNOWN, -1);
|
||||
getMessagesStorage().putMessages(topics.messages, false, true, false, 0, false, 0);
|
||||
getMessagesStorage().saveTopics(-chatId, topicsByChatId.get(chatId), true, true);
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void updateMaxReadId(long chatId, int topicId, int readMaxId, int unreadCount) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(chatId, topicId);
|
||||
if (topic != null) {
|
||||
topic.read_inbox_max_id = readMaxId;
|
||||
topic.unread_count = unreadCount;
|
||||
sortTopics(chatId);
|
||||
}
|
||||
}
|
||||
|
||||
public TLRPC.TL_forumTopic findTopic(long chatId, int topicId) {
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
|
||||
if (topicsMap != null) {
|
||||
return topicsMap.get(topicId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getTopicName(TLRPC.Chat chat, MessageObject message) {
|
||||
if (message.messageOwner.reply_to == null) {
|
||||
return null;
|
||||
}
|
||||
int topicId = message.messageOwner.reply_to.reply_to_top_id;
|
||||
if (topicId == 0) {
|
||||
topicId = message.messageOwner.reply_to.reply_to_msg_id;
|
||||
}
|
||||
if (topicId != 0) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(chat.id, topicId);
|
||||
if (topic != null) {
|
||||
return topic.title;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public CharSequence getTopicIconName(TLRPC.Chat chat, MessageObject message, TextPaint paint) {
|
||||
if (message.messageOwner.reply_to == null) {
|
||||
return null;
|
||||
}
|
||||
int topicId = message.messageOwner.reply_to.reply_to_top_id;
|
||||
if (topicId == 0) {
|
||||
topicId = message.messageOwner.reply_to.reply_to_msg_id;
|
||||
}
|
||||
if (topicId != 0) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(chat.id, topicId);
|
||||
if (topic != null) {
|
||||
return ForumUtilities.getTopicSpannedName(topic, paint);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final static int[] countsTmp = new int[4];
|
||||
|
||||
public int[] getForumUnreadCount(long chatId) {
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
|
||||
Arrays.fill(countsTmp, 0);
|
||||
if (topics != null) {
|
||||
for (int i = 0; i < topics.size(); i++) {
|
||||
TLRPC.TL_forumTopic topic = topics.get(i);
|
||||
countsTmp[0] += topic.unread_count > 0 ? 1 : 0;
|
||||
countsTmp[1] += topic.unread_mentions_count > 0 ? 1 : 0;
|
||||
countsTmp[2] += topic.unread_reactions_count > 0 ? 1 : 0;
|
||||
if (!getMessagesController().isDialogMuted(-chatId, topic.id)) {
|
||||
countsTmp[3] += topic.unread_count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return countsTmp;
|
||||
}
|
||||
|
||||
public void onTopicCreated(long dialogId, TLRPC.TL_forumTopic forumTopic, boolean saveInDatabase) {
|
||||
LongSparseArray<TLRPC.TL_forumTopic> map = topicsMapByChatId.get(-dialogId);
|
||||
if (findTopic(-dialogId, forumTopic.id) != null) {
|
||||
return;
|
||||
}
|
||||
if (map == null) {
|
||||
map = new LongSparseArray<>();
|
||||
topicsMapByChatId.put(-dialogId, map);
|
||||
}
|
||||
ArrayList<TLRPC.TL_forumTopic> list = topicsByChatId.get(-dialogId);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
topicsByChatId.put(-dialogId, list);
|
||||
}
|
||||
map.put(forumTopic.id, forumTopic);
|
||||
list.add(forumTopic);
|
||||
if (saveInDatabase) {
|
||||
getMessagesStorage().saveTopics(dialogId, Collections.singletonList(forumTopic), false, true);
|
||||
}
|
||||
sortTopics(-dialogId, true);
|
||||
}
|
||||
|
||||
public void onTopicEdited(long dialogId, TLRPC.TL_forumTopic forumTopic) {
|
||||
getMessagesStorage().updateTopicData(dialogId, forumTopic, TOPIC_FLAG_ICON + TOPIC_FLAG_TITLE);
|
||||
sortTopics(-dialogId);
|
||||
}
|
||||
|
||||
public void deleteTopics(long chatId, ArrayList<Integer> topicIds) {
|
||||
ArrayList<TLRPC.TL_forumTopic> topicsArray = topicsByChatId.get(chatId);
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
|
||||
if (topicsMap != null && topicsArray != null) {
|
||||
for (int i = 0; i < topicIds.size(); i++) {
|
||||
int topicId = topicIds.get(i);
|
||||
TLRPC.TL_forumTopic topic = topicsMap.get(topicId);
|
||||
topicsMap.remove(topicId);
|
||||
if (topic != null) {
|
||||
topicsByTopMsgId.remove(messageHash(topic.top_message, chatId));
|
||||
topicsArray.remove(topic);
|
||||
}
|
||||
}
|
||||
sortTopics(chatId);
|
||||
}
|
||||
for (int i = 0; i < topicIds.size(); i++) {
|
||||
deleteTopic(chatId, topicIds.get(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteTopic(long chatId, int topicId, int offset) {
|
||||
TLRPC.TL_channels_deleteTopicHistory deleteTopicHistory = new TLRPC.TL_channels_deleteTopicHistory();
|
||||
deleteTopicHistory.channel = getMessagesController().getInputChannel(chatId);
|
||||
deleteTopicHistory.top_msg_id = topicId;
|
||||
if (offset == 0) {
|
||||
getMessagesStorage().removeTopic(-chatId, topicId);
|
||||
}
|
||||
ConnectionsManager.getInstance(currentAccount).sendRequest(deleteTopicHistory, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error == null) {
|
||||
TLRPC.TL_messages_affectedHistory res = (TLRPC.TL_messages_affectedHistory) response;
|
||||
getMessagesController().processNewChannelDifferenceParams(res.pts, res.pts_count, chatId);
|
||||
if (res.offset > 0) {
|
||||
deleteTopic(chatId, topicId, res.offset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void toggleCloseTopic(long chatId, int topicId, boolean close) {
|
||||
TLRPC.TL_channels_editForumTopic req = new TLRPC.TL_channels_editForumTopic();
|
||||
req.channel = getMessagesController().getInputChannel(chatId);
|
||||
req.topic_id = topicId;
|
||||
req.flags |= 4;
|
||||
req.closed = close;
|
||||
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
|
||||
if (topicsMap != null) {
|
||||
TLRPC.TL_forumTopic topic = topicsMap.get(topicId);
|
||||
if (topic != null) {
|
||||
topic.closed = close;
|
||||
getMessagesStorage().updateTopicData(-chatId, topic, TOPIC_FLAG_CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() {
|
||||
@Override
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error == null) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void pinTopic(long chatId, int topicId, boolean pin) {
|
||||
TLRPC.TL_channels_updatePinnedForumTopic req = new TLRPC.TL_channels_updatePinnedForumTopic();
|
||||
req.channel = getMessagesController().getInputChannel(chatId);
|
||||
req.topic_id = topicId;
|
||||
req.pinned = pin;
|
||||
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
|
||||
if (topics != null) {
|
||||
for (int i = 0; i < topics.size(); ++i) {
|
||||
TLRPC.TL_forumTopic topic = topics.get(i);
|
||||
if (topic != null && (topicId == topic.id && pin) != topic.pinned) {
|
||||
topic.pinned = topicId == topic.id && pin;
|
||||
// topic.flags = topic.pinned ? (topic.flags | 8) : (topic.flags &~ 8);
|
||||
getMessagesStorage().updateTopicData(-chatId, topic, TOPIC_FLAG_PIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortTopics(chatId);
|
||||
|
||||
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
|
||||
if (response instanceof TLRPC.Updates) {
|
||||
// getMessagesController().processUpdates((TLRPC.Updates) response, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateMentionsUnread(long dialogId, int topicId, int topicMentionsCount) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
TLRPC.TL_forumTopic topic = findTopic(-dialogId, topicId);
|
||||
if (topic != null) {
|
||||
topic.unread_mentions_count = topicMentionsCount;
|
||||
sortTopics(-dialogId, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int updateReactionsUnread(long dialogId, int topicId, int count, boolean increment) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(-dialogId, topicId);
|
||||
int totalCount = -1;
|
||||
if (topic != null) {
|
||||
if (increment) {
|
||||
topic.unread_reactions_count += count;
|
||||
if (topic.unread_reactions_count < 0) {
|
||||
topic.unread_reactions_count = 0;
|
||||
}
|
||||
} else {
|
||||
topic.unread_reactions_count = count;
|
||||
}
|
||||
totalCount = topic.unread_reactions_count;
|
||||
sortTopics(-dialogId, true);
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public void markAllReactionsAsRead(long chatId, int topicId) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(chatId, topicId);
|
||||
if (topic != null && topic.unread_reactions_count > 0) {
|
||||
topic.unread_reactions_count = 0;
|
||||
sortTopics(chatId);
|
||||
}
|
||||
}
|
||||
|
||||
public TLRPC.Message getLastMessage(long id) {
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(id);
|
||||
if (!topics.isEmpty()) {
|
||||
return topics.get(0).topMessage;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
LongSparseArray<TopicsLoadOffset> offsets = new LongSparseArray<>();
|
||||
|
||||
public TopicsLoadOffset getLoadOffset(long chatId) {
|
||||
TopicsLoadOffset offset = offsets.get(chatId);
|
||||
if (offset != null) {
|
||||
return offset;
|
||||
}
|
||||
return new TopicsLoadOffset();
|
||||
// SharedPreferences sharedPreferences = getUserConfig().getPreferences();
|
||||
// TopicsLoadOffset topicsLoadOffset = new TopicsLoadOffset();
|
||||
// topicsLoadOffset.lastMessageId = sharedPreferences.getInt("topics_load_offset_message_id_" + chatId, 0);
|
||||
// topicsLoadOffset.lastMessageDate = sharedPreferences.getInt("topics_load_offset_date_" + chatId, 0);
|
||||
// topicsLoadOffset.lastMessageId = sharedPreferences.getInt("topics_load_offset_topic_id_" + chatId, 0);
|
||||
// return topicsLoadOffset;
|
||||
}
|
||||
|
||||
public void saveLoadOffset(long chatId, int lastMessageId, int lastMessageDate, int lastTopicId) {
|
||||
TopicsLoadOffset offset = new TopicsLoadOffset();
|
||||
offset.lastMessageId = lastMessageId;
|
||||
offset.lastMessageDate = lastMessageDate;
|
||||
offset.lastTopicId = lastTopicId;
|
||||
offsets.put(chatId, offset);
|
||||
// SharedPreferences.Editor editor = getUserConfig().getPreferences().edit();
|
||||
// editor.putInt("topics_load_offset_message_id_" + chatId, lastMessageId);
|
||||
// editor.putInt("topics_load_offset_date_" + chatId, lastMessageDate);
|
||||
// editor.putInt("topics_load_offset_topic_id_" + chatId, lastTopicId);
|
||||
// editor.apply();
|
||||
}
|
||||
|
||||
public void clearLoadingOffset(long chatId) {
|
||||
offsets.remove(chatId);
|
||||
// SharedPreferences.Editor editor = getUserConfig().getPreferences().edit();
|
||||
// editor.remove("topics_load_offset_message_id_" + chatId);
|
||||
// editor.remove("topics_load_offset_date_" + chatId);
|
||||
// editor.remove("topics_load_offset_topic_id_" + chatId);
|
||||
// editor.apply();
|
||||
}
|
||||
|
||||
public boolean endIsReached(long chatId) {
|
||||
return endIsReached.get(chatId, 0) == 1;
|
||||
}
|
||||
|
||||
public void processUpdate(List<TopicUpdate> topicUpdates) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
HashSet<Long> changedDialogs = new HashSet<>();
|
||||
LongSparseArray<ArrayList<TLRPC.TL_forumTopic>> topicsToReload = null;
|
||||
for (int i = 0; i < topicUpdates.size(); i++) {
|
||||
TopicUpdate update = topicUpdates.get(i);
|
||||
if (update.reloadTopic) {
|
||||
if (topicsToReload == null) {
|
||||
topicsToReload = new LongSparseArray<>();
|
||||
}
|
||||
ArrayList<TLRPC.TL_forumTopic> arrayList = topicsToReload.get(update.dialogId);
|
||||
if (arrayList == null) {
|
||||
arrayList = new ArrayList<>();
|
||||
topicsToReload.put(update.dialogId, arrayList);
|
||||
}
|
||||
TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic();
|
||||
forumTopic.id = update.topicId;
|
||||
arrayList.add(forumTopic);
|
||||
} else {
|
||||
TLRPC.TL_forumTopic topic = findTopic(-update.dialogId, update.topicId);
|
||||
if (topic != null) {
|
||||
if (update.onlyCounters) {
|
||||
if (update.unreadCount >= 0) {
|
||||
topic.unread_count = update.unreadCount;
|
||||
}
|
||||
if (update.unreadMentions >= 0) {
|
||||
topic.unread_mentions_count = update.unreadMentions;
|
||||
}
|
||||
} else {
|
||||
topicsByTopMsgId.remove(messageHash(topic.top_message, -update.dialogId));
|
||||
topic.topMessage = update.topMessage;
|
||||
topic.groupedMessages = update.groupedMessages;
|
||||
topic.top_message = update.topMessageId;
|
||||
topic.unread_count = update.unreadCount;
|
||||
topic.unread_mentions_count = update.unreadMentions;
|
||||
topicsByTopMsgId.put(messageHash(topic.top_message, -update.dialogId), topic);
|
||||
}
|
||||
changedDialogs.add(-update.dialogId);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Long changedDialog : changedDialogs) {
|
||||
sortTopics(changedDialog, true);
|
||||
}
|
||||
|
||||
if (topicsToReload != null) {
|
||||
for (int i = 0; i < topicsToReload.size(); i++) {
|
||||
long dialogId = topicsToReload.keyAt(i);
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsToReload.valueAt(i);
|
||||
reloadTopics(-dialogId, topics);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isLoading(long chatId) {
|
||||
return topicsIsLoading.get(chatId, 0) == 1 && (topicsByChatId.get(chatId) == null || topicsByChatId.get(chatId).isEmpty());
|
||||
}
|
||||
|
||||
public void onTopicsDeletedServerSide(ArrayList<MessagesStorage.TopicKey> topicsToDelete) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
HashSet<Long> changedChatId = new HashSet<>();
|
||||
for (int i = 0; i < topicsToDelete.size(); i++) {
|
||||
MessagesStorage.TopicKey topicKey = topicsToDelete.get(i);
|
||||
long chatId = -topicKey.dialogId;
|
||||
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
|
||||
if (topicsMap != null) {
|
||||
topicsMap.remove(topicKey.topicId);
|
||||
}
|
||||
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
|
||||
if (topics != null) {
|
||||
for (int k = 0; k < topics.size(); k++) {
|
||||
if (topics.get(k).id == topicKey.topicId) {
|
||||
topics.remove(k);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogDeleted, -chatId, topicKey.topicId);
|
||||
changedChatId.add(chatId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for (Long chatId : changedChatId) {
|
||||
sortTopics(chatId, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void reloadTopics(long chatId) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
topicsByChatId.remove(chatId);
|
||||
topicsMapByChatId.remove(chatId);
|
||||
endIsReached.delete(chatId);
|
||||
clearLoadingOffset(chatId);
|
||||
|
||||
TLRPC.Chat chat = getMessagesController().getChat(chatId);
|
||||
if (chat != null && chat.forum) {
|
||||
preloadTopics(chatId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void databaseCleared() {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
topicsByChatId.clear();
|
||||
topicsMapByChatId.clear();
|
||||
endIsReached.clear();
|
||||
|
||||
SharedPreferences.Editor editor = getUserConfig().getPreferences().edit();
|
||||
for (String key : getUserConfig().getPreferences().getAll().keySet()) {
|
||||
if (key.startsWith("topics_load_offset_message_id_")) {
|
||||
editor.remove(key);
|
||||
}
|
||||
if (key.startsWith("topics_load_offset_date_")) {
|
||||
editor.remove(key);
|
||||
}
|
||||
if (key.startsWith("topics_load_offset_topic_id_")) {
|
||||
editor.remove(key);
|
||||
}
|
||||
}
|
||||
editor.apply();
|
||||
});
|
||||
}
|
||||
|
||||
public void updateReadOutbox(HashMap<MessagesStorage.TopicKey, Integer> topicsReadOutbox) {
|
||||
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
HashSet<Long> updatedChats = new HashSet<>();
|
||||
for (MessagesStorage.TopicKey topicKey : topicsReadOutbox.keySet()) {
|
||||
int value = topicsReadOutbox.get(topicKey);
|
||||
TLRPC.TL_forumTopic topic = findTopic(-topicKey.dialogId, topicKey.topicId);
|
||||
if (topic != null) {
|
||||
topic.read_outbox_max_id = Math.max(topic.read_outbox_max_id, value);
|
||||
updatedChats.add(-topicKey.dialogId);
|
||||
if ( topic.read_outbox_max_id >= topic.topMessage.id) {
|
||||
topic.topMessage.unread = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO topics
|
||||
// optimize move to mask update
|
||||
for (Long chatId : updatedChats) {
|
||||
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.topicsDidLoaded, chatId, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateTopicInUi(long dialogId, TLRPC.TL_forumTopic forumTopic, int flags) {
|
||||
TLRPC.TL_forumTopic topic = findTopic(-dialogId, forumTopic.id);
|
||||
if (topic != null) {
|
||||
if ((flags & TOPIC_FLAG_TITLE) != 0) {
|
||||
topic.title = forumTopic.title;
|
||||
}
|
||||
if ((flags & TOPIC_FLAG_ICON) != 0) {
|
||||
topic.icon_emoji_id = forumTopic.icon_emoji_id;
|
||||
}
|
||||
if ((flags & TOPIC_FLAG_CLOSE) != 0) {
|
||||
topic.closed = forumTopic.closed;
|
||||
}
|
||||
if ((flags & TOPIC_FLAG_PIN) != 0) {
|
||||
topic.pinned = forumTopic.pinned;
|
||||
}
|
||||
sortTopics(-dialogId);
|
||||
}
|
||||
}
|
||||
|
||||
public void processEditedMessages(LongSparseArray<ArrayList<MessageObject>> editingMessagesFinal) {
|
||||
HashSet<Long> changedChatId = new HashSet<>();
|
||||
for (int i = 0; i < editingMessagesFinal.size(); i++) {
|
||||
ArrayList<MessageObject> messageObjects = editingMessagesFinal.valueAt(i);
|
||||
for (int j = 0; j < messageObjects.size(); j++) {
|
||||
TLRPC.TL_forumTopic topic = topicsByTopMsgId.get(messageHash(messageObjects.get(j).getId(), -messageObjects.get(j).getDialogId()));
|
||||
if (topic != null) {
|
||||
topic.topMessage = messageObjects.get(j).messageOwner;
|
||||
changedChatId.add(-messageObjects.get(j).getDialogId());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Long chatId : changedChatId) {
|
||||
sortTopics(chatId, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void processEditedMessage(TLRPC.Message newMsg) {
|
||||
TLRPC.TL_forumTopic topic = topicsByTopMsgId.get(messageHash(newMsg.id, -newMsg.dialog_id));
|
||||
if (topic != null) {
|
||||
topic.topMessage = newMsg;
|
||||
sortTopics(-newMsg.dialog_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
private class TopicsLoadOffset {
|
||||
int lastMessageId;
|
||||
int lastMessageDate;
|
||||
int lastTopicId;
|
||||
}
|
||||
|
||||
public static class TopicUpdate {
|
||||
long dialogId;
|
||||
int topicId;
|
||||
int unreadMentions;
|
||||
int unreadCount;
|
||||
int topMessageId;
|
||||
TLRPC.Message topMessage;
|
||||
ArrayList<MessageObject> groupedMessages;
|
||||
boolean reloadTopic;
|
||||
boolean onlyCounters;
|
||||
}
|
||||
|
||||
|
||||
public void onTopicFragmentResume(long chatId) {
|
||||
int v = openedTopicsBuChatId.get(chatId, 0);
|
||||
openedTopicsBuChatId.put(chatId, v + 1);
|
||||
sortTopics(chatId);
|
||||
}
|
||||
|
||||
public void onTopicFragmentPause(long chatId) {
|
||||
int v = openedTopicsBuChatId.get(chatId, 0);
|
||||
v--;
|
||||
if (v < 0) {
|
||||
v = 0;
|
||||
}
|
||||
openedTopicsBuChatId.put(chatId, v);
|
||||
|
||||
}
|
||||
}
|
|
@ -70,8 +70,10 @@ public class UserConfig extends BaseController {
|
|||
|
||||
public String premiumGiftsStickerPack;
|
||||
public String genericAnimationsStickerPack;
|
||||
public String defaultTopicIcons;
|
||||
public long lastUpdatedPremiumGiftsStickerPack;
|
||||
public long lastUpdatedGenericAnimations;
|
||||
public long lastUpdatedDefaultTopicIcons;
|
||||
|
||||
public volatile byte[] savedPasswordHash;
|
||||
public volatile byte[] savedSaltedPassword;
|
||||
|
@ -405,7 +407,7 @@ public class UserConfig extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private SharedPreferences getPreferences() {
|
||||
public SharedPreferences getPreferences() {
|
||||
if (currentAccount == 0) {
|
||||
return ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.math.BigInteger;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -112,32 +113,36 @@ public class Utilities {
|
|||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
int val = 0;
|
||||
try {
|
||||
int start = -1, end;
|
||||
for (end = 0; end < value.length(); ++end) {
|
||||
char character = value.charAt(end);
|
||||
boolean allowedChar = character == '-' || character >= '0' && character <= '9';
|
||||
if (allowedChar && start < 0) {
|
||||
start = end;
|
||||
} else if (!allowedChar && start >= 0) {
|
||||
end++;
|
||||
break;
|
||||
if (BuildConfig.BUILD_HOST_IS_WINDOWS) {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
return Integer.valueOf(matcher.group());
|
||||
}
|
||||
} else {
|
||||
int val = 0;
|
||||
try {
|
||||
int start = -1, end;
|
||||
for (end = 0; end < value.length(); ++end) {
|
||||
char character = value.charAt(end);
|
||||
boolean allowedChar = character == '-' || character >= '0' && character <= '9';
|
||||
if (allowedChar && start < 0) {
|
||||
start = end;
|
||||
} else if (!allowedChar && start >= 0) {
|
||||
end++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start >= 0) {
|
||||
String str = value.subSequence(start, end).toString();
|
||||
if (start >= 0) {
|
||||
String str = value.subSequence(start, end).toString();
|
||||
// val = parseInt(str);
|
||||
val = Integer.parseInt(str);
|
||||
}
|
||||
// Matcher matcher = pattern.matcher(value);
|
||||
// if (matcher.find()) {
|
||||
// String num = matcher.group(0);
|
||||
// val = Integer.parseInt(num);
|
||||
// }
|
||||
} catch (Exception ignore) {}
|
||||
return val;
|
||||
val = Integer.parseInt(str);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
return val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int parseInt(final String s) {
|
||||
int num = 0;
|
||||
boolean negative = true;
|
||||
|
@ -464,4 +469,12 @@ public class Utilities {
|
|||
public static interface Callback<T> {
|
||||
public void run(T arg);
|
||||
}
|
||||
|
||||
public static <Key, Value> Value getOrDefault(HashMap<Key, Value> map, Key key, Value defaultValue) {
|
||||
Value v = map.get(key);
|
||||
if (v == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public class WearReplyReceiver extends BroadcastReceiver {
|
|||
}
|
||||
long dialogId = intent.getLongExtra("dialog_id", 0);
|
||||
int maxId = intent.getIntExtra("max_id", 0);
|
||||
int topicId = intent.getIntExtra("topic_id", 0);
|
||||
int currentAccount = intent.getIntExtra("currentAccount", 0);
|
||||
if (dialogId == 0 || maxId == 0 || !UserConfig.isValidAccount(currentAccount)) {
|
||||
return;
|
||||
|
@ -45,7 +46,7 @@ public class WearReplyReceiver extends BroadcastReceiver {
|
|||
TLRPC.User user1 = accountInstance.getMessagesStorage().getUserSync(dialogId);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
accountInstance.getMessagesController().putUser(user1, true);
|
||||
sendMessage(accountInstance, text, dialogId, maxId);
|
||||
sendMessage(accountInstance, text, dialogId, topicId, maxId);
|
||||
});
|
||||
});
|
||||
return;
|
||||
|
@ -57,17 +58,31 @@ public class WearReplyReceiver extends BroadcastReceiver {
|
|||
TLRPC.Chat chat1 = accountInstance.getMessagesStorage().getChatSync(-dialogId);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
accountInstance.getMessagesController().putChat(chat1, true);
|
||||
sendMessage(accountInstance, text, dialogId, maxId);
|
||||
sendMessage(accountInstance, text, dialogId, topicId, maxId);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
sendMessage(accountInstance, text, dialogId, maxId);
|
||||
sendMessage(accountInstance, text, dialogId, topicId, maxId);
|
||||
}
|
||||
|
||||
private void sendMessage(AccountInstance accountInstance, CharSequence text, long dialog_id, int max_id) {
|
||||
accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, null, null, null, true, null, null, null, true, 0, null, false);
|
||||
accountInstance.getMessagesController().markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, 0, true, 0);
|
||||
private void sendMessage(AccountInstance accountInstance, CharSequence text, long dialog_id, int topicId, int max_id) {
|
||||
MessageObject replyToMsgId = null;
|
||||
if (topicId != 0) {
|
||||
TLRPC.TL_message topicStartMessage = new TLRPC.TL_message();
|
||||
topicStartMessage.message = "";
|
||||
topicStartMessage.id = topicId;
|
||||
topicStartMessage.peer_id = accountInstance.getMessagesController().getPeer(dialog_id);
|
||||
topicStartMessage.action = new TLRPC.TL_messageActionTopicCreate();
|
||||
topicStartMessage.action.title = "";
|
||||
replyToMsgId = new MessageObject(accountInstance.getCurrentAccount(), topicStartMessage, false, false);
|
||||
}
|
||||
|
||||
accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, replyToMsgId, null, null, true, null, null, null, true, 0, null, false);
|
||||
//TODO handle topics
|
||||
if (topicId == 0) {
|
||||
accountInstance.getMessagesController().markDialogAsRead(dialog_id, max_id, max_id, 0, false, topicId, 0, true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.telegram.tgnet.TLRPC;
|
|||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.URLEncoder;
|
||||
|
@ -181,11 +182,35 @@ public class Browser {
|
|||
return url.matches("^(https" + (forceHttps ? "" : "?") + "://)?(te\\.?legra\\.ph|graph\\.org).*"); // telegra.ph, te.legra.ph, graph.org
|
||||
}
|
||||
|
||||
public static String extractUsername(String link) {
|
||||
if (link == null || TextUtils.isEmpty(link)) {
|
||||
return null;
|
||||
}
|
||||
if (link.startsWith("@")) {
|
||||
return link.substring(1);
|
||||
}
|
||||
if (link.startsWith("t.me/")) {
|
||||
return link.substring(5);
|
||||
}
|
||||
if (link.startsWith("http://t.me/")) {
|
||||
return link.substring(12);
|
||||
}
|
||||
if (link.startsWith("https://t.me/")) {
|
||||
return link.substring(13);
|
||||
}
|
||||
Matcher prefixMatcher = LaunchActivity.PREFIX_T_ME_PATTERN.matcher(link);
|
||||
if (prefixMatcher.find()) {
|
||||
return prefixMatcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean urlMustNotHaveConfirmation(String url) {
|
||||
return (
|
||||
isTelegraphUrl(url, false, true) ||
|
||||
url.matches("^(https://)?t\\.me/iv\\??.*") || // t.me/iv?
|
||||
url.matches("^(https://)?telegram\\.org/(blog|tour)/?.*") // telegram.org/blog, telegram.org/tour
|
||||
url.matches("^(https://)?telegram\\.org/(blog|tour)/?.*") || // telegram.org/blog, telegram.org/tour
|
||||
url.matches("^(https://)?fragment\\.com/?.*") // fragment.com
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
return x;
|
||||
}
|
||||
|
||||
public void focusToPoint(int x, int y) {
|
||||
public void focusToPoint(int x, int y, boolean visible) {
|
||||
Rect focusRect = calculateTapArea(x, y, 1f);
|
||||
Rect meteringRect = calculateTapArea(x, y, 1.5f);
|
||||
|
||||
|
@ -554,13 +554,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
cameraSession.focusToRect(focusRect, meteringRect);
|
||||
}
|
||||
|
||||
focusProgress = 0.0f;
|
||||
innerAlpha = 1.0f;
|
||||
outerAlpha = 1.0f;
|
||||
cx = x;
|
||||
cy = y;
|
||||
lastDrawTime = System.currentTimeMillis();
|
||||
invalidate();
|
||||
if (visible) {
|
||||
focusProgress = 0.0f;
|
||||
innerAlpha = 1.0f;
|
||||
outerAlpha = 1.0f;
|
||||
cx = x;
|
||||
cy = y;
|
||||
lastDrawTime = System.currentTimeMillis();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void focusToPoint(int x, int y) {
|
||||
focusToPoint(x, y, true);
|
||||
}
|
||||
|
||||
public void setZoom(float value) {
|
||||
|
|
|
@ -74,22 +74,40 @@ public class BitmapsCache {
|
|||
public void createCache() {
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
||||
if (file.exists()) {
|
||||
RandomAccessFile randomAccessFile = null;
|
||||
try {
|
||||
randomAccessFile = new RandomAccessFile(file, "r");
|
||||
cacheCreated = randomAccessFile.readBoolean();
|
||||
int framesCount = randomAccessFile.readInt();
|
||||
if (framesCount == 0) {
|
||||
cacheCreated = false;
|
||||
}
|
||||
if (cacheCreated) {
|
||||
randomAccessFile.close();
|
||||
return;
|
||||
} else {
|
||||
file.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
file.delete();
|
||||
} catch (Throwable e2) {
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (randomAccessFile != null) {
|
||||
try {
|
||||
randomAccessFile.close();
|
||||
} catch (Throwable e2) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
randomAccessFile.close();
|
||||
randomAccessFile = new RandomAccessFile(file, "rw");
|
||||
|
||||
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
||||
|
||||
|
||||
Bitmap[] bitmap = new Bitmap[N];
|
||||
ByteArrayOutputStream[] byteArrayOutputStream = new ByteArrayOutputStream[N];
|
||||
|
@ -267,10 +285,15 @@ public class BitmapsCache {
|
|||
return cacheCreated;
|
||||
}
|
||||
RandomAccessFile randomAccessFile = null;
|
||||
int framesCount;
|
||||
try {
|
||||
synchronized (mutex) {
|
||||
randomAccessFile = new RandomAccessFile(file, "r");
|
||||
cacheCreated = randomAccessFile.readBoolean();
|
||||
framesCount = randomAccessFile.readInt();
|
||||
if (framesCount <= 0) {
|
||||
cacheCreated = false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
|
@ -283,7 +306,7 @@ public class BitmapsCache {
|
|||
}
|
||||
}
|
||||
}
|
||||
checkCache = false;
|
||||
checkCache = true;
|
||||
return cacheCreated;
|
||||
}
|
||||
|
||||
|
@ -346,7 +369,7 @@ public class BitmapsCache {
|
|||
} catch (FileNotFoundException e) {
|
||||
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
FileLog.e(e, false);
|
||||
}
|
||||
|
||||
if (randomAccessFile != null) {
|
||||
|
|
|
@ -77,6 +77,7 @@ public class ConnectionsManager extends BaseController {
|
|||
public final static int RequestFlagForceDownload = 32;
|
||||
public final static int RequestFlagInvokeAfter = 64;
|
||||
public final static int RequestFlagNeedQuickAck = 128;
|
||||
public final static int RequestFlagDoNotWaitFloodWait = 1024;
|
||||
|
||||
public final static int ConnectionStateConnecting = 1;
|
||||
public final static int ConnectionStateWaitingForNetwork = 2;
|
||||
|
@ -1296,7 +1297,7 @@ public class ConnectionsManager extends BaseController {
|
|||
buffer.writeBytes(bytes);
|
||||
return buffer;
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
FileLog.e(e, false);
|
||||
} finally {
|
||||
try {
|
||||
if (httpConnectionStream != null) {
|
||||
|
@ -1392,7 +1393,7 @@ public class ConnectionsManager extends BaseController {
|
|||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||
currentTask = task;
|
||||
});
|
||||
FileLog.e(e);
|
||||
FileLog.e(e, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -587,6 +587,14 @@ public class NativeByteBuffer extends AbstractSerializedData {
|
|||
return buffer.remaining();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (!reused) {
|
||||
reuse();
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
public static native long native_getFreeBuffer(int length);
|
||||
public static native ByteBuffer native_getJavaByteBuffer(long address);
|
||||
public static native int native_limit(long address);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,6 @@ import android.graphics.Rect;
|
|||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -53,28 +52,24 @@ import org.telegram.messenger.SharedConfig;
|
|||
import org.telegram.ui.Components.BackButtonMenu;
|
||||
import org.telegram.ui.Components.Bulletin;
|
||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||
import org.telegram.ui.Components.FloatingDebug.FloatingDebugController;
|
||||
import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider;
|
||||
import org.telegram.ui.Components.GroupCallPip;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ActionBarLayout extends FrameLayout {
|
||||
|
||||
public interface ActionBarLayoutDelegate {
|
||||
boolean onPreIme();
|
||||
|
||||
boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout);
|
||||
|
||||
boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout);
|
||||
|
||||
boolean needCloseLastFragment(ActionBarLayout layout);
|
||||
|
||||
void onRebuildAllFragments(ActionBarLayout layout, boolean last);
|
||||
}
|
||||
public class ActionBarLayout extends FrameLayout implements INavigationLayout, FloatingDebugProvider {
|
||||
|
||||
public boolean highlightActionButtons = false;
|
||||
|
||||
@Override
|
||||
public void setHighlightActionButtons(boolean highlightActionButtons) {
|
||||
this.highlightActionButtons = highlightActionButtons;
|
||||
}
|
||||
|
||||
public class LayoutContainer extends FrameLayout {
|
||||
|
||||
private Rect rect = new Rect();
|
||||
|
@ -300,33 +295,6 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ThemeAnimationSettings {
|
||||
|
||||
public final Theme.ThemeInfo theme;
|
||||
public final int accentId;
|
||||
public final boolean nightTheme;
|
||||
public final boolean instant;
|
||||
public boolean onlyTopFragment;
|
||||
public boolean applyTheme = true;
|
||||
public Runnable afterStartDescriptionsAddedRunnable;
|
||||
public Runnable beforeAnimationRunnable;
|
||||
public Runnable afterAnimationRunnable;
|
||||
public onAnimationProgress animationProgress;
|
||||
public long duration = 200;
|
||||
public Theme.ResourcesProvider resourcesProvider;
|
||||
|
||||
public ThemeAnimationSettings(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
||||
this.theme = theme;
|
||||
this.accentId = accentId;
|
||||
this.nightTheme = nightTheme;
|
||||
this.instant = instant;
|
||||
}
|
||||
|
||||
public interface onAnimationProgress {
|
||||
void setProgress(float p);
|
||||
}
|
||||
}
|
||||
|
||||
private static Drawable headerShadowDrawable;
|
||||
private static Drawable layerShadowDrawable;
|
||||
private static Paint scrimPaint;
|
||||
|
@ -405,11 +373,11 @@ public class ActionBarLayout extends FrameLayout {
|
|||
private int titleOverlayTextId;
|
||||
private Runnable overlayAction;
|
||||
|
||||
private ActionBarLayoutDelegate delegate;
|
||||
private INavigationLayoutDelegate delegate;
|
||||
protected Activity parentActivity;
|
||||
|
||||
public ArrayList<BaseFragment> fragmentsStack;
|
||||
public ArrayList<BackButtonMenu.PulledDialog> pulledDialogs;
|
||||
private List<BaseFragment> fragmentsStack;
|
||||
private List<BackButtonMenu.PulledDialog> pulledDialogs;
|
||||
private Rect rect = new Rect();
|
||||
private boolean delayedAnimationResumed;
|
||||
private Runnable onFragmentStackChangedListener;
|
||||
|
@ -427,7 +395,8 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void init(ArrayList<BaseFragment> stack) {
|
||||
@Override
|
||||
public void setFragmentStack(List<BaseFragment> stack) {
|
||||
this.fragmentsStack = stack;
|
||||
this.containerViewBack = new LayoutContainer(parentActivity);
|
||||
addView(containerViewBack);
|
||||
|
@ -464,18 +433,30 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void drawHeaderShadow(Canvas canvas, int y) {
|
||||
drawHeaderShadow(canvas, 255, y);
|
||||
private int[] measureSpec = new int[2];
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (delegate != null) {
|
||||
measureSpec[0] = widthMeasureSpec;
|
||||
measureSpec[1] = heightMeasureSpec;
|
||||
delegate.onMeasureOverride(measureSpec);
|
||||
widthMeasureSpec = measureSpec[0];
|
||||
heightMeasureSpec = measureSpec[1];
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInBubbleMode(boolean value) {
|
||||
inBubbleMode = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInBubbleMode() {
|
||||
return inBubbleMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawHeaderShadow(Canvas canvas, int alpha, int y) {
|
||||
if (headerShadowDrawable != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
|
@ -522,13 +503,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return innerTranslationX;
|
||||
}
|
||||
|
||||
public void dismissDialogs() {
|
||||
if (!fragmentsStack.isEmpty()) {
|
||||
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
lastFragment.dismissCurrentDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (transitionAnimationInProgress) {
|
||||
if (currentAnimation != null) {
|
||||
|
@ -555,6 +530,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserLeaveHint() {
|
||||
if (!fragmentsStack.isEmpty()) {
|
||||
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
|
@ -562,6 +538,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (!fragmentsStack.isEmpty()) {
|
||||
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
|
@ -646,6 +623,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCurrentPreviewFragmentAlpha() {
|
||||
if (inPreviewMode || transitionAnimationPreviewMode || previewOpenAnimationInProgress) {
|
||||
return (oldFragment != null && oldFragment.inPreviewMode ? containerViewBack : containerView).getAlpha();
|
||||
|
@ -654,6 +632,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawCurrentPreviewFragment(Canvas canvas, Drawable foregroundDrawable) {
|
||||
if (inPreviewMode || transitionAnimationPreviewMode || previewOpenAnimationInProgress) {
|
||||
final ViewGroup v = oldFragment != null && oldFragment.inPreviewMode ? containerViewBack : containerView;
|
||||
|
@ -697,8 +676,9 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void setDelegate(ActionBarLayoutDelegate actionBarLayoutDelegate) {
|
||||
delegate = actionBarLayoutDelegate;
|
||||
@Override
|
||||
public void setDelegate(INavigationLayoutDelegate INavigationLayoutDelegate) {
|
||||
delegate = INavigationLayoutDelegate;
|
||||
}
|
||||
|
||||
private void onSlideAnimationEnd(final boolean backAnimation) {
|
||||
|
@ -807,6 +787,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
lastFragment.prepareFragmentToSlide(false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (!checkTransitionAnimation() && !inActionMode && !animationInProgress) {
|
||||
if (fragmentsStack.size() > 1) {
|
||||
|
@ -944,6 +925,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (transitionAnimationPreviewMode || startedTracking || checkTransitionAnimation() || fragmentsStack.isEmpty()) {
|
||||
return;
|
||||
|
@ -963,6 +945,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
for (BaseFragment fragment : fragmentsStack) {
|
||||
fragment.onLowMemory();
|
||||
|
@ -1002,6 +985,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTransitionAnimation() {
|
||||
if (transitionAnimationPreviewMode) {
|
||||
return false;
|
||||
|
@ -1012,10 +996,17 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return transitionAnimationInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreviewOpenAnimationInProgress() {
|
||||
return previewOpenAnimationInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSwipeInProgress() {
|
||||
return startedTracking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransitionAnimationInProgress() {
|
||||
return transitionAnimationInProgress || animationInProgress;
|
||||
}
|
||||
|
@ -1058,22 +1049,6 @@ public class ActionBarLayout extends FrameLayout {
|
|||
containerViewBack.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public boolean presentFragmentAsPreview(BaseFragment fragment) {
|
||||
return presentFragment(fragment, false, false, true, true, null);
|
||||
}
|
||||
|
||||
public boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, ActionBarPopupWindow.ActionBarPopupWindowLayout menu) {
|
||||
return presentFragment(fragment, false, false, true, true, menu);
|
||||
}
|
||||
|
||||
public boolean presentFragment(BaseFragment fragment) {
|
||||
return presentFragment(fragment, false, false, true, false, null);
|
||||
}
|
||||
|
||||
public boolean presentFragment(BaseFragment fragment, boolean removeLast) {
|
||||
return presentFragment(fragment, removeLast, false, true, false, null);
|
||||
}
|
||||
|
||||
private void startLayoutAnimation(final boolean open, final boolean first, final boolean preview) {
|
||||
if (first) {
|
||||
animationProgress = 0.0f;
|
||||
|
@ -1166,6 +1141,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeDelayedFragmentAnimation() {
|
||||
delayedAnimationResumed = true;
|
||||
if (delayedOpenAnimationRunnable == null || waitingForKeyboardCloseRunnable != null) {
|
||||
|
@ -1180,6 +1156,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return inPreviewMode || transitionAnimationPreviewMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInPassivePreviewMode() {
|
||||
return (inPreviewMode && previewMenu == null) || transitionAnimationPreviewMode;
|
||||
}
|
||||
|
@ -1188,13 +1165,16 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return isInPreviewMode() && previewMenu != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean presentFragment(NavigationParams params) {
|
||||
BaseFragment fragment = params.fragment;
|
||||
boolean removeLast = params.removeLast;
|
||||
boolean forceWithoutAnimation = params.noAnimation;
|
||||
boolean check = params.checkPresentFromDelegate;
|
||||
boolean preview = params.preview;
|
||||
ActionBarPopupWindow.ActionBarPopupWindowLayout menu = params.menuView;
|
||||
|
||||
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check, final boolean preview) {
|
||||
return presentFragment(fragment, removeLast, forceWithoutAnimation, check, preview, null);
|
||||
}
|
||||
|
||||
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check, final boolean preview, ActionBarPopupWindow.ActionBarPopupWindowLayout menu) {
|
||||
if (fragment == null || checkTransitionAnimation() || delegate != null && check && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) {
|
||||
if (fragment == null || checkTransitionAnimation() || delegate != null && check && !delegate.needPresentFragment(this, params) || !fragment.onFragmentCreate()) {
|
||||
return false;
|
||||
}
|
||||
if (inPreviewMode && transitionAnimationPreviewMode) {
|
||||
|
@ -1489,6 +1469,12 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseFragment> getFragmentStack() {
|
||||
return fragmentsStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentStackChangedListener(Runnable onFragmentStackChanged) {
|
||||
this.onFragmentStackChangedListener = onFragmentStackChanged;
|
||||
}
|
||||
|
@ -1500,10 +1486,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
ImageLoader.getInstance().onFragmentStackChanged();
|
||||
}
|
||||
|
||||
public boolean addFragmentToStack(BaseFragment fragment) {
|
||||
return addFragmentToStack(fragment, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFragmentToStack(BaseFragment fragment, int position) {
|
||||
if (delegate != null && !delegate.needAddFragmentToStack(fragment, this) || !fragment.onFragmentCreate()) {
|
||||
return false;
|
||||
|
@ -1548,6 +1531,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
onFragmentStackChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePreviewFragment(float dy) {
|
||||
if (!inPreviewMode || previewMenu != null || transitionAnimationPreviewMode) {
|
||||
return;
|
||||
|
@ -1566,6 +1550,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expandPreviewFragment() {
|
||||
previewOpenAnimationInProgress = true;
|
||||
inPreviewMode = false;
|
||||
|
@ -1604,6 +1589,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
fragment.setInMenuMode(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishPreviewFragment() {
|
||||
if (!inPreviewMode && !transitionAnimationPreviewMode) {
|
||||
return;
|
||||
|
@ -1803,7 +1789,8 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void showFragment(int i) {
|
||||
@Override
|
||||
public void bringToFront(int i) {
|
||||
if (fragmentsStack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1859,7 +1846,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
if (fragmentsStack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
showFragment(fragmentsStack.size() - 1);
|
||||
bringToFront(fragmentsStack.size() - 1);
|
||||
}
|
||||
|
||||
private void removeFragmentFromStackInternal(BaseFragment fragment) {
|
||||
|
@ -1870,13 +1857,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
onFragmentStackChanged();
|
||||
}
|
||||
|
||||
public void removeFragmentFromStack(int num) {
|
||||
if (num >= fragmentsStack.size()) {
|
||||
return;
|
||||
}
|
||||
removeFragmentFromStackInternal(fragmentsStack.get(num));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFragmentFromStack(BaseFragment fragment) {
|
||||
if (useAlphaAnimations && fragmentsStack.size() == 1 && AndroidUtilities.isTablet()) {
|
||||
closeLastFragment(true);
|
||||
|
@ -1941,9 +1922,13 @@ public class ActionBarLayout extends FrameLayout {
|
|||
if (animationProgressListener != null) {
|
||||
animationProgressListener.setProgress(value);
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.onThemeProgress(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@Override
|
||||
public float getThemeAnimationValue() {
|
||||
return themeAnimationValue;
|
||||
}
|
||||
|
@ -1976,14 +1961,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
||||
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), null);
|
||||
}
|
||||
|
||||
public void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant, Runnable onDone) {
|
||||
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), onDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateThemedValues(ThemeAnimationSettings settings, Runnable onDone) {
|
||||
if (transitionAnimationInProgress || startedTracking) {
|
||||
animateThemeAfterAnimation = true;
|
||||
|
@ -2135,6 +2113,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebuildLogout() {
|
||||
containerView.removeAllViews();
|
||||
containerViewBack.removeAllViews();
|
||||
|
@ -2143,6 +2122,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
oldFragment = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebuildAllFragmentViews(boolean last, boolean showLastAfter) {
|
||||
if (transitionAnimationInProgress || startedTracking) {
|
||||
rebuildAfterAnimation = true;
|
||||
|
@ -2169,6 +2149,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && !checkTransitionAnimation() && !startedTracking && currentActionBar != null) {
|
||||
currentActionBar.onMenuButtonPressed();
|
||||
|
@ -2176,6 +2157,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeStarted(Object mode) {
|
||||
if (currentActionBar != null) {
|
||||
currentActionBar.setVisibility(GONE);
|
||||
|
@ -2183,6 +2165,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
inActionMode = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeFinished(Object mode) {
|
||||
if (currentActionBar != null) {
|
||||
currentActionBar.setVisibility(VISIBLE);
|
||||
|
@ -2232,6 +2215,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivityForResult(final Intent intent, final int requestCode) {
|
||||
if (parentActivity == null) {
|
||||
return;
|
||||
|
@ -2253,14 +2237,37 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Theme.MessageDrawable getMessageDrawableOutStart() {
|
||||
return messageDrawableOutStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Theme.MessageDrawable getMessageDrawableOutMediaStart() {
|
||||
return messageDrawableOutMediaStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BackButtonMenu.PulledDialog> getPulledDialogs() {
|
||||
return pulledDialogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPulledDialogs(List<BackButtonMenu.PulledDialog> pulledDialogs) {
|
||||
this.pulledDialogs = pulledDialogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseAlphaAnimations(boolean value) {
|
||||
useAlphaAnimations = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundView(View view) {
|
||||
backgroundView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawerLayoutContainer(DrawerLayoutContainer layout) {
|
||||
drawerLayoutContainer = layout;
|
||||
}
|
||||
|
@ -2273,6 +2280,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
removeActionBarExtraHeight = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleOverlayText(String title, int titleId, Runnable action) {
|
||||
titleOverlayText = title;
|
||||
titleOverlayTextId = titleId;
|
||||
|
@ -2285,6 +2293,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean extendActionMode(Menu menu) {
|
||||
return !fragmentsStack.isEmpty() && fragmentsStack.get(fragmentsStack.size() - 1).extendActionMode(menu);
|
||||
}
|
||||
|
@ -2294,12 +2303,44 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentPanTranslationOffset(int offset) {
|
||||
if (containerView != null) {
|
||||
containerView.setFragmentPanTranslationOffset(offset);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup getOverlayContainerView() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FloatingDebugController.DebugItem> onGetDebugItems() {
|
||||
BaseFragment fragment = getLastFragment();
|
||||
if (fragment != null) {
|
||||
List<FloatingDebugController.DebugItem> items = new ArrayList<>();
|
||||
if (fragment instanceof FloatingDebugProvider) {
|
||||
items.addAll(((FloatingDebugProvider) fragment).onGetDebugItems());
|
||||
}
|
||||
observeDebugItemsFromView(items, fragment.getFragmentView());
|
||||
return items;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void observeDebugItemsFromView(List<FloatingDebugController.DebugItem> items, View v) {
|
||||
if (v instanceof FloatingDebugProvider) {
|
||||
items.addAll(((FloatingDebugProvider) v).onGetDebugItems());
|
||||
}
|
||||
if (v instanceof ViewGroup) {
|
||||
ViewGroup vg = (ViewGroup) v;
|
||||
for (int i = 0; i < vg.getChildCount(); i++) {
|
||||
observeDebugItemsFromView(items, vg.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private View findScrollingChild(ViewGroup parent, float x, float y) {
|
||||
int n = parent.getChildCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
@ -2322,34 +2363,4 @@ public class ActionBarLayout extends FrameLayout {
|
|||
return null;
|
||||
}
|
||||
|
||||
private class StartColorsProvider implements Theme.ResourcesProvider {
|
||||
|
||||
HashMap<String, Integer> colors = new HashMap<>();
|
||||
|
||||
String[] keysToSave = new String[]{
|
||||
Theme.key_chat_outBubble,
|
||||
Theme.key_chat_outBubbleGradient1,
|
||||
Theme.key_chat_outBubbleGradient2,
|
||||
Theme.key_chat_outBubbleGradient3,
|
||||
Theme.key_chat_outBubbleGradientAnimated,
|
||||
Theme.key_chat_outBubbleShadow
|
||||
};
|
||||
|
||||
@Override
|
||||
public Integer getColor(String key) {
|
||||
return colors.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCurrentColor(String key) {
|
||||
return colors.get(key);
|
||||
}
|
||||
|
||||
public void saveColors(Theme.ResourcesProvider fragmentResourceProvider) {
|
||||
colors.clear();
|
||||
for (String key : keysToSave) {
|
||||
colors.put(key, fragmentResourceProvider.getCurrentColor(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ import android.transition.TransitionManager;
|
|||
import android.transition.TransitionSet;
|
||||
import android.transition.TransitionValues;
|
||||
import android.transition.Visibility;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Gravity;
|
||||
|
@ -60,7 +59,6 @@ import org.telegram.messenger.LocaleController;
|
|||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.XiaomiUtilities;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.Adapters.FiltersView;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
|
@ -78,6 +76,15 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
|
||||
private FrameLayout wrappedSearchFrameLayout;
|
||||
|
||||
public void setSearchPaddingStart(int padding) {
|
||||
searchItemPaddingStart = padding;
|
||||
if (searchContainer != null) {
|
||||
((MarginLayoutParams)searchContainer.getLayoutParams()).leftMargin = AndroidUtilities.dp(padding);
|
||||
searchContainer.setClipChildren(searchItemPaddingStart != 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ActionBarMenuItemSearchListener {
|
||||
public void onSearchExpand() {
|
||||
}
|
||||
|
@ -171,6 +178,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
private float transitionOffset;
|
||||
private View showSubMenuFrom;
|
||||
private final Theme.ResourcesProvider resourcesProvider;
|
||||
public int searchItemPaddingStart;
|
||||
|
||||
private OnClickListener onClickListener;
|
||||
|
||||
|
@ -711,9 +719,9 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
}
|
||||
});
|
||||
|
||||
// if (measurePopup) {
|
||||
container.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST));
|
||||
measurePopup = false;
|
||||
// if (measurePopup) {
|
||||
container.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST));
|
||||
measurePopup = false;
|
||||
//}
|
||||
processedPopupClick = false;
|
||||
popupWindow.setFocusable(true);
|
||||
|
@ -889,35 +897,35 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
ChangeBounds changeBounds = new ChangeBounds();
|
||||
changeBounds.setDuration(150);
|
||||
transition.addTransition(new Visibility() {
|
||||
@Override
|
||||
public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
|
||||
if (view instanceof SearchFilterView) {
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(
|
||||
ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1f)
|
||||
);
|
||||
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||
return set;
|
||||
}
|
||||
return ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1f);
|
||||
}
|
||||
@Override
|
||||
public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
|
||||
if (view instanceof SearchFilterView) {
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(
|
||||
ObjectAnimator.ofFloat(view, View.ALPHA, view.getAlpha(), 0f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_X, view.getScaleX(), 0.5f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_Y, view.getScaleX(), 0.5f)
|
||||
);
|
||||
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||
return set;
|
||||
}
|
||||
return ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0);
|
||||
}
|
||||
}.setDuration(150)).addTransition(changeBounds);
|
||||
@Override
|
||||
public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
|
||||
if (view instanceof SearchFilterView) {
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(
|
||||
ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1f)
|
||||
);
|
||||
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||
return set;
|
||||
}
|
||||
return ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1f);
|
||||
}
|
||||
@Override
|
||||
public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
|
||||
if (view instanceof SearchFilterView) {
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(
|
||||
ObjectAnimator.ofFloat(view, View.ALPHA, view.getAlpha(), 0f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_X, view.getScaleX(), 0.5f),
|
||||
ObjectAnimator.ofFloat(view, View.SCALE_Y, view.getScaleX(), 0.5f)
|
||||
);
|
||||
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||
return set;
|
||||
}
|
||||
return ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0);
|
||||
}
|
||||
}.setDuration(150)).addTransition(changeBounds);
|
||||
transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
|
||||
transition.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||
int selectedAccount = UserConfig.selectedAccount;
|
||||
|
@ -1194,7 +1202,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
searchField.layout(x, searchField.getTop(), x + searchField.getMeasuredWidth(), searchField.getBottom());
|
||||
}
|
||||
};
|
||||
searchContainer.setClipChildren(false);
|
||||
searchContainer.setClipChildren(searchItemPaddingStart != 0);
|
||||
wrappedSearchFrameLayout = null;
|
||||
if (wrapInScrollView) {
|
||||
wrappedSearchFrameLayout = new FrameLayout(getContext());
|
||||
|
@ -1232,11 +1240,11 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
};
|
||||
horizontalScrollView.addView(searchContainer, LayoutHelper.createScroll(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, 0));
|
||||
horizontalScrollView.setHorizontalScrollBarEnabled(false);
|
||||
horizontalScrollView.setClipChildren(false);
|
||||
horizontalScrollView.setClipChildren(searchItemPaddingStart != 0);
|
||||
wrappedSearchFrameLayout.addView(horizontalScrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 48, 0));
|
||||
parentMenu.addView(wrappedSearchFrameLayout, 0, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 0, 0, 0, 0));
|
||||
parentMenu.addView(wrappedSearchFrameLayout, 0, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, searchItemPaddingStart, 0, 0, 0));
|
||||
} else {
|
||||
parentMenu.addView(searchContainer, 0, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 6, 0, 0, 0));
|
||||
parentMenu.addView(searchContainer, 0, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, searchItemPaddingStart + 6, 0, 0, 0));
|
||||
}
|
||||
searchContainer.setVisibility(GONE);
|
||||
|
||||
|
@ -1370,11 +1378,11 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
searchFilterLayout.setVisibility(View.VISIBLE);
|
||||
if (!LocaleController.isRTL) {
|
||||
searchContainer.addView(searchFieldCaption, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER_VERTICAL | Gravity.LEFT, 0, 5.5f, 0, 0));
|
||||
searchContainer.addView(searchField, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER_VERTICAL, 6, 0, 48, 0));
|
||||
searchContainer.addView(searchField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.CENTER_VERTICAL, 6, 0, wrapInScrollView ? 0 : 48, 0));
|
||||
searchContainer.addView(searchFilterLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.CENTER_VERTICAL, 0, 0, 48, 0));
|
||||
} else {
|
||||
searchContainer.addView(searchFilterLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.CENTER_VERTICAL, 0, 0, 48, 0));
|
||||
searchContainer.addView(searchField, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER_VERTICAL, 0, 0, wrapInScrollView ? 0 : 48, 0));
|
||||
searchContainer.addView(searchField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.CENTER_VERTICAL, 0, 0, wrapInScrollView ? 0 : 48, 0));
|
||||
searchContainer.addView(searchFieldCaption, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 5.5f, 48, 0));
|
||||
}
|
||||
searchFilterLayout.setClipChildren(false);
|
||||
|
|
|
@ -15,11 +15,13 @@ import android.animation.ObjectAnimator;
|
|||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextPaint;
|
||||
|
@ -38,17 +40,22 @@ import android.widget.LinearLayout;
|
|||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.LineProgressView;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.RLottieImageView;
|
||||
import org.telegram.ui.Components.RadialProgressView;
|
||||
import org.telegram.ui.Components.spoilers.SpoilersTextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public class AlertDialog extends Dialog implements Drawable.Callback {
|
||||
|
||||
|
@ -88,8 +95,10 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
private CharSequence message;
|
||||
private int topResId;
|
||||
private View topView;
|
||||
private boolean topAnimationIsNew;
|
||||
private int topAnimationId;
|
||||
private int topAnimationSize;
|
||||
private Map<String, Integer> topAnimationLayerColors;
|
||||
private int topHeight = 132;
|
||||
private Drawable topDrawable;
|
||||
private int topBackgroundColor;
|
||||
|
@ -139,7 +148,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
private ArrayList<AlertDialogCell> itemViews = new ArrayList<>();
|
||||
private float aspectRatio;
|
||||
private boolean dimEnabled = true;
|
||||
private float dimAlpha = 0.6f;
|
||||
private float dimAlpha = 0.5f;
|
||||
private boolean dimCustom = false;
|
||||
private final Theme.ResourcesProvider resourcesProvider;
|
||||
private boolean topAnimationAutoRepeat = true;
|
||||
|
@ -213,7 +222,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
|
||||
backgroundPaddings = new Rect();
|
||||
if (progressStyle != 3) {
|
||||
shadowDrawable = context.getResources().getDrawable(R.drawable.popup_fixed_alert).mutate();
|
||||
shadowDrawable = context.getResources().getDrawable(R.drawable.popup_fixed_alert3).mutate();
|
||||
shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY));
|
||||
shadowDrawable.getPadding(backgroundPaddings);
|
||||
}
|
||||
|
@ -354,7 +363,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
}
|
||||
}
|
||||
|
||||
setMeasuredDimension(width, maxContentHeight - availableHeight + getPaddingTop() + getPaddingBottom());
|
||||
setMeasuredDimension(width, maxContentHeight - availableHeight + getPaddingTop() + getPaddingBottom() - (topAnimationIsNew ? AndroidUtilities.dp(8) : 0));
|
||||
inLayout = false;
|
||||
|
||||
if (lastScreenWidth != AndroidUtilities.displaySize.x) {
|
||||
|
@ -468,11 +477,53 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
} else {
|
||||
topImageView.setAutoRepeat(topAnimationAutoRepeat);
|
||||
topImageView.setAnimation(topAnimationId, topAnimationSize, topAnimationSize);
|
||||
if (topAnimationLayerColors != null) {
|
||||
RLottieDrawable drawable = topImageView.getAnimatedDrawable();
|
||||
for (Map.Entry<String, Integer> en : topAnimationLayerColors.entrySet()) {
|
||||
drawable.setLayerColor(en.getKey(), en.getValue());
|
||||
}
|
||||
}
|
||||
topImageView.playAnimation();
|
||||
}
|
||||
topImageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
topImageView.setBackgroundDrawable(getContext().getResources().getDrawable(R.drawable.popup_fixed_top));
|
||||
topImageView.getBackground().setColorFilter(new PorterDuffColorFilter(topBackgroundColor, PorterDuff.Mode.MULTIPLY));
|
||||
if (topAnimationIsNew) {
|
||||
GradientDrawable d = new GradientDrawable();
|
||||
d.setColor(topBackgroundColor);
|
||||
d.setCornerRadius(AndroidUtilities.dp(128));
|
||||
topImageView.setBackground(new Drawable() {
|
||||
int size = topAnimationSize + AndroidUtilities.dp(52);
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
d.setBounds((int) ((topImageView.getWidth() - size) / 2f), (int) ((topImageView.getHeight() - size) / 2f), (int) ((topImageView.getWidth() + size) / 2f), (int) ((topImageView.getHeight() + size) / 2f));
|
||||
d.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
d.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
d.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return d.getOpacity();
|
||||
}
|
||||
});
|
||||
topHeight = 92;
|
||||
} else {
|
||||
topImageView.setBackgroundDrawable(getContext().getResources().getDrawable(R.drawable.popup_fixed_top));
|
||||
topImageView.getBackground().setColorFilter(new PorterDuffColorFilter(topBackgroundColor, PorterDuff.Mode.MULTIPLY));
|
||||
}
|
||||
if (topAnimationIsNew) {
|
||||
topImageView.setTranslationY(AndroidUtilities.dp(16));
|
||||
} else {
|
||||
topImageView.setTranslationY(0);
|
||||
}
|
||||
topImageView.setPadding(0, 0, 0, 0);
|
||||
containerView.addView(topImageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, topHeight, Gravity.LEFT | Gravity.TOP, -8, -8, 0, 0));
|
||||
} else if (topView != null) {
|
||||
|
@ -482,15 +533,15 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
|
||||
if (title != null) {
|
||||
titleContainer = new FrameLayout(getContext());
|
||||
containerView.addView(titleContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 0));
|
||||
containerView.addView(titleContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : 0, 24, 0, 24, 0));
|
||||
|
||||
titleTextView = new SpoilersTextView(getContext(), false);
|
||||
titleTextView.setText(title);
|
||||
titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
||||
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
titleTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||
titleContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 0, 19, 0, (subtitle != null ? 2 : (items != null ? 14 : 10))));
|
||||
titleTextView.setGravity((topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||
titleContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 0, 19, 0, topAnimationIsNew ? 4 : (subtitle != null ? 2 : (items != null ? 14 : 10))));
|
||||
}
|
||||
|
||||
if (secondTitle != null && title != null) {
|
||||
|
@ -544,7 +595,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
}
|
||||
|
||||
messageTextView = new SpoilersTextView(getContext(), false);
|
||||
messageTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||
messageTextView.setTextColor(getThemedColor(topAnimationIsNew ? Theme.key_windowBackgroundWhiteGrayText : Theme.key_dialogTextBlack));
|
||||
messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
messageTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy());
|
||||
messageTextView.setLinkTextColor(getThemedColor(Theme.key_dialogTextLink));
|
||||
|
@ -552,7 +603,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
messageTextView.setClickable(false);
|
||||
messageTextView.setEnabled(false);
|
||||
}
|
||||
messageTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||
messageTextView.setGravity((topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||
if (progressViewStyle == 1) {
|
||||
progressViewContainer = new FrameLayout(getContext());
|
||||
containerView.addView(progressViewContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44, Gravity.LEFT | Gravity.TOP, 23, title == null ? 24 : 0, 23, 24));
|
||||
|
@ -592,7 +643,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
progressView.setProgressColor(getThemedColor(Theme.key_dialog_inlineProgress));
|
||||
progressViewContainer.addView(progressView, LayoutHelper.createLinear(86, 86));
|
||||
} else {
|
||||
scrollContainer.addView(messageTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 0, 24, customView != null || items != null ? customViewOffset : 0));
|
||||
scrollContainer.addView(messageTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 0, 24, customView != null || items != null ? customViewOffset : 0));
|
||||
}
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
messageTextView.setText(message);
|
||||
|
@ -734,6 +785,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
}
|
||||
buttonsLayout.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
|
||||
containerView.addView(buttonsLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52));
|
||||
if (topAnimationIsNew) {
|
||||
buttonsLayout.setTranslationY(-AndroidUtilities.dp(8));
|
||||
}
|
||||
|
||||
if (positiveButtonText != null) {
|
||||
TextView textView = new TextView(getContext()) {
|
||||
|
@ -746,20 +800,20 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
@Override
|
||||
public void setTextColor(int color) {
|
||||
super.setTextColor(color);
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color));
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), color));
|
||||
}
|
||||
};
|
||||
textView.setMinWidth(AndroidUtilities.dp(64));
|
||||
textView.setTag(Dialog.BUTTON_POSITIVE);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
// textView.setLines(1);
|
||||
// textView.setSingleLine(true); //TODO
|
||||
textView.setText(positiveButtonText.toString().toUpperCase());
|
||||
textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0);
|
||||
textView.setText(positiveButtonText.toString());
|
||||
textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0);
|
||||
if (verticalButtons) {
|
||||
buttonsLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT));
|
||||
} else {
|
||||
|
@ -786,20 +840,20 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
@Override
|
||||
public void setTextColor(int color) {
|
||||
super.setTextColor(color);
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color));
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), color));
|
||||
}
|
||||
};
|
||||
textView.setMinWidth(AndroidUtilities.dp(64));
|
||||
textView.setTag(Dialog.BUTTON_NEGATIVE);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setSingleLine(true);
|
||||
textView.setText(negativeButtonText.toString().toUpperCase());
|
||||
textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0);
|
||||
textView.setText(negativeButtonText.toString());
|
||||
textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0);
|
||||
if (verticalButtons) {
|
||||
buttonsLayout.addView(textView, 0, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT));
|
||||
} else {
|
||||
|
@ -826,20 +880,20 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
@Override
|
||||
public void setTextColor(int color) {
|
||||
super.setTextColor(color);
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color));
|
||||
setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), color));
|
||||
}
|
||||
};
|
||||
textView.setMinWidth(AndroidUtilities.dp(64));
|
||||
textView.setTag(Dialog.BUTTON_NEUTRAL);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setSingleLine(true);
|
||||
textView.setText(neutralButtonText.toString().toUpperCase());
|
||||
textView.setBackground(Theme.getRoundRectSelectorDrawable(getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0);
|
||||
textView.setText(neutralButtonText.toString());
|
||||
textView.setBackground(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), getThemedColor(dialogButtonColorKey)));
|
||||
textView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0);
|
||||
if (verticalButtons) {
|
||||
buttonsLayout.addView(textView, 1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT));
|
||||
} else {
|
||||
|
@ -1296,10 +1350,20 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
|
|||
}
|
||||
|
||||
public Builder setTopAnimation(int resId, int size, boolean autoRepeat, int backgroundColor) {
|
||||
return setTopAnimation(resId, size, autoRepeat, backgroundColor, null);
|
||||
}
|
||||
|
||||
public Builder setTopAnimation(int resId, int size, boolean autoRepeat, int backgroundColor, Map<String, Integer> layerColors) {
|
||||
alertDialog.topAnimationId = resId;
|
||||
alertDialog.topAnimationSize = size;
|
||||
alertDialog.topAnimationAutoRepeat = autoRepeat;
|
||||
alertDialog.topBackgroundColor = backgroundColor;
|
||||
alertDialog.topAnimationLayerColors = layerColors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTopAnimationIsNew(boolean isNew) {
|
||||
alertDialog.topAnimationIsNew = isNew;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.app.Dialog;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
@ -62,7 +63,7 @@ public abstract class BaseFragment {
|
|||
protected int currentAccount = UserConfig.selectedAccount;
|
||||
|
||||
protected View fragmentView;
|
||||
protected ActionBarLayout parentLayout;
|
||||
protected INavigationLayout parentLayout;
|
||||
protected ActionBar actionBar;
|
||||
protected boolean inPreviewMode;
|
||||
protected boolean inMenuMode;
|
||||
|
@ -92,6 +93,18 @@ public abstract class BaseFragment {
|
|||
currentAccount = account;
|
||||
}
|
||||
|
||||
public boolean hasOwnBackground() {
|
||||
return hasOwnBackground;
|
||||
}
|
||||
|
||||
public void setHasOwnBackground(boolean hasOwnBackground) {
|
||||
this.hasOwnBackground = hasOwnBackground;
|
||||
}
|
||||
|
||||
public boolean getFragmentBeginToShow() {
|
||||
return fragmentBeginToShow;
|
||||
}
|
||||
|
||||
public ActionBar getActionBar() {
|
||||
return actionBar;
|
||||
}
|
||||
|
@ -100,6 +113,10 @@ public abstract class BaseFragment {
|
|||
return fragmentView;
|
||||
}
|
||||
|
||||
public void setFragmentView(View fragmentView) {
|
||||
this.fragmentView = fragmentView;
|
||||
}
|
||||
|
||||
public View createView(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
@ -136,7 +153,7 @@ public abstract class BaseFragment {
|
|||
return parentLayout != null && parentLayout.isInPassivePreviewMode();
|
||||
}
|
||||
|
||||
protected void setInPreviewMode(boolean value) {
|
||||
public void setInPreviewMode(boolean value) {
|
||||
inPreviewMode = value;
|
||||
if (actionBar != null) {
|
||||
if (inPreviewMode) {
|
||||
|
@ -147,18 +164,18 @@ public abstract class BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
protected void setInMenuMode(boolean value) {
|
||||
public void setInMenuMode(boolean value) {
|
||||
inMenuMode = value;
|
||||
}
|
||||
|
||||
protected void onPreviewOpenAnimationEnd() {
|
||||
public void onPreviewOpenAnimationEnd() {
|
||||
}
|
||||
|
||||
protected boolean hideKeyboardOnShow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void clearViews() {
|
||||
public void clearViews() {
|
||||
if (fragmentView != null) {
|
||||
ViewGroup parent = (ViewGroup) fragmentView.getParent();
|
||||
if (parent != null) {
|
||||
|
@ -185,16 +202,16 @@ public abstract class BaseFragment {
|
|||
parentLayout = null;
|
||||
}
|
||||
|
||||
protected void onRemoveFromParent() {
|
||||
public void onRemoveFromParent() {
|
||||
|
||||
}
|
||||
|
||||
public void setParentFragment(BaseFragment fragment) {
|
||||
setParentLayout(fragment.parentLayout);
|
||||
fragmentView = createView(parentLayout.getContext());
|
||||
fragmentView = createView(parentLayout.getView().getContext());
|
||||
}
|
||||
|
||||
protected void setParentLayout(ActionBarLayout layout) {
|
||||
public void setParentLayout(INavigationLayout layout) {
|
||||
if (parentLayout != layout) {
|
||||
parentLayout = layout;
|
||||
inBubbleMode = parentLayout != null && parentLayout.isInBubbleMode();
|
||||
|
@ -208,12 +225,12 @@ public abstract class BaseFragment {
|
|||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
if (parentLayout != null && parentLayout.getContext() != fragmentView.getContext()) {
|
||||
if (parentLayout != null && parentLayout.getView().getContext() != fragmentView.getContext()) {
|
||||
fragmentView = null;
|
||||
}
|
||||
}
|
||||
if (actionBar != null) {
|
||||
boolean differentParent = parentLayout != null && parentLayout.getContext() != actionBar.getContext();
|
||||
boolean differentParent = parentLayout != null && parentLayout.getView().getContext() != actionBar.getContext();
|
||||
if (actionBar.shouldAddToContainer() || differentParent) {
|
||||
ViewGroup parent = (ViewGroup) actionBar.getParent();
|
||||
if (parent != null) {
|
||||
|
@ -229,7 +246,7 @@ public abstract class BaseFragment {
|
|||
}
|
||||
}
|
||||
if (parentLayout != null && actionBar == null) {
|
||||
actionBar = createActionBar(parentLayout.getContext());
|
||||
actionBar = createActionBar(parentLayout.getView().getContext());
|
||||
if (actionBar != null) {
|
||||
actionBar.parentFragment = this;
|
||||
}
|
||||
|
@ -340,11 +357,23 @@ public abstract class BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
public void setPaused(boolean paused) {
|
||||
if (isPaused == paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (paused) {
|
||||
onPause();
|
||||
} else {
|
||||
onResume();
|
||||
}
|
||||
}
|
||||
|
||||
public BaseFragment getFragmentForAlert(int offset) {
|
||||
if (parentLayout == null || parentLayout.fragmentsStack.size() <= 1 + offset) {
|
||||
if (parentLayout == null || parentLayout.getFragmentStack().size() <= 1 + offset) {
|
||||
return this;
|
||||
}
|
||||
return parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2 - offset);
|
||||
return parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2 - offset);
|
||||
}
|
||||
|
||||
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
|
||||
|
@ -372,10 +401,10 @@ public abstract class BaseFragment {
|
|||
}
|
||||
|
||||
public boolean isLastFragment() {
|
||||
return parentLayout != null && !parentLayout.fragmentsStack.isEmpty() && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this;
|
||||
return parentLayout != null && parentLayout.getLastFragment() == this;
|
||||
}
|
||||
|
||||
public ActionBarLayout getParentLayout() {
|
||||
public INavigationLayout getParentLayout() {
|
||||
return parentLayout;
|
||||
}
|
||||
|
||||
|
@ -409,9 +438,13 @@ public abstract class BaseFragment {
|
|||
return allowPresentFragment() && parentLayout != null && parentLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, true, false, null);
|
||||
}
|
||||
|
||||
public boolean presentFragment(INavigationLayout.NavigationParams params) {
|
||||
return allowPresentFragment() && parentLayout != null && parentLayout.presentFragment(params);
|
||||
}
|
||||
|
||||
public Activity getParentActivity() {
|
||||
if (parentLayout != null) {
|
||||
return parentLayout.parentActivity;
|
||||
return parentLayout.getParentActivity();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -467,26 +500,26 @@ public abstract class BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
protected void onSlideProgress(boolean isOpen, float progress) {
|
||||
public void onSlideProgress(boolean isOpen, float progress) {
|
||||
|
||||
}
|
||||
|
||||
protected void onTransitionAnimationProgress(boolean isOpen, float progress) {
|
||||
public void onTransitionAnimationProgress(boolean isOpen, float progress) {
|
||||
|
||||
}
|
||||
|
||||
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
inTransitionAnimation = true;
|
||||
if (isOpen) {
|
||||
fragmentBeginToShow = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
inTransitionAnimation = false;
|
||||
}
|
||||
|
||||
protected void onBecomeFullyVisible() {
|
||||
public void onBecomeFullyVisible() {
|
||||
AccessibilityManager mgr = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
if (mgr.isEnabled()) {
|
||||
ActionBar actionBar = getActionBar();
|
||||
|
@ -499,15 +532,15 @@ public abstract class BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
protected int getPreviewHeight() {
|
||||
public int getPreviewHeight() {
|
||||
return LayoutHelper.MATCH_PARENT;
|
||||
}
|
||||
|
||||
protected void onBecomeFullyHidden() {
|
||||
public void onBecomeFullyHidden() {
|
||||
|
||||
}
|
||||
|
||||
protected AnimatorSet onCustomTransitionAnimation(boolean isOpen, final Runnable callback) {
|
||||
public AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -524,7 +557,7 @@ public abstract class BaseFragment {
|
|||
}
|
||||
|
||||
public Dialog showDialog(Dialog dialog, boolean allowInTransition, final Dialog.OnDismissListener onDismissListener) {
|
||||
if (dialog == null || parentLayout == null || parentLayout.animationInProgress || parentLayout.startedTracking || !allowInTransition && parentLayout.checkTransitionAnimation()) {
|
||||
if (dialog == null || parentLayout == null || parentLayout.isTransitionAnimationInProgress() || parentLayout.isSwipeInProgress() || !allowInTransition && parentLayout.checkTransitionAnimation()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
|
@ -669,7 +702,7 @@ public abstract class BaseFragment {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void prepareFragmentToSlide(boolean topFragment, boolean beginSlide) {
|
||||
public void prepareFragmentToSlide(boolean topFragment, boolean beginSlide) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -677,18 +710,18 @@ public abstract class BaseFragment {
|
|||
|
||||
}
|
||||
|
||||
public ActionBarLayout[] showAsSheet(BaseFragment fragment) {
|
||||
public INavigationLayout[] showAsSheet(BaseFragment fragment) {
|
||||
if (getParentActivity() == null) {
|
||||
return null;
|
||||
}
|
||||
ActionBarLayout[] actionBarLayout = new ActionBarLayout[]{new ActionBarLayout(getParentActivity())};
|
||||
INavigationLayout[] actionBarLayout = new INavigationLayout[]{INavigationLayout.newLayout(getParentActivity())};
|
||||
BottomSheet bottomSheet = new BottomSheet(getParentActivity(), true) {
|
||||
{
|
||||
actionBarLayout[0].init(new ArrayList<>());
|
||||
actionBarLayout[0].setFragmentStack(new ArrayList<>());
|
||||
actionBarLayout[0].addFragmentToStack(fragment);
|
||||
actionBarLayout[0].showLastFragment();
|
||||
actionBarLayout[0].setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
|
||||
containerView = actionBarLayout[0];
|
||||
actionBarLayout[0].getView().setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
|
||||
containerView = actionBarLayout[0].getView();
|
||||
setApplyBottomPadding(false);
|
||||
setApplyBottomPadding(false);
|
||||
setOnDismissListener(dialog -> fragment.onFragmentDestroy());
|
||||
|
@ -701,7 +734,7 @@ public abstract class BaseFragment {
|
|||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (actionBarLayout[0] == null || actionBarLayout[0].fragmentsStack.size() <= 1) {
|
||||
if (actionBarLayout[0] == null || actionBarLayout[0].getFragmentStack().size() <= 1) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
actionBarLayout[0].onBackPressed();
|
||||
|
@ -791,4 +824,8 @@ public abstract class BaseFragment {
|
|||
}
|
||||
return ColorUtils.calculateLuminance(color) > 0.7f;
|
||||
}
|
||||
|
||||
public void drawOverlay(Canvas canvas, View parent) {
|
||||
|
||||
}
|
||||
}
|
|
@ -1599,7 +1599,8 @@ public class BottomSheet extends Dialog {
|
|||
try {
|
||||
super.dismiss();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
//ignore: not attached to window manager
|
||||
FileLog.e(e, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public class DrawerLayoutContainer extends FrameLayout {
|
|||
private static final int MIN_DRAWER_MARGIN = 64;
|
||||
|
||||
private ViewGroup drawerLayout;
|
||||
private ActionBarLayout parentActionBarLayout;
|
||||
private INavigationLayout parentActionBarLayout;
|
||||
|
||||
private boolean maybeStartTracking;
|
||||
private boolean startedTracking;
|
||||
|
@ -204,8 +204,8 @@ public class DrawerLayoutContainer extends FrameLayout {
|
|||
if (drawerLayout.getVisibility() != newVisibility) {
|
||||
drawerLayout.setVisibility(newVisibility);
|
||||
}
|
||||
if (!parentActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
BaseFragment currentFragment = parentActionBarLayout.fragmentsStack.get(0);
|
||||
if (!parentActionBarLayout.getFragmentStack().isEmpty()) {
|
||||
BaseFragment currentFragment = parentActionBarLayout.getFragmentStack().get(0);
|
||||
if (drawerPosition == drawerLayout.getMeasuredWidth()) {
|
||||
currentFragment.setProgressToDrawerOpened(1f);
|
||||
} else if (drawerPosition == 0) {
|
||||
|
@ -233,8 +233,8 @@ public class DrawerLayoutContainer extends FrameLayout {
|
|||
if (!allowOpenDrawer || drawerLayout == null) {
|
||||
return;
|
||||
}
|
||||
if (AndroidUtilities.isTablet() && parentActionBarLayout != null && parentActionBarLayout.parentActivity != null) {
|
||||
AndroidUtilities.hideKeyboard(parentActionBarLayout.parentActivity.getCurrentFocus());
|
||||
if (AndroidUtilities.isTablet() && parentActionBarLayout != null && parentActionBarLayout.getParentActivity() != null) {
|
||||
AndroidUtilities.hideKeyboard(parentActionBarLayout.getParentActivity().getCurrentFocus());
|
||||
}
|
||||
cancelCurrentAnimation();
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
|
@ -307,7 +307,7 @@ public class DrawerLayoutContainer extends FrameLayout {
|
|||
return drawerLayout;
|
||||
}
|
||||
|
||||
public void setParentActionBarLayout(ActionBarLayout layout) {
|
||||
public void setParentActionBarLayout(INavigationLayout layout) {
|
||||
parentActionBarLayout = layout;
|
||||
}
|
||||
|
||||
|
@ -432,13 +432,13 @@ public class DrawerLayoutContainer extends FrameLayout {
|
|||
return true;
|
||||
}
|
||||
|
||||
if ((allowOpenDrawerBySwipe || drawerOpened) && allowOpenDrawer && parentActionBarLayout.fragmentsStack.size() == 1) {
|
||||
if ((allowOpenDrawerBySwipe || drawerOpened) && allowOpenDrawer && parentActionBarLayout.getFragmentStack().size() == 1) {
|
||||
if (ev != null && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) && !startedTracking && !maybeStartTracking) {
|
||||
View scrollingChild = findScrollingChild(this, ev.getX(),ev.getY());
|
||||
if (scrollingChild != null) {
|
||||
return false;
|
||||
}
|
||||
parentActionBarLayout.getHitRect(rect);
|
||||
parentActionBarLayout.getView().getHitRect(rect);
|
||||
startedTrackingX = (int) ev.getX();
|
||||
startedTrackingY = (int) ev.getY();
|
||||
if (rect.contains(startedTrackingX, startedTrackingY)) {
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
package org.telegram.ui.ActionBar;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.ui.Components.BackButtonMenu;
|
||||
import org.telegram.ui.LNavigation.LNavigation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public interface INavigationLayout {
|
||||
int REBUILD_FLAG_REBUILD_LAST = 1, REBUILD_FLAG_REBUILD_ONLY_LAST = 2;
|
||||
|
||||
boolean presentFragment(NavigationParams params);
|
||||
boolean checkTransitionAnimation();
|
||||
boolean addFragmentToStack(BaseFragment fragment, int position);
|
||||
void removeFragmentFromStack(BaseFragment fragment);
|
||||
List<BaseFragment> getFragmentStack();
|
||||
void setDelegate(INavigationLayoutDelegate INavigationLayoutDelegate);
|
||||
void closeLastFragment(boolean animated, boolean forceNoAnimation);
|
||||
DrawerLayoutContainer getDrawerLayoutContainer();
|
||||
void setDrawerLayoutContainer(DrawerLayoutContainer drawerLayoutContainer);
|
||||
void setRemoveActionBarExtraHeight(boolean removeExtraHeight);
|
||||
void setTitleOverlayText(String title, int titleId, Runnable action);
|
||||
void animateThemedValues(ThemeAnimationSettings settings, Runnable onDone);
|
||||
float getThemeAnimationValue();
|
||||
void setFragmentStackChangedListener(Runnable onFragmentStackChanged);
|
||||
boolean isTransitionAnimationInProgress();
|
||||
void resumeDelayedFragmentAnimation();
|
||||
|
||||
boolean isInPassivePreviewMode();
|
||||
void setInBubbleMode(boolean bubbleMode);
|
||||
boolean isInBubbleMode();
|
||||
|
||||
boolean isInPreviewMode();
|
||||
boolean isPreviewOpenAnimationInProgress();
|
||||
void movePreviewFragment(float dy);
|
||||
void expandPreviewFragment();
|
||||
void finishPreviewFragment();
|
||||
void setFragmentPanTranslationOffset(int offset);
|
||||
ViewGroup getOverlayContainerView();
|
||||
void setHighlightActionButtons(boolean highlight);
|
||||
float getCurrentPreviewFragmentAlpha();
|
||||
void drawCurrentPreviewFragment(Canvas canvas, Drawable foregroundDrawable);
|
||||
|
||||
void drawHeaderShadow(Canvas canvas, int alpha, int y);
|
||||
|
||||
boolean isSwipeInProgress();
|
||||
|
||||
void onPause();
|
||||
void onResume();
|
||||
void onBackPressed();
|
||||
void onUserLeaveHint();
|
||||
void onLowMemory();
|
||||
boolean extendActionMode(Menu menu);
|
||||
void onActionModeStarted(Object mode);
|
||||
void onActionModeFinished(Object mode);
|
||||
void startActivityForResult(Intent intent, int requestCode);
|
||||
|
||||
// TODO: Migrate them to be out of navigation layout
|
||||
Theme.MessageDrawable getMessageDrawableOutStart();
|
||||
Theme.MessageDrawable getMessageDrawableOutMediaStart();
|
||||
|
||||
// TODO: Make something like FieldsContainer and put them there?
|
||||
List<BackButtonMenu.PulledDialog> getPulledDialogs();
|
||||
void setPulledDialogs(List<BackButtonMenu.PulledDialog> pulledDialogs);
|
||||
|
||||
static INavigationLayout newLayout(Context context) {
|
||||
return SharedConfig.useLNavigation ? new LNavigation(context) : new ActionBarLayout(context);
|
||||
}
|
||||
|
||||
default boolean hasIntegratedBlurInPreview() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default void rebuildFragments(int flags) {
|
||||
if ((flags & REBUILD_FLAG_REBUILD_ONLY_LAST) != 0) {
|
||||
showLastFragment();
|
||||
return;
|
||||
}
|
||||
boolean last = (flags & REBUILD_FLAG_REBUILD_LAST) != 0;
|
||||
rebuildAllFragmentViews(last, last);
|
||||
}
|
||||
|
||||
default void setBackgroundView(View backgroundView) {
|
||||
// Not always required
|
||||
}
|
||||
|
||||
default void setUseAlphaAnimations(boolean useAlphaAnimations) {
|
||||
// Not always required
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Should be replaced with {@link INavigationLayout#rebuildFragments(int)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void rebuildLogout() {
|
||||
// No-op usually, can contain hackfixes
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Should be replaced with {@link INavigationLayout#rebuildFragments(int)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void showLastFragment() {}
|
||||
|
||||
/**
|
||||
* @deprecated Should be replaced with {@link INavigationLayout#rebuildFragments(int)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void rebuildAllFragmentViews(boolean last, boolean showLastAfter) {}
|
||||
|
||||
default void drawHeaderShadow(Canvas canvas, int y) {
|
||||
drawHeaderShadow(canvas, 0xFF, y);
|
||||
}
|
||||
|
||||
default BaseFragment getBackgroundFragment() {
|
||||
return getFragmentStack().size() <= 1 ? null : getFragmentStack().get(getFragmentStack().size() - 2);
|
||||
}
|
||||
|
||||
default BaseFragment getLastFragment() {
|
||||
return getFragmentStack().isEmpty() ? null : getFragmentStack().get(getFragmentStack().size() - 1);
|
||||
}
|
||||
|
||||
default void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
||||
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), null);
|
||||
}
|
||||
|
||||
default void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant, Runnable onDone) {
|
||||
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), onDone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in favor of {@link INavigationLayout#bringToFront(int)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void showFragment(int i) {
|
||||
bringToFront(i);
|
||||
}
|
||||
|
||||
default void bringToFront(int i) {
|
||||
BaseFragment fragment = getFragmentStack().get(i);
|
||||
removeFragmentFromStack(fragment);
|
||||
addFragmentToStack(fragment);
|
||||
rebuildFragments(REBUILD_FLAG_REBUILD_ONLY_LAST);
|
||||
}
|
||||
|
||||
default void removeAllFragments() {
|
||||
for (BaseFragment fragment : new ArrayList<>(getFragmentStack())) {
|
||||
removeFragmentFromStack(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
default Activity getParentActivity() {
|
||||
Context ctx = getView().getContext();
|
||||
if (ctx instanceof Activity) {
|
||||
return (Activity) ctx;
|
||||
}
|
||||
throw new IllegalArgumentException("NavigationLayout added in non-activity context!");
|
||||
}
|
||||
|
||||
default ViewGroup getView() {
|
||||
if (this instanceof ViewGroup) {
|
||||
return (ViewGroup) this;
|
||||
}
|
||||
throw new IllegalArgumentException("You should override getView() if you're not inheriting from it.");
|
||||
}
|
||||
|
||||
default void closeLastFragment() {
|
||||
closeLastFragment(true);
|
||||
}
|
||||
|
||||
default void closeLastFragment(boolean animated) {
|
||||
closeLastFragment(animated, false);
|
||||
}
|
||||
|
||||
default void setFragmentStack(List<BaseFragment> stack) {
|
||||
init(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method was replaced with {@link INavigationLayout#setFragmentStack(List)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void init(List<BaseFragment> stack) {
|
||||
throw new RuntimeException("Neither setFragmentStack(...) or init(...) were overriden!");
|
||||
}
|
||||
|
||||
default void removeFragmentFromStack(int i) {
|
||||
if (i < 0 || i >= getFragmentStack().size()) {
|
||||
return;
|
||||
}
|
||||
removeFragmentFromStack(getFragmentStack().get(i));
|
||||
}
|
||||
|
||||
default boolean addFragmentToStack(BaseFragment fragment) {
|
||||
return addFragmentToStack(fragment, -1);
|
||||
}
|
||||
|
||||
default boolean presentFragment(BaseFragment fragment) {
|
||||
return presentFragment(new NavigationParams(fragment));
|
||||
}
|
||||
|
||||
default boolean presentFragment(BaseFragment fragment, boolean removeLast) {
|
||||
return presentFragment(new NavigationParams(fragment).setRemoveLast(removeLast));
|
||||
}
|
||||
|
||||
default boolean presentFragmentAsPreview(BaseFragment fragment) {
|
||||
return presentFragment(new NavigationParams(fragment).setPreview(true));
|
||||
}
|
||||
|
||||
default boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, ActionBarPopupWindow.ActionBarPopupWindowLayout menuView) {
|
||||
return presentFragment(new NavigationParams(fragment).setPreview(true).setMenuView(menuView));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated You should use {@link INavigationLayout.NavigationParams} for advanced params
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean presentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, boolean check, boolean preview) {
|
||||
return presentFragment(new NavigationParams(fragment).setRemoveLast(removeLast).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(check).setPreview(preview));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated You should use {@link INavigationLayout.NavigationParams} for advanced params
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean presentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, boolean check, boolean preview, ActionBarPopupWindow.ActionBarPopupWindowLayout menuView) {
|
||||
return presentFragment(new NavigationParams(fragment).setRemoveLast(removeLast).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(check).setPreview(preview).setMenuView(menuView));
|
||||
}
|
||||
|
||||
default void dismissDialogs() {
|
||||
List<BaseFragment> fragmentsStack = getFragmentStack();
|
||||
if (!fragmentsStack.isEmpty()) {
|
||||
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
lastFragment.dismissCurrentDialog();
|
||||
}
|
||||
}
|
||||
|
||||
interface INavigationLayoutDelegate {
|
||||
default boolean needPresentFragment(INavigationLayout layout, NavigationParams params) {
|
||||
return needPresentFragment(params.fragment, params.removeLast, params.noAnimation, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated You should override {@link INavigationLayoutDelegate#needPresentFragment(INavigationLayout, NavigationParams)} for more fields
|
||||
*/
|
||||
default boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, INavigationLayout layout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean needAddFragmentToStack(BaseFragment fragment, INavigationLayout layout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean onPreIme() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean needCloseLastFragment(INavigationLayout layout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void onMeasureOverride(int[] measureSpec) {}
|
||||
default void onRebuildAllFragments(INavigationLayout layout, boolean last) {}
|
||||
default void onThemeProgress(float progress) {}
|
||||
}
|
||||
|
||||
class NavigationParams {
|
||||
public BaseFragment fragment;
|
||||
public boolean removeLast;
|
||||
public boolean noAnimation;
|
||||
public boolean checkPresentFromDelegate = true;
|
||||
public boolean preview;
|
||||
public ActionBarPopupWindow.ActionBarPopupWindowLayout menuView;
|
||||
public boolean needDelayWithoutAnimation;
|
||||
|
||||
public boolean isFromDelay;
|
||||
public boolean delayDone;
|
||||
|
||||
public NavigationParams(BaseFragment fragment) {
|
||||
this.fragment = fragment;
|
||||
}
|
||||
|
||||
public NavigationParams setRemoveLast(boolean removeLast) {
|
||||
this.removeLast = removeLast;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationParams setNoAnimation(boolean noAnimation) {
|
||||
this.noAnimation = noAnimation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationParams setCheckPresentFromDelegate(boolean checkPresentFromDelegate) {
|
||||
this.checkPresentFromDelegate = checkPresentFromDelegate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationParams setPreview(boolean preview) {
|
||||
this.preview = preview;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationParams setMenuView(ActionBarPopupWindow.ActionBarPopupWindowLayout menuView) {
|
||||
this.menuView = menuView;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NavigationParams setNeedDelayWithoutAnimation(boolean needDelayWithoutAnimation) {
|
||||
this.needDelayWithoutAnimation = needDelayWithoutAnimation;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class ThemeAnimationSettings {
|
||||
public final Theme.ThemeInfo theme;
|
||||
public final int accentId;
|
||||
public final boolean nightTheme;
|
||||
public final boolean instant;
|
||||
public boolean onlyTopFragment;
|
||||
public boolean applyTheme = true;
|
||||
public Runnable afterStartDescriptionsAddedRunnable;
|
||||
public Runnable beforeAnimationRunnable;
|
||||
public Runnable afterAnimationRunnable;
|
||||
public onAnimationProgress animationProgress;
|
||||
public long duration = 200;
|
||||
public Theme.ResourcesProvider resourcesProvider;
|
||||
|
||||
public ThemeAnimationSettings(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
||||
this.theme = theme;
|
||||
this.accentId = accentId;
|
||||
this.nightTheme = nightTheme;
|
||||
this.instant = instant;
|
||||
}
|
||||
|
||||
public interface onAnimationProgress {
|
||||
void setProgress(float p);
|
||||
}
|
||||
}
|
||||
|
||||
class StartColorsProvider implements Theme.ResourcesProvider {
|
||||
HashMap<String, Integer> colors = new HashMap<>();
|
||||
String[] keysToSave = new String[] {
|
||||
Theme.key_chat_outBubble,
|
||||
Theme.key_chat_outBubbleGradient1,
|
||||
Theme.key_chat_outBubbleGradient2,
|
||||
Theme.key_chat_outBubbleGradient3,
|
||||
Theme.key_chat_outBubbleGradientAnimated,
|
||||
Theme.key_chat_outBubbleShadow
|
||||
};
|
||||
|
||||
@Override
|
||||
public Integer getColor(String key) {
|
||||
return colors.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCurrentColor(String key) {
|
||||
return colors.get(key);
|
||||
}
|
||||
|
||||
public void saveColors(Theme.ResourcesProvider fragmentResourceProvider) {
|
||||
colors.clear();
|
||||
for (String key : keysToSave) {
|
||||
colors.put(key, fragmentResourceProvider.getCurrentColor(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,14 +27,11 @@ import android.text.SpannableStringBuilder;
|
|||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import androidx.core.math.MathUtils;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.Emoji;
|
||||
import org.telegram.ui.Cells.DialogCell;
|
||||
|
@ -71,6 +68,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
private int rightDrawableTopPadding;
|
||||
private boolean buildFullLayout;
|
||||
private float fullAlpha;
|
||||
private boolean widthWrapContent;
|
||||
|
||||
private Drawable wrapBackgroundDrawable;
|
||||
|
||||
|
@ -82,6 +80,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
private Paint fadePaint;
|
||||
private Paint fadePaintBack;
|
||||
private Paint fadeEllpsizePaint;
|
||||
private int fadeEllpsizePaintWidth;
|
||||
private int lastWidth;
|
||||
|
||||
private int offsetX;
|
||||
|
@ -95,6 +94,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
|
||||
private boolean rightDrawableOutside;
|
||||
private boolean ellipsizeByGradient;
|
||||
private int ellipsizeByGradientWidthDp = 16;
|
||||
private int paddingRight;
|
||||
|
||||
private int minWidth;
|
||||
|
@ -124,6 +124,8 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
private AnimatedEmojiSpan.EmojiGroupedSpans emojiStack;
|
||||
private boolean attachedToWindow;
|
||||
|
||||
private Layout.Alignment mAlignment = Layout.Alignment.ALIGN_NORMAL;
|
||||
|
||||
public SimpleTextView(Context context) {
|
||||
super(context);
|
||||
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
@ -196,6 +198,16 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
updateFadePaints();
|
||||
}
|
||||
|
||||
public void setEllipsizeByGradient(int value) {
|
||||
setEllipsizeByGradient(true);
|
||||
ellipsizeByGradientWidthDp = value;
|
||||
updateFadePaints();
|
||||
}
|
||||
|
||||
public void setWidthWrapContent(boolean value) {
|
||||
widthWrapContent = value;
|
||||
}
|
||||
|
||||
private void updateFadePaints() {
|
||||
if ((fadePaint == null || fadePaintBack == null) && scrollNonFitText) {
|
||||
fadePaint = new Paint();
|
||||
|
@ -206,9 +218,9 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
fadePaintBack.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(6), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
|
||||
fadePaintBack.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
|
||||
}
|
||||
if (fadeEllpsizePaint == null && ellipsizeByGradient) {
|
||||
if ((fadeEllpsizePaint == null || fadeEllpsizePaintWidth != AndroidUtilities.dp(ellipsizeByGradientWidthDp)) && ellipsizeByGradient) {
|
||||
fadeEllpsizePaint = new Paint();
|
||||
fadeEllpsizePaint.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(16), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
|
||||
fadeEllpsizePaint.setShader(new LinearGradient(0, 0, fadeEllpsizePaintWidth = AndroidUtilities.dp(ellipsizeByGradientWidthDp), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
|
||||
fadeEllpsizePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
|
||||
}
|
||||
}
|
||||
|
@ -325,7 +337,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
string = TextUtils.ellipsize(string, textPaint, width, TextUtils.TruncateAt.END);
|
||||
}
|
||||
if (!ellipsizeByGradient && !string.equals(text)) {
|
||||
fullLayout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, fullTextMaxLines, false);
|
||||
fullLayout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, getAlignment(), 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, fullTextMaxLines, false);
|
||||
if (fullLayout != null) {
|
||||
int end = fullLayout.getLineEnd(0);
|
||||
int start = fullLayout.getLineStart(1);
|
||||
|
@ -338,22 +350,22 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
} else {
|
||||
part = "…";
|
||||
}
|
||||
firstLineLayout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
layout = new StaticLayout(substr, 0, substr.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
firstLineLayout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), getAlignment(), 1.0f, 0.0f, false);
|
||||
layout = new StaticLayout(substr, 0, substr.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), getAlignment(), 1.0f, 0.0f, false);
|
||||
if (layout.getLineLeft(0) != 0) {
|
||||
part = "\u200F" + part;
|
||||
}
|
||||
partLayout = new StaticLayout(part, 0, part.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
fullLayout = StaticLayoutEx.createStaticLayout(full, 0, full.length(), textPaint, width + AndroidUtilities.dp(8) + fullLayoutAdditionalWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width + fullLayoutAdditionalWidth, fullTextMaxLines, false);
|
||||
partLayout = new StaticLayout(part, 0, part.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), getAlignment(), 1.0f, 0.0f, false);
|
||||
fullLayout = StaticLayoutEx.createStaticLayout(full, 0, full.length(), textPaint, width + AndroidUtilities.dp(8) + fullLayoutAdditionalWidth, getAlignment(), 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width + fullLayoutAdditionalWidth, fullTextMaxLines, false);
|
||||
}
|
||||
} else {
|
||||
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), getAlignment(), 1.0f, 0.0f, false);
|
||||
fullLayout = null;
|
||||
partLayout = null;
|
||||
firstLineLayout = null;
|
||||
}
|
||||
} else if (maxLines > 1) {
|
||||
layout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, maxLines, false);
|
||||
layout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, getAlignment(), 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, maxLines, false);
|
||||
} else {
|
||||
CharSequence string;
|
||||
if (scrollNonFitText || ellipsizeByGradient) {
|
||||
|
@ -365,7 +377,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
calcOffset(width);
|
||||
return false;
|
||||
}*/
|
||||
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), getAlignment(), 1.0f, 0.0f, false);
|
||||
}
|
||||
|
||||
spoilersPool.addAll(spoilers);
|
||||
|
@ -390,6 +402,15 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void setAlignment(Layout.Alignment alignment) {
|
||||
mAlignment = alignment;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
private Layout.Alignment getAlignment() {
|
||||
return mAlignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
@ -407,6 +428,10 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
} else {
|
||||
finalHeight = getPaddingTop() + textHeight + getPaddingBottom();
|
||||
}
|
||||
if (widthWrapContent) {
|
||||
// textWidth = (int) Math.ceil(layout.getLineWidth(0));
|
||||
width = Math.min(width, getPaddingLeft() + textWidth + getPaddingRight() + minusWidth + (rightDrawableOutside && rightDrawable != null ? rightDrawable.getIntrinsicWidth() + drawablePadding : 0));
|
||||
}
|
||||
setMeasuredDimension(width, finalHeight);
|
||||
|
||||
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
|
||||
|
@ -632,7 +657,10 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
}
|
||||
|
||||
public void setRightPadding(int padding) {
|
||||
paddingRight = padding;
|
||||
if (paddingRight != padding) {
|
||||
paddingRight = padding;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -803,10 +831,10 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
canvas.translate(getMaxTextWidth() - paddingRight - AndroidUtilities.dp(6), 0);
|
||||
canvas.drawRect(0, 0, AndroidUtilities.dp(6), getMeasuredHeight(), fadePaintBack);
|
||||
canvas.restore();
|
||||
} else if (ellipsizeByGradient && fadeEllpsizePaint != null) {
|
||||
} else if (ellipsizeByGradient && (!widthWrapContent || textDoesNotFit) && fadeEllpsizePaint != null) {
|
||||
canvas.save();
|
||||
canvas.translate(getMaxTextWidth() - paddingRight - AndroidUtilities.dp(rightDrawable != null && !(rightDrawable instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) && rightDrawableOutside ? 18 : 16), 0);
|
||||
canvas.drawRect(0, 0, AndroidUtilities.dp(16), getMeasuredHeight(), fadeEllpsizePaint);
|
||||
canvas.translate(getMaxTextWidth() - paddingRight - fadeEllpsizePaintWidth - AndroidUtilities.dp(rightDrawable != null && !(rightDrawable instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) && rightDrawableOutside ? +2 : 0), 0);
|
||||
canvas.drawRect(0, 0, fadeEllpsizePaintWidth, getMeasuredHeight(), fadeEllpsizePaint);
|
||||
canvas.restore();
|
||||
}
|
||||
updateScrollAnimation();
|
||||
|
|
|
@ -170,6 +170,10 @@ public class Theme {
|
|||
public boolean isSelected;
|
||||
private Path path;
|
||||
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
private Rect backupRect = new Rect();
|
||||
|
||||
private final ResourcesProvider resourcesProvider;
|
||||
|
@ -183,6 +187,7 @@ public class Theme {
|
|||
public static MotionBackgroundDrawable[] motionBackground = new MotionBackgroundDrawable[3];
|
||||
|
||||
private int[] currentShadowDrawableRadius = new int[]{-1, -1, -1, -1};
|
||||
private Bitmap[] shadowDrawableBitmap = new Bitmap[4];
|
||||
private Drawable[] shadowDrawable = new Drawable[4];
|
||||
private int[] shadowDrawableColor = new int[]{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
|
||||
|
||||
|
@ -212,6 +217,8 @@ public class Theme {
|
|||
|
||||
PathDrawParams pathDrawCacheParams;
|
||||
private int overrideRoundRadius;
|
||||
private float overrideRounding;
|
||||
public boolean forceInvalidatePath;
|
||||
|
||||
public MessageDrawable(int type, boolean out, boolean selected) {
|
||||
this(type, out, selected, null);
|
||||
|
@ -430,7 +437,14 @@ public class Theme {
|
|||
}
|
||||
|
||||
public Drawable getBackgroundDrawable() {
|
||||
int newRad = AndroidUtilities.dp(SharedConfig.bubbleRadius);
|
||||
int newRad;
|
||||
if (overrideRoundRadius != 0) {
|
||||
newRad = overrideRoundRadius;
|
||||
} else if (overrideRounding > 0) {
|
||||
newRad = 0;
|
||||
} else {
|
||||
newRad = AndroidUtilities.dp(SharedConfig.bubbleRadius);
|
||||
}
|
||||
int idx;
|
||||
if (isTopNear && isBottomNear) {
|
||||
idx = 3;
|
||||
|
@ -557,6 +571,9 @@ public class Theme {
|
|||
boolean forceSetColor = false;
|
||||
if (currentShadowDrawableRadius[idx] != newRad) {
|
||||
currentShadowDrawableRadius[idx] = newRad;
|
||||
if (shadowDrawableBitmap[idx] != null) {
|
||||
shadowDrawableBitmap[idx].recycle();
|
||||
}
|
||||
try {
|
||||
Bitmap bitmap = Bitmap.createBitmap(dp(50), dp(40), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
@ -582,6 +599,7 @@ public class Theme {
|
|||
draw(canvas, shadowPaint);
|
||||
}
|
||||
|
||||
shadowDrawableBitmap[idx] = bitmap;
|
||||
shadowDrawable[idx] = new NinePatchDrawable(bitmap, getByteBuffer(bitmap.getWidth() / 2 - 1, bitmap.getWidth() / 2 + 1, bitmap.getHeight() / 2 - 1, bitmap.getHeight() / 2 + 1).array(), new Rect(), null);
|
||||
forceSetColor = true;
|
||||
} catch (Throwable ignore) {
|
||||
|
@ -596,6 +614,20 @@ public class Theme {
|
|||
return shadowDrawable[idx];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
|
||||
for (Bitmap bitmap : shadowDrawableBitmap) {
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
}
|
||||
Arrays.fill(shadowDrawableBitmap, null);
|
||||
Arrays.fill(shadowDrawable, null);
|
||||
Arrays.fill(currentShadowDrawableRadius, -1);
|
||||
}
|
||||
|
||||
private static ByteBuffer getByteBuffer(int x1, int x2, int y1, int y2) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(4 + 4 * 7 + 4 * 2 + 4 * 2 + 4 * 9).order(ByteOrder.nativeOrder());
|
||||
buffer.put((byte) 0x01);
|
||||
|
@ -662,7 +694,7 @@ public class Theme {
|
|||
|
||||
public void draw(Canvas canvas, Paint paintToUse) {
|
||||
Rect bounds = getBounds();
|
||||
if (paintToUse == null && gradientShader == null) {
|
||||
if (paintToUse == null && gradientShader == null && overrideRoundRadius == 0 && overrideRounding <= 0) {
|
||||
Drawable background = getBackgroundDrawable();
|
||||
if (background != null) {
|
||||
background.setBounds(bounds);
|
||||
|
@ -676,12 +708,15 @@ public class Theme {
|
|||
if (overrideRoundRadius != 0) {
|
||||
rad = overrideRoundRadius;
|
||||
nearRad = overrideRoundRadius;
|
||||
} else if (overrideRounding > 0) {
|
||||
rad = AndroidUtilities.lerp(dp(SharedConfig.bubbleRadius), Math.min(bounds.width(), bounds.height()) / 2, overrideRounding);
|
||||
nearRad = AndroidUtilities.lerp(dp(Math.min(6, SharedConfig.bubbleRadius)), Math.min(bounds.width(), bounds.height()) / 2, overrideRounding);
|
||||
} else if (currentType == TYPE_PREVIEW) {
|
||||
rad = dp(6);
|
||||
nearRad = dp(6);
|
||||
} else {
|
||||
rad = dp(SharedConfig.bubbleRadius);
|
||||
nearRad = dp(Math.min(5, SharedConfig.bubbleRadius));
|
||||
nearRad = dp(Math.min(6, SharedConfig.bubbleRadius));
|
||||
}
|
||||
int smallRad = dp(6);
|
||||
|
||||
|
@ -712,8 +747,8 @@ public class Theme {
|
|||
path = this.path;
|
||||
invalidatePath = true;
|
||||
}
|
||||
if (invalidatePath) {
|
||||
path.reset();
|
||||
if (invalidatePath || overrideRoundRadius != 0) {
|
||||
path.rewind();
|
||||
if (isOut) {
|
||||
if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) {
|
||||
if (currentType == TYPE_MEDIA) {
|
||||
|
@ -888,6 +923,10 @@ public class Theme {
|
|||
this.overrideRoundRadius = radius;
|
||||
}
|
||||
|
||||
public void setRoundingRadius(float rounding) {
|
||||
this.overrideRounding = rounding;
|
||||
}
|
||||
|
||||
public static class PathDrawParams {
|
||||
Path path = new Path();
|
||||
Rect lastRect = new Rect();
|
||||
|
@ -901,6 +940,10 @@ public class Theme {
|
|||
lastRect.set(bounds);
|
||||
return invalidate;
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2366,6 +2409,21 @@ public class Theme {
|
|||
themeAccent.backgroundRotation = patternRotations[a];
|
||||
themeAccent.patternSlug = patternSlugs[a];
|
||||
}
|
||||
|
||||
//override default themes
|
||||
if (isHome(themeAccent) && name.equals("Dark Blue") || name.equals("Night")) {
|
||||
themeAccent.myMessagesAccentColor = 0xff6573f8;
|
||||
themeAccent.myMessagesGradientAccentColor1 = 0xff7644cb;
|
||||
themeAccent.myMessagesGradientAccentColor2 = 0xff8849b4;
|
||||
themeAccent.myMessagesGradientAccentColor3 = 0xffa751a8;
|
||||
if (name.equals("Night")) {
|
||||
themeAccent.patternIntensity = -0.57f;
|
||||
themeAccent.backgroundOverrideColor = 0xff6c7fa6;
|
||||
themeAccent.backgroundGradientOverrideColor1 = 0xff2e344b;
|
||||
themeAccent.backgroundGradientOverrideColor2 = 0xff7874a7;
|
||||
themeAccent.backgroundGradientOverrideColor3 = 0xff333258;
|
||||
}
|
||||
}
|
||||
themeAccentsMap.put(themeAccent.id, themeAccent);
|
||||
themeAccents.add(themeAccent);
|
||||
}
|
||||
|
@ -2863,7 +2921,9 @@ public class Theme {
|
|||
public static Drawable dialogs_errorDrawable;
|
||||
public static Drawable dialogs_reorderDrawable;
|
||||
public static Drawable dialogs_lockDrawable;
|
||||
public static Drawable dialogs_lock2Drawable;
|
||||
public static Drawable dialogs_muteDrawable;
|
||||
public static Drawable dialogs_unmuteDrawable;
|
||||
public static Drawable dialogs_verifiedDrawable;
|
||||
public static ScamDrawable dialogs_scamDrawable;
|
||||
public static ScamDrawable dialogs_fakeDrawable;
|
||||
|
@ -2954,6 +3014,7 @@ public class Theme {
|
|||
public static TextPaint chat_forwardNamePaint;
|
||||
public static TextPaint chat_replyNamePaint;
|
||||
public static TextPaint chat_replyTextPaint;
|
||||
public static TextPaint chat_commentTextPaint;
|
||||
public static TextPaint chat_contextResult_titleTextPaint;
|
||||
public static TextPaint chat_contextResult_descriptionTextPaint;
|
||||
|
||||
|
@ -3895,6 +3956,7 @@ public class Theme {
|
|||
public static final String key_drawable_goIcon = "drawableGoIcon";
|
||||
public static final String key_drawable_msgError = "drawableMsgError";
|
||||
public static final String key_drawable_msgIn = "drawableMsgIn";
|
||||
public static final String key_drawable_msgInInstant = "drawableMsgInInstant";
|
||||
public static final String key_drawable_msgInClock = "drawableMsgInClock";
|
||||
public static final String key_drawable_msgInClockSelected = "drawableMsgInClockSelected";
|
||||
public static final String key_drawable_msgInSelected = "drawableMsgInSelected";
|
||||
|
@ -6538,13 +6600,33 @@ public class Theme {
|
|||
for (int a = 0; a < count; a++) {
|
||||
Drawable layer = drawable.getDrawable(a);
|
||||
if (layer instanceof RippleRadMaskDrawable) {
|
||||
drawable.setDrawableByLayerId(android.R.id.mask, new RippleRadMaskDrawable(top, bottom));
|
||||
((RippleRadMaskDrawable) layer).setRadius(top, bottom);
|
||||
// drawable.setDrawableByLayerId(android.R.id.mask, new RippleRadMaskDrawable(top, bottom));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setMaskDrawableRad(Drawable rippleDrawable, int topLeftRad, int topRightRad, int bottomRightRad, int bottomLeftRad) {
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
return;
|
||||
}
|
||||
if (rippleDrawable instanceof RippleDrawable) {
|
||||
RippleDrawable drawable = (RippleDrawable) rippleDrawable;
|
||||
int count = drawable.getNumberOfLayers();
|
||||
for (int a = 0; a < count; a++) {
|
||||
Drawable layer = drawable.getDrawable(a);
|
||||
if (layer instanceof RippleRadMaskDrawable) {
|
||||
((RippleRadMaskDrawable) layer).setRadius(topLeftRad, topRightRad, bottomRightRad, bottomLeftRad);
|
||||
// drawable.setDrawableByLayerId(android.R.id.mask, new RippleRadMaskDrawable(top, bottom));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Drawable createRadSelectorDrawable(int color, int topRad, int bottomRad) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
maskPaint.setColor(0xffffffff);
|
||||
|
@ -7660,7 +7742,7 @@ public class Theme {
|
|||
switchingNightTheme = false;
|
||||
}
|
||||
} else {
|
||||
if (currentTheme != currentDayTheme && (currentTheme == null || currentNightTheme != null && currentTheme.isDark() != currentNightTheme.isDark())) {
|
||||
if (currentTheme != currentDayTheme && (currentTheme == null || currentDayTheme != null && currentTheme.isLight() != currentDayTheme.isLight())) {
|
||||
isInNigthMode = false;
|
||||
lastThemeSwitchTime = SystemClock.elapsedRealtime();
|
||||
switchingNightTheme = true;
|
||||
|
@ -8796,6 +8878,7 @@ public class Theme {
|
|||
dialogs_actionMessagePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
dialogs_lockDrawable = resources.getDrawable(R.drawable.list_secret);
|
||||
dialogs_lock2Drawable = resources.getDrawable(R.drawable.msg_mini_lock2);
|
||||
dialogs_checkDrawable = resources.getDrawable(R.drawable.list_check).mutate();
|
||||
dialogs_playDrawable = resources.getDrawable(R.drawable.minithumb_play).mutate();
|
||||
dialogs_checkReadDrawable = resources.getDrawable(R.drawable.list_check).mutate();
|
||||
|
@ -8804,6 +8887,7 @@ public class Theme {
|
|||
dialogs_errorDrawable = resources.getDrawable(R.drawable.list_warning_sign);
|
||||
dialogs_reorderDrawable = resources.getDrawable(R.drawable.list_reorder).mutate();
|
||||
dialogs_muteDrawable = resources.getDrawable(R.drawable.list_mute).mutate();
|
||||
dialogs_unmuteDrawable = resources.getDrawable(R.drawable.list_unmute).mutate();
|
||||
dialogs_verifiedDrawable = resources.getDrawable(R.drawable.verified_area).mutate();
|
||||
dialogs_scamDrawable = new ScamDrawable(11, 0);
|
||||
dialogs_fakeDrawable = new ScamDrawable(11, 1);
|
||||
|
@ -8873,6 +8957,7 @@ public class Theme {
|
|||
dialogs_offlinePaint.setColor(getColor(key_windowBackgroundWhiteGrayText3));
|
||||
|
||||
setDrawableColorByKey(dialogs_lockDrawable, key_chats_secretIcon);
|
||||
setDrawableColorByKey(dialogs_lock2Drawable, key_chats_pinnedIcon);
|
||||
setDrawableColorByKey(dialogs_checkDrawable, key_chats_sentCheck);
|
||||
setDrawableColorByKey(dialogs_checkReadDrawable, key_chats_sentReadCheck);
|
||||
setDrawableColorByKey(dialogs_halfCheckDrawable, key_chats_sentReadCheck);
|
||||
|
@ -8881,6 +8966,7 @@ public class Theme {
|
|||
setDrawableColorByKey(dialogs_pinnedDrawable, key_chats_pinnedIcon);
|
||||
setDrawableColorByKey(dialogs_reorderDrawable, key_chats_pinnedIcon);
|
||||
setDrawableColorByKey(dialogs_muteDrawable, key_chats_muteIcon);
|
||||
setDrawableColorByKey(dialogs_unmuteDrawable, key_chats_muteIcon);
|
||||
setDrawableColorByKey(dialogs_mentionDrawable, key_chats_mentionIcon);
|
||||
setDrawableColorByKey(dialogs_reactionsMentionDrawable, key_chats_mentionIcon);
|
||||
setDrawableColorByKey(dialogs_verifiedDrawable, key_chats_verifiedBackground);
|
||||
|
@ -8922,6 +9008,14 @@ public class Theme {
|
|||
chat_msgTextPaintThreeEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
chat_msgBotButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
chat_msgBotButtonPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_namePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
}
|
||||
|
||||
final float[] emojiSizePercents = new float[] {.7f, .52f, .37f, .28f, .25f, .19f};
|
||||
|
@ -8935,6 +9029,14 @@ public class Theme {
|
|||
chat_msgTextPaint.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize));
|
||||
chat_msgGameTextPaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_msgBotButtonPaint.setTextSize(AndroidUtilities.dp(15));
|
||||
float smallerDp = (2 * SharedConfig.fontSize + 10) / 3f; // 6f + SharedConfig.fontSize / 2f;
|
||||
chat_namePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_replyNamePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_replyTextPaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_forwardNamePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_adminPaint.setTextSize(AndroidUtilities.dp(smallerDp - 1));
|
||||
// float timeDp = 2 * (SharedConfig.fontSize - 16) / 3f + 12;
|
||||
// chat_timePaint.setTextSize(AndroidUtilities.dp(timeDp));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8991,6 +9093,7 @@ public class Theme {
|
|||
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_commentTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
chat_instantViewPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
chat_instantViewPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
chat_instantViewRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
@ -9272,6 +9375,7 @@ public class Theme {
|
|||
addChatDrawable(key_drawable_msgInSelected, chat_msgInSelectedDrawable, null);
|
||||
addChatDrawable(key_drawable_msgInMedia, chat_msgInMediaDrawable, null);
|
||||
addChatDrawable(key_drawable_msgInMediaSelected, chat_msgInMediaSelectedDrawable, null);
|
||||
addChatDrawable(key_drawable_msgInInstant, chat_msgInInstantDrawable, key_chat_inInstant);
|
||||
addChatDrawable(key_drawable_msgOut, chat_msgOutDrawable, null);
|
||||
addChatDrawable(key_drawable_msgOutSelected, chat_msgOutSelectedDrawable, null);
|
||||
addChatDrawable(key_drawable_msgOutMedia, chat_msgOutMediaDrawable, null);
|
||||
|
@ -9325,12 +9429,14 @@ public class Theme {
|
|||
chat_contactNamePaint.setTextSize(AndroidUtilities.dp(15));
|
||||
chat_contactPhonePaint.setTextSize(AndroidUtilities.dp(13));
|
||||
chat_durationPaint.setTextSize(AndroidUtilities.dp(12));
|
||||
float smallerDp = (2 * SharedConfig.fontSize + 10) / 3f; // 6f + SharedConfig.fontSize / 2f;
|
||||
chat_namePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_replyNamePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_replyTextPaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_forwardNamePaint.setTextSize(AndroidUtilities.dp(smallerDp));
|
||||
chat_adminPaint.setTextSize(AndroidUtilities.dp(smallerDp - 1));
|
||||
float timeDp = 2 * (SharedConfig.fontSize - 16) / 3f + 12;
|
||||
chat_timePaint.setTextSize(AndroidUtilities.dp(12));
|
||||
chat_adminPaint.setTextSize(AndroidUtilities.dp(13));
|
||||
chat_namePaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_forwardNamePaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_replyNamePaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_replyTextPaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_gamePaint.setTextSize(AndroidUtilities.dp(13));
|
||||
chat_shipmentPaint.setTextSize(AndroidUtilities.dp(13));
|
||||
chat_instantViewPaint.setTextSize(AndroidUtilities.dp(13));
|
||||
|
@ -9342,6 +9448,8 @@ public class Theme {
|
|||
chat_contextResult_descriptionTextPaint.setTextSize(AndroidUtilities.dp(13));
|
||||
chat_radialProgressPaint.setStrokeWidth(AndroidUtilities.dp(3));
|
||||
chat_radialProgress2Paint.setStrokeWidth(AndroidUtilities.dp(2));
|
||||
chat_commentTextPaint.setTextSize(AndroidUtilities.dp(14));
|
||||
chat_commentTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -195,14 +195,14 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
|
|||
if (width > height) {
|
||||
titleTextView.measure(MeasureSpec.makeMeasureSpec((int) (width * 0.6f), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
|
||||
descriptionText.measure(MeasureSpec.makeMeasureSpec((int) (width * 0.6f), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
|
||||
buttonTextView.measure(MeasureSpec.makeMeasureSpec((int) (width * 0.6f), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(42), MeasureSpec.EXACTLY));
|
||||
buttonTextView.measure(MeasureSpec.makeMeasureSpec((int) (width * 0.6f), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(42), MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
titleTextView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
|
||||
descriptionText.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
|
||||
if (currentType == ACTION_TYPE_SET_PASSCODE) {
|
||||
buttonTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(24 * 2), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
buttonTextView.measure(MeasureSpec.makeMeasureSpec((int) (width * 0.6f), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(42), MeasureSpec.EXACTLY));
|
||||
buttonTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(72), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -384,7 +384,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
|
|||
y = (int) (height * 0.493f);
|
||||
descriptionText.layout(0, y, descriptionText.getMeasuredWidth(), y + descriptionText.getMeasuredHeight());
|
||||
x = (width - buttonTextView.getMeasuredWidth()) / 2;
|
||||
y = (int) (height * 0.71f);
|
||||
y = (int) (height * 0.853f);
|
||||
buttonTextView.layout(x, y, x + buttonTextView.getMeasuredWidth(), y + buttonTextView.getMeasuredHeight());
|
||||
}
|
||||
break;
|
||||
|
@ -703,6 +703,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
|
|||
titleTextView.setText(LocaleController.getString("PeopleNearby", R.string.PeopleNearby));
|
||||
descriptionText.setText(LocaleController.getString("PeopleNearbyAccessInfo", R.string.PeopleNearbyAccessInfo));
|
||||
buttonTextView.setText(LocaleController.getString("PeopleNearbyAllowAccess", R.string.PeopleNearbyAllowAccess));
|
||||
flickerButton = true;
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_NEARBY_LOCATION_ENABLED: {
|
||||
|
|
|
@ -607,7 +607,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
|
|||
if (chat.participants_count != 0) {
|
||||
subtitle = LocaleController.formatPluralStringComma("Subscribers", chat.participants_count);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(chat.username)) {
|
||||
if (!ChatObject.isPublic(chat)) {
|
||||
subtitle = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase();
|
||||
} else {
|
||||
subtitle = LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase();
|
||||
|
@ -619,7 +619,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter {
|
|||
} else {
|
||||
if (chat.has_geo) {
|
||||
subtitle = LocaleController.getString("MegaLocation", R.string.MegaLocation);
|
||||
} else if (TextUtils.isEmpty(chat.username)) {
|
||||
} else if (!ChatObject.isPublic(chat)) {
|
||||
subtitle = LocaleController.getString("MegaPrivate", R.string.MegaPrivate).toLowerCase();
|
||||
} else {
|
||||
subtitle = LocaleController.getString("MegaPublic", R.string.MegaPublic).toLowerCase();
|
||||
|
|
|
@ -13,11 +13,15 @@ import android.os.SystemClock;
|
|||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.SQLite.SQLiteCursor;
|
||||
import org.telegram.SQLite.SQLitePreparedStatement;
|
||||
|
@ -25,21 +29,20 @@ import org.telegram.messenger.AndroidUtilities;
|
|||
import org.telegram.messenger.ChatObject;
|
||||
import org.telegram.messenger.ContactsController;
|
||||
import org.telegram.messenger.DialogObject;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.MessagesStorage;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.UserObject;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.DialogCell;
|
||||
import org.telegram.ui.Cells.GraySectionCell;
|
||||
import org.telegram.ui.Cells.HashtagSearchCell;
|
||||
|
@ -56,11 +59,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||
|
||||
private final int VIEW_TYPE_PROFILE_CELL = 0;
|
||||
|
@ -1124,7 +1122,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
|
|||
if (chat == null) {
|
||||
chat = (TLRPC.Chat) obj;
|
||||
}
|
||||
un = chat.username;
|
||||
un = ChatObject.getPublicUsername(chat);
|
||||
} else if (obj instanceof TLRPC.EncryptedChat) {
|
||||
encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(((TLRPC.EncryptedChat) obj).id);
|
||||
user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id);
|
||||
|
@ -1219,9 +1217,9 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
|
|||
if (chat != null && chat.participants_count != 0) {
|
||||
String membersString;
|
||||
if (ChatObject.isChannel(chat) && !chat.megagroup) {
|
||||
membersString = LocaleController.formatPluralString("Subscribers", chat.participants_count);
|
||||
membersString = LocaleController.formatPluralStringComma("Subscribers", chat.participants_count, ' ');
|
||||
} else {
|
||||
membersString = LocaleController.formatPluralString("Members", chat.participants_count);
|
||||
membersString = LocaleController.formatPluralStringComma("Members", chat.participants_count, ' ');
|
||||
}
|
||||
if (username instanceof SpannableStringBuilder) {
|
||||
((SpannableStringBuilder) username).append(", ").append(membersString);
|
||||
|
@ -1381,7 +1379,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
|
|||
cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||
cell.useSeparator = (position != getItemCount() - 1);
|
||||
MessageObject messageObject = (MessageObject) getItem(position);
|
||||
cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, false);
|
||||
cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, false, false);
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_HASHTAG_CELL: {
|
||||
|
|
|
@ -1113,7 +1113,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
|
|||
}
|
||||
firstName = chat.title;
|
||||
lastName = null;
|
||||
username = chat.username;
|
||||
username = ChatObject.getPublicUsername(chat);
|
||||
object = chat;
|
||||
id = -chat.id;
|
||||
} else {
|
||||
|
|
|
@ -12,6 +12,8 @@ import android.content.Context;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
|
@ -22,8 +24,6 @@ import org.telegram.ui.Components.RecyclerListView;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||
|
||||
private Context mContext;
|
||||
|
@ -86,7 +86,7 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
|||
DialogCell cell = (DialogCell) holder.itemView;
|
||||
cell.useSeparator = true;
|
||||
MessageObject messageObject = (MessageObject) getItem(position);
|
||||
cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, true);
|
||||
cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.view.ViewGroup;
|
|||
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ChatObject;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserObject;
|
||||
|
@ -320,7 +321,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter {
|
|||
id = ((TLRPC.User) object).id;
|
||||
self = ((TLRPC.User) object).self;
|
||||
} else if (object instanceof TLRPC.Chat) {
|
||||
un = ((TLRPC.Chat) object).username;
|
||||
un = ChatObject.getPublicUsername((TLRPC.Chat) object);
|
||||
id = ((TLRPC.Chat) object).id;
|
||||
}
|
||||
|
||||
|
|
|
@ -236,12 +236,12 @@ public class ArchivedStickersActivity extends BaseFragment implements Notificati
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
isInTransition = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
isInTransition = false;
|
||||
if (doOnTransitionEnd != null) {
|
||||
doOnTransitionEnd.run();
|
||||
|
|
|
@ -104,6 +104,7 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
|||
import org.json.JSONObject;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.ChatObject;
|
||||
import org.telegram.messenger.DownloadController;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
@ -3201,7 +3202,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
if (pageBlock instanceof TLRPC.TL_pageBlockChannel) {
|
||||
TLRPC.TL_pageBlockChannel pageBlockChannel = (TLRPC.TL_pageBlockChannel) pageBlock;
|
||||
MessagesController.getInstance(currentAccount).openByUserName(pageBlockChannel.channel.username, parentFragment, 2);
|
||||
MessagesController.getInstance(currentAccount).openByUserName(ChatObject.getPublicUsername(pageBlockChannel.channel), parentFragment, 2);
|
||||
close(false, true);
|
||||
} else if (pageBlock instanceof TL_pageBlockRelatedArticlesChild) {
|
||||
TL_pageBlockRelatedArticlesChild pageBlockRelatedArticlesChild = (TL_pageBlockRelatedArticlesChild) pageBlock;
|
||||
|
@ -4161,7 +4162,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
messageObject.messageOwner.media.webpage = webPage;
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(messageObject.messageOwner);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(messagesRes, messageObject.getDialogId(), -2, 0, false, messageObject.scheduled);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(messagesRes, messageObject.getDialogId(), -2, 0, false, messageObject.scheduled, 0);
|
||||
}
|
||||
pagesStack.set(0, webPage);
|
||||
if (pagesStack.size() == 1) {
|
||||
|
@ -4194,7 +4195,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
if (messageObject != null) {
|
||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(messageObject.messageOwner);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(messagesRes, messageObject.getDialogId(), -2, 0, false, messageObject.scheduled);
|
||||
MessagesStorage.getInstance(currentAccount).putMessages(messagesRes, messageObject.getDialogId(), -2, 0, false, messageObject.scheduled, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4652,7 +4653,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
|
||||
private void loadChannel(final BlockChannelCell cell, WebpageAdapter adapter, TLRPC.Chat channel) {
|
||||
if (loadingChannel || TextUtils.isEmpty(channel.username)) {
|
||||
if (loadingChannel || !ChatObject.isPublic(channel)) {
|
||||
return;
|
||||
}
|
||||
loadingChannel = true;
|
||||
|
@ -6025,7 +6026,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
float y = event.getY();
|
||||
if (channelCell.getVisibility() == VISIBLE && y > channelCell.getTranslationY() && y < channelCell.getTranslationY() + AndroidUtilities.dp(39)) {
|
||||
if (parentAdapter.channelBlock != null && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
MessagesController.getInstance(currentAccount).openByUserName(parentAdapter.channelBlock.channel.username, parentFragment, 2);
|
||||
MessagesController.getInstance(currentAccount).openByUserName(ChatObject.getPublicUsername(parentAdapter.channelBlock.channel), parentFragment, 2);
|
||||
close(false, true);
|
||||
}
|
||||
return true;
|
||||
|
@ -9909,7 +9910,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
float y = event.getY();
|
||||
if (channelCell.getVisibility() == VISIBLE && y > channelCell.getTranslationY() && y < channelCell.getTranslationY() + AndroidUtilities.dp(39)) {
|
||||
if (parentAdapter.channelBlock != null && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
MessagesController.getInstance(currentAccount).openByUserName(parentAdapter.channelBlock.channel.username, parentFragment, 2);
|
||||
MessagesController.getInstance(currentAccount).openByUserName(ChatObject.getPublicUsername(parentAdapter.channelBlock.channel), parentFragment, 2);
|
||||
close(false, true);
|
||||
}
|
||||
return true;
|
||||
|
@ -11212,6 +11213,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
}
|
||||
|
||||
public boolean openPhoto(TLRPC.PageBlock block, WebpageAdapter adapter) {
|
||||
if (parentFragment == null || parentFragment.getParentActivity() == null) {
|
||||
return false;
|
||||
}
|
||||
final int index;
|
||||
final List<TLRPC.PageBlock> pageBlocks;
|
||||
if (!(block instanceof TLRPC.TL_pageBlockVideo) || WebPageUtils.isVideo(adapter.currentPage, block)) {
|
||||
|
|
|
@ -8,11 +8,7 @@
|
|||
|
||||
package org.telegram.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
|
@ -25,19 +21,14 @@ import org.telegram.messenger.AccountInstance;
|
|||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.BuildVars;
|
||||
import org.telegram.messenger.ContactsController;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.ImageLoader;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.camera.CameraController;
|
||||
import org.telegram.ui.ActionBar.ActionBarLayout;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.DrawerLayoutContainer;
|
||||
import org.telegram.ui.ActionBar.INavigationLayout;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.PasscodeView;
|
||||
|
@ -45,13 +36,13 @@ import org.telegram.ui.Components.ThemeEditorView;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BubbleActivity extends BasePermissionsActivity implements ActionBarLayout.ActionBarLayoutDelegate {
|
||||
public class BubbleActivity extends BasePermissionsActivity implements INavigationLayout.INavigationLayoutDelegate {
|
||||
|
||||
private boolean finished;
|
||||
private ArrayList<BaseFragment> mainFragmentsStack = new ArrayList<>();
|
||||
|
||||
private PasscodeView passcodeView;
|
||||
private ActionBarLayout actionBarLayout;
|
||||
private INavigationLayout actionBarLayout;
|
||||
protected DrawerLayoutContainer drawerLayoutContainer;
|
||||
|
||||
private Intent passcodeSaveIntent;
|
||||
|
@ -89,7 +80,7 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
Theme.createDialogsResources(this);
|
||||
Theme.createChatResources(this, false);
|
||||
|
||||
actionBarLayout = new ActionBarLayout(this);
|
||||
actionBarLayout = INavigationLayout.newLayout(this);
|
||||
actionBarLayout.setInBubbleMode(true);
|
||||
actionBarLayout.setRemoveActionBarExtraHeight(true);
|
||||
|
||||
|
@ -99,11 +90,11 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
|
||||
RelativeLayout launchLayout = new RelativeLayout(this);
|
||||
drawerLayoutContainer.addView(launchLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
launchLayout.addView(actionBarLayout, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
launchLayout.addView(actionBarLayout.getView(), LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
drawerLayoutContainer.setParentActionBarLayout(actionBarLayout);
|
||||
actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer);
|
||||
actionBarLayout.init(mainFragmentsStack);
|
||||
actionBarLayout.setFragmentStack(mainFragmentsStack);
|
||||
actionBarLayout.setDelegate(this);
|
||||
|
||||
passcodeView = new PasscodeView(this);
|
||||
|
@ -188,11 +179,6 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreIme() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
@ -246,8 +232,8 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
if (editorView != null) {
|
||||
editorView.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
if (actionBarLayout.fragmentsStack.size() != 0) {
|
||||
BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
|
||||
if (actionBarLayout.getFragmentStack().size() != 0) {
|
||||
BaseFragment fragment = actionBarLayout.getFragmentStack().get(actionBarLayout.getFragmentStack().size() - 1);
|
||||
fragment.onActivityResultFragment(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
@ -257,8 +243,8 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (!checkPermissionsResult(requestCode, permissions, grantResults)) return;
|
||||
|
||||
if (actionBarLayout.fragmentsStack.size() != 0) {
|
||||
BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
|
||||
if (actionBarLayout.getFragmentStack().size() != 0) {
|
||||
BaseFragment fragment = actionBarLayout.getFragmentStack().get(actionBarLayout.getFragmentStack().size() - 1);
|
||||
fragment.onRequestPermissionsResultFragment(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
|
@ -361,27 +347,12 @@ public class BubbleActivity extends BasePermissionsActivity implements ActionBar
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needCloseLastFragment(ActionBarLayout layout) {
|
||||
if (layout.fragmentsStack.size() <= 1) {
|
||||
public boolean needCloseLastFragment(INavigationLayout layout) {
|
||||
if (layout.getFragmentStack().size() <= 1) {
|
||||
onFinish();
|
||||
finish();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebuildAllFragments(ActionBarLayout layout, boolean last) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
|||
|
||||
long fragmentCreateTime;
|
||||
|
||||
private boolean updateDatabaseSize;
|
||||
|
||||
@Override
|
||||
public boolean onFragmentCreate() {
|
||||
super.onFragmentCreate();
|
||||
|
@ -537,7 +539,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
|||
CheckBoxCell cell = (CheckBoxCell) v;
|
||||
int num = (Integer) cell.getTag();
|
||||
if (enabledCount == 1 && clearViewData[num].clear) {
|
||||
AndroidUtilities.shakeView(((CheckBoxCell) v).getCheckBoxView(), 2, 0);
|
||||
AndroidUtilities.shakeView(((CheckBoxCell) v).getCheckBoxView());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -630,6 +632,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
|||
progressDialog = null;
|
||||
if (listAdapter != null) {
|
||||
databaseSize = MessagesStorage.getInstance(currentAccount).getDatabaseSize();
|
||||
updateDatabaseSize = true;
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +712,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
|||
case 0:
|
||||
TextSettingsCell textCell = (TextSettingsCell) holder.itemView;
|
||||
if (position == databaseRow) {
|
||||
textCell.setTextAndValue(LocaleController.getString("ClearLocalDatabase", R.string.ClearLocalDatabase), AndroidUtilities.formatFileSize(databaseSize), false);
|
||||
textCell.setTextAndValue(LocaleController.getString("ClearLocalDatabase", R.string.ClearLocalDatabase), AndroidUtilities.formatFileSize(databaseSize), updateDatabaseSize, false);
|
||||
updateDatabaseSize = false;
|
||||
} else if (position == migrateOldFolderRow) {
|
||||
textCell.setTextAndValue(LocaleController.getString("MigrateOldFolder", R.string.MigrateOldFolder), null, false);
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ public class CalendarActivity extends BaseFragment {
|
|||
Paint blackoutPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private long dialogId;
|
||||
private int topicId;
|
||||
private boolean loading;
|
||||
private boolean checkEnterItems;
|
||||
private boolean inSelectionMode;
|
||||
|
@ -140,6 +141,7 @@ public class CalendarActivity extends BaseFragment {
|
|||
@Override
|
||||
public boolean onFragmentCreate() {
|
||||
dialogId = getArguments().getLong("dialog_id");
|
||||
topicId = getArguments().getInt("topic_id");
|
||||
calendarType = getArguments().getInt("type");
|
||||
|
||||
if (dialogId >= 0) {
|
||||
|
@ -313,8 +315,8 @@ public class CalendarActivity extends BaseFragment {
|
|||
public void run(boolean forAll) {
|
||||
finishFragment();
|
||||
|
||||
if (parentLayout.fragmentsStack.size() >= 2) {
|
||||
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2);
|
||||
if (parentLayout.getFragmentStack().size() >= 2) {
|
||||
BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2);
|
||||
if (fragment instanceof ChatActivity) {
|
||||
((ChatActivity) fragment).deleteHistory(dateSelectedStart, dateSelectedEnd + 86400, forAll);
|
||||
}
|
||||
|
@ -600,6 +602,9 @@ public class CalendarActivity extends BaseFragment {
|
|||
@SuppressLint("NotifyDataSetChanged")
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
if (parentLayout == null) {
|
||||
return false;
|
||||
}
|
||||
if (calendarType == TYPE_MEDIA_CALENDAR && messagesByDays != null) {
|
||||
PeriodDay day = getDayAtCoord(e.getX(), e.getY());
|
||||
if (day != null && day.messageObject != null && callback != null) {
|
||||
|
@ -640,8 +645,8 @@ public class CalendarActivity extends BaseFragment {
|
|||
}
|
||||
} else {
|
||||
PeriodDay day = getDayAtCoord(e.getX(), e.getY());
|
||||
if (day != null && parentLayout.fragmentsStack.size() >= 2) {
|
||||
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2);
|
||||
if (day != null && parentLayout.getFragmentStack().size() >= 2) {
|
||||
BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2);
|
||||
if (fragment instanceof ChatActivity) {
|
||||
finishFragment();
|
||||
((ChatActivity) fragment).jumpToDate(day.date);
|
||||
|
@ -710,8 +715,8 @@ public class CalendarActivity extends BaseFragment {
|
|||
cellJump.setTextAndIcon(LocaleController.getString("JumpToDate", R.string.JumpToDate), R.drawable.msg_message);
|
||||
cellJump.setMinimumWidth(160);
|
||||
cellJump.setOnClickListener(view -> {
|
||||
if (parentLayout.fragmentsStack.size() >= 3) {
|
||||
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 3);
|
||||
if (parentLayout.getFragmentStack().size() >= 3) {
|
||||
BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 3);
|
||||
if (fragment instanceof ChatActivity) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
finishFragment();
|
||||
|
@ -740,8 +745,8 @@ public class CalendarActivity extends BaseFragment {
|
|||
cellDelete.setTextAndIcon(LocaleController.getString("ClearHistory", R.string.ClearHistory), R.drawable.msg_delete);
|
||||
cellDelete.setMinimumWidth(160);
|
||||
cellDelete.setOnClickListener(view -> {
|
||||
if (parentLayout.fragmentsStack.size() >= 3) {
|
||||
BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 3);
|
||||
if (parentLayout.getFragmentStack().size() >= 3) {
|
||||
BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 3);
|
||||
if (fragment instanceof ChatActivity) {
|
||||
AlertsCreator.createClearDaysDialogAlert(CalendarActivity.this, 1, getMessagesController().getUser(dialogId), null, false, new MessagesStorage.BooleanCallback() {
|
||||
@Override
|
||||
|
@ -773,7 +778,7 @@ public class CalendarActivity extends BaseFragment {
|
|||
});
|
||||
blurredView.setVisibility(View.GONE);
|
||||
blurredView.setFitsSystemWindows(true);
|
||||
parentLayout.containerView.addView(blurredView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
parentLayout.getOverlayContainerView().addView(blurredView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
prepareBlurBitmap();
|
||||
|
||||
presentFragmentAsPreviewWithMenu(chatActivity, previewMenu);
|
||||
|
@ -1261,13 +1266,13 @@ public class CalendarActivity extends BaseFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
super.onTransitionAnimationStart(isOpen, backward);
|
||||
isOpened = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationProgress(boolean isOpen, float progress) {
|
||||
public void onTransitionAnimationProgress(boolean isOpen, float progress) {
|
||||
super.onTransitionAnimationProgress(isOpen, progress);
|
||||
if (blurredView != null && blurredView.getVisibility() == View.VISIBLE) {
|
||||
if (isOpen) {
|
||||
|
@ -1279,7 +1284,7 @@ public class CalendarActivity extends BaseFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
|
||||
if (isOpen && blurredView != null && blurredView.getVisibility() == View.VISIBLE) {
|
||||
blurredView.setVisibility(View.GONE);
|
||||
blurredView.setBackground(null);
|
||||
|
@ -1393,12 +1398,12 @@ public class CalendarActivity extends BaseFragment {
|
|||
if (blurredView == null) {
|
||||
return;
|
||||
}
|
||||
int w = (int) (parentLayout.getMeasuredWidth() / 6.0f);
|
||||
int h = (int) (parentLayout.getMeasuredHeight() / 6.0f);
|
||||
int w = (int) (parentLayout.getView().getMeasuredWidth() / 6.0f);
|
||||
int h = (int) (parentLayout.getView().getMeasuredHeight() / 6.0f);
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.scale(1.0f / 6.0f, 1.0f / 6.0f);
|
||||
parentLayout.draw(canvas);
|
||||
parentLayout.getView().draw(canvas);
|
||||
Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(w, h) / 180));
|
||||
blurredView.setBackground(new BitmapDrawable(bitmap));
|
||||
blurredView.setAlpha(0.0f);
|
||||
|
|
|
@ -1069,7 +1069,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
|
|||
cell.button.setTag(chat.id);
|
||||
String text;
|
||||
if (ChatObject.isChannel(chat) && !chat.megagroup) {
|
||||
if (TextUtils.isEmpty(chat.username)) {
|
||||
if (!ChatObject.isPublic(chat)) {
|
||||
text = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase();
|
||||
} else {
|
||||
text = LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase();
|
||||
|
@ -1077,7 +1077,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
|
|||
} else {
|
||||
if (chat.has_geo) {
|
||||
text = LocaleController.getString("MegaLocation", R.string.MegaLocation);
|
||||
} else if (TextUtils.isEmpty(chat.username)) {
|
||||
} else if (!ChatObject.isPublic(chat)) {
|
||||
text = LocaleController.getString("MegaPrivate", R.string.MegaPrivate).toLowerCase();
|
||||
} else {
|
||||
text = LocaleController.getString("MegaPublic", R.string.MegaPublic).toLowerCase();
|
||||
|
@ -1115,7 +1115,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter.
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
public void onTransitionAnimationStart(boolean isOpen, boolean backward) {
|
||||
super.onTransitionAnimationStart(isOpen, backward);
|
||||
if (isOpen) {
|
||||
openTransitionStarted = true;
|
||||
|
|
|
@ -15,6 +15,8 @@ import android.content.pm.PackageManager;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
|
@ -33,6 +35,7 @@ import android.text.SpannableStringBuilder;
|
|||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
|
@ -75,9 +78,9 @@ import org.telegram.messenger.camera.CameraSession;
|
|||
import org.telegram.messenger.camera.CameraView;
|
||||
import org.telegram.messenger.camera.Size;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarLayout;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.BottomSheet;
|
||||
import org.telegram.ui.ActionBar.INavigationLayout;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Components.AnimationProperties;
|
||||
|
@ -154,15 +157,15 @@ public class CameraScanActivity extends BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
public static ActionBarLayout[] showAsSheet(BaseFragment parentFragment, boolean gallery, int type, CameraScanActivityDelegate cameraDelegate) {
|
||||
public static INavigationLayout[] showAsSheet(BaseFragment parentFragment, boolean gallery, int type, CameraScanActivityDelegate cameraDelegate) {
|
||||
if (parentFragment == null || parentFragment.getParentActivity() == null) {
|
||||
return null;
|
||||
}
|
||||
ActionBarLayout[] actionBarLayout = new ActionBarLayout[]{new ActionBarLayout(parentFragment.getParentActivity())};
|
||||
INavigationLayout[] actionBarLayout = new INavigationLayout[]{INavigationLayout.newLayout(parentFragment.getParentActivity())};
|
||||
BottomSheet bottomSheet = new BottomSheet(parentFragment.getParentActivity(), false) {
|
||||
CameraScanActivity fragment;
|
||||
{
|
||||
actionBarLayout[0].init(new ArrayList<>());
|
||||
actionBarLayout[0].setFragmentStack(new ArrayList<>());
|
||||
fragment = new CameraScanActivity(type) {
|
||||
@Override
|
||||
public void finishFragment() {
|
||||
|
@ -178,9 +181,9 @@ public class CameraScanActivity extends BaseFragment {
|
|||
fragment.needGalleryButton = gallery;
|
||||
actionBarLayout[0].addFragmentToStack(fragment);
|
||||
actionBarLayout[0].showLastFragment();
|
||||
actionBarLayout[0].setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
|
||||
actionBarLayout[0].getView().setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
|
||||
fragment.setDelegate(cameraDelegate);
|
||||
containerView = actionBarLayout[0];
|
||||
containerView = actionBarLayout[0].getView();
|
||||
setApplyBottomPadding(false);
|
||||
setApplyBottomPadding(false);
|
||||
setOnDismissListener(dialog -> fragment.onFragmentDestroy());
|
||||
|
@ -193,7 +196,7 @@ public class CameraScanActivity extends BaseFragment {
|
|||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (actionBarLayout[0] == null || actionBarLayout[0].fragmentsStack.size() <= 1) {
|
||||
if (actionBarLayout[0] == null || actionBarLayout[0].getFragmentStack().size() <= 1) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
actionBarLayout[0].onBackPressed();
|
||||
|
@ -888,6 +891,11 @@ public class CameraScanActivity extends BaseFragment {
|
|||
public void run() {
|
||||
if (cameraView != null && !recognized && cameraView.getCameraSession() != null) {
|
||||
handler.post(() -> {
|
||||
try {
|
||||
cameraView.focusToPoint(cameraView.getWidth() / 2, cameraView.getHeight() / 2, false);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
if (cameraView != null) {
|
||||
processShot(cameraView.getTextureView().getBitmap());
|
||||
}
|
||||
|
@ -1011,6 +1019,52 @@ public class CameraScanActivity extends BaseFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private Bitmap invert(Bitmap bitmap) {
|
||||
int height = bitmap.getHeight();
|
||||
int width = bitmap.getWidth();
|
||||
|
||||
Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(newBitmap);
|
||||
Paint paint = new Paint();
|
||||
|
||||
ColorMatrix matrixGrayscale = new ColorMatrix();
|
||||
matrixGrayscale.setSaturation(0);
|
||||
ColorMatrix matrixInvert = new ColorMatrix();
|
||||
matrixInvert.set(new float[] {
|
||||
-1.0f, 0.0f, 0.0f, 0.0f, 255.0f,
|
||||
0.0f, -1.0f, 0.0f, 0.0f, 255.0f,
|
||||
0.0f, 0.0f, -1.0f, 0.0f, 255.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 0.0f
|
||||
});
|
||||
matrixInvert.preConcat(matrixGrayscale);
|
||||
paint.setColorFilter(new ColorMatrixColorFilter(matrixInvert));
|
||||
canvas.drawBitmap(bitmap, 0, 0, paint);
|
||||
return newBitmap;
|
||||
}
|
||||
|
||||
private Bitmap monochrome(Bitmap bitmap, int threshold) {
|
||||
int height = bitmap.getHeight();
|
||||
int width = bitmap.getWidth();
|
||||
|
||||
Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(newBitmap);
|
||||
Paint paint = new Paint();
|
||||
|
||||
paint.setColorFilter(new ColorMatrixColorFilter(createThresholdMatrix(threshold)));
|
||||
canvas.drawBitmap(bitmap, 0, 0, paint);
|
||||
|
||||
return newBitmap;
|
||||
}
|
||||
public static ColorMatrix createThresholdMatrix(int threshold) {
|
||||
ColorMatrix matrix = new ColorMatrix(new float[] {
|
||||
85.f, 85.f, 85.f, 0.f, -255.f * threshold,
|
||||
85.f, 85.f, 85.f, 0.f, -255.f * threshold,
|
||||
85.f, 85.f, 85.f, 0.f, -255.f * threshold,
|
||||
0f, 0f, 0f, 1f, 0f
|
||||
});
|
||||
return matrix;
|
||||
}
|
||||
|
||||
private class QrResult {
|
||||
String text;
|
||||
RectF bounds;
|
||||
|
@ -1052,6 +1106,60 @@ public class CameraScanActivity extends BaseFragment {
|
|||
}
|
||||
bounds.set(minX, minY, maxX, maxY);
|
||||
}
|
||||
} else if (bitmap != null) {
|
||||
Bitmap inverted = invert(bitmap);
|
||||
bitmap.recycle();
|
||||
frame = new Frame.Builder().setBitmap(inverted).build();
|
||||
width = inverted.getWidth();
|
||||
height = inverted.getHeight();
|
||||
codes = visionQrReader.detect(frame);
|
||||
if (codes != null && codes.size() > 0) {
|
||||
Barcode code = codes.valueAt(0);
|
||||
text = code.rawValue;
|
||||
if (code.cornerPoints == null || code.cornerPoints.length == 0) {
|
||||
bounds = null;
|
||||
} else {
|
||||
float minX = Float.MAX_VALUE,
|
||||
maxX = Float.MIN_VALUE,
|
||||
minY = Float.MAX_VALUE,
|
||||
maxY = Float.MIN_VALUE;
|
||||
for (Point point : code.cornerPoints) {
|
||||
minX = Math.min(minX, point.x);
|
||||
maxX = Math.max(maxX, point.x);
|
||||
minY = Math.min(minY, point.y);
|
||||
maxY = Math.max(maxY, point.y);
|
||||
}
|
||||
bounds.set(minX, minY, maxX, maxY);
|
||||
}
|
||||
} else {
|
||||
Bitmap monochrome = monochrome(inverted, 90);
|
||||
inverted.recycle();
|
||||
frame = new Frame.Builder().setBitmap(monochrome).build();
|
||||
width = inverted.getWidth();
|
||||
height = inverted.getHeight();
|
||||
codes = visionQrReader.detect(frame);
|
||||
if (codes != null && codes.size() > 0) {
|
||||
Barcode code = codes.valueAt(0);
|
||||
text = code.rawValue;
|
||||
if (code.cornerPoints == null || code.cornerPoints.length == 0) {
|
||||
bounds = null;
|
||||
} else {
|
||||
float minX = Float.MAX_VALUE,
|
||||
maxX = Float.MIN_VALUE,
|
||||
minY = Float.MAX_VALUE,
|
||||
maxY = Float.MIN_VALUE;
|
||||
for (Point point : code.cornerPoints) {
|
||||
minX = Math.min(minX, point.x);
|
||||
maxX = Math.max(maxX, point.x);
|
||||
minY = Math.min(minY, point.y);
|
||||
maxY = Math.max(maxY, point.y);
|
||||
}
|
||||
bounds.set(minX, minY, maxX, maxY);
|
||||
}
|
||||
} else {
|
||||
text = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = null;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import android.widget.FrameLayout;
|
|||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
|
@ -93,6 +94,8 @@ public class AboutLinkCell extends FrameLayout {
|
|||
private boolean needSpace = false;
|
||||
private boolean moreButtonDisabled;
|
||||
|
||||
private GestureDetectorCompat gestureDetector;
|
||||
|
||||
public AboutLinkCell(Context context, BaseFragment fragment) {
|
||||
this(context, fragment, null);
|
||||
}
|
||||
|
@ -103,59 +106,9 @@ public class AboutLinkCell extends FrameLayout {
|
|||
this.resourcesProvider = resourcesProvider;
|
||||
parentFragment = fragment;
|
||||
|
||||
container = new FrameLayout(context) {
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
|
||||
boolean result = false;
|
||||
if (textLayout != null || nextLinesLayouts != null) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (x >= showMoreTextView.getLeft() && x <= showMoreTextView.getRight() &&
|
||||
y >= showMoreTextView.getTop() && y <= showMoreTextView.getBottom()) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
if (getMeasuredWidth() > 0 && x > getMeasuredWidth() - AndroidUtilities.dp(23)) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (firstThreeLinesLayout != null && expandT < 1 && shouldExpand) {
|
||||
if (checkTouchTextLayout(firstThreeLinesLayout, textX, textY, x, y)) {
|
||||
result = true;
|
||||
} else if (nextLinesLayouts != null) {
|
||||
for (int i = 0; i < nextLinesLayouts.length; ++i) {
|
||||
if (checkTouchTextLayout(nextLinesLayouts[i], nextLinesLayoutsPositions[i].x, nextLinesLayoutsPositions[i].y, x, y)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (checkTouchTextLayout(textLayout, textX, textY, x, y)) {
|
||||
result = true;
|
||||
}
|
||||
if (!result) {
|
||||
resetPressedLink();
|
||||
}
|
||||
} else if (pressedLink != null) {
|
||||
try {
|
||||
onLinkClick((ClickableSpan) pressedLink.getSpan());
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
resetPressedLink();
|
||||
result = true;
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
resetPressedLink();
|
||||
}
|
||||
}
|
||||
return result || super.onTouchEvent(event);
|
||||
}
|
||||
};
|
||||
container = new FrameLayout(context);
|
||||
container.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
links = new LinkSpanDrawable.LinkCollector(container);
|
||||
container.setClickable(true);
|
||||
rippleBackground = Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 0, 0);
|
||||
|
||||
valueTextView = new TextView(context);
|
||||
|
@ -191,7 +144,7 @@ public class AboutLinkCell extends FrameLayout {
|
|||
if (wasPressed != pressed) {
|
||||
invalidate();
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
return pressed || super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,6 +183,46 @@ public class AboutLinkCell extends FrameLayout {
|
|||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
|
||||
if (showMoreTextView.getVisibility() == View.VISIBLE &&
|
||||
x >= showMoreTextBackgroundView.getLeft() && x <= showMoreTextBackgroundView.getRight() &&
|
||||
y >= showMoreTextBackgroundView.getTop() && y <= showMoreTextBackgroundView.getBottom()
|
||||
) {
|
||||
// event.offsetLocation(showMoreTextBackgroundView.getLeft(), showMoreTextBackgroundView.getTop());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
if (textLayout != null || nextLinesLayouts != null) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
resetPressedLink();
|
||||
LinkSpanDrawable link = hitLink(x, y);
|
||||
if (link != null) {
|
||||
result = true;
|
||||
links.addLink(pressedLink = link);
|
||||
AndroidUtilities.runOnUIThread(longPressedRunnable, ViewConfiguration.getLongPressTimeout());
|
||||
}
|
||||
} else if (pressedLink != null) {
|
||||
try {
|
||||
onLinkClick((ClickableSpan) pressedLink.getSpan());
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
resetPressedLink();
|
||||
result = true;
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
resetPressedLink();
|
||||
}
|
||||
}
|
||||
return result || super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private void setShowMoreMarginBottom(int marginBottom) {
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) showMoreTextBackgroundView.getLayoutParams();
|
||||
if (lp.bottomMargin != marginBottom) {
|
||||
|
@ -325,11 +318,6 @@ public class AboutLinkCell extends FrameLayout {
|
|||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(@Nullable OnClickListener l) {
|
||||
container.setOnClickListener(l);
|
||||
}
|
||||
|
||||
protected void didPressUrl(String url) {
|
||||
|
||||
}
|
||||
|
@ -426,7 +414,34 @@ public class AboutLinkCell extends FrameLayout {
|
|||
}
|
||||
};
|
||||
|
||||
private boolean checkTouchTextLayout(StaticLayout textLayout, int textX, int textY, int ex, int ey) {
|
||||
private LinkSpanDrawable hitLink(int x, int y) {
|
||||
if (x >= showMoreTextView.getLeft() && x <= showMoreTextView.getRight() &&
|
||||
y >= showMoreTextView.getTop() && y <= showMoreTextView.getBottom()) {
|
||||
return null;
|
||||
}
|
||||
if (getMeasuredWidth() > 0 && x > getMeasuredWidth() - AndroidUtilities.dp(23)) {
|
||||
return null;
|
||||
}
|
||||
LinkSpanDrawable link;
|
||||
if (firstThreeLinesLayout != null && expandT < 1 && shouldExpand) {
|
||||
if ((link = checkTouchTextLayout(firstThreeLinesLayout, textX, textY, x, y)) != null) {
|
||||
return link;
|
||||
}
|
||||
if (nextLinesLayouts != null) {
|
||||
for (int i = 0; i < nextLinesLayouts.length; ++i) {
|
||||
if ((link = checkTouchTextLayout(nextLinesLayouts[i], nextLinesLayoutsPositions[i].x, nextLinesLayoutsPositions[i].y, x, y)) != null) {
|
||||
return link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((link = checkTouchTextLayout(textLayout, textX, textY, x, y)) != null) {
|
||||
return link;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LinkSpanDrawable checkTouchTextLayout(StaticLayout textLayout, int textX, int textY, int ex, int ey) {
|
||||
try {
|
||||
int x = (int) (ex - textX);
|
||||
int y = (int) (ey - textY);
|
||||
|
@ -438,26 +453,19 @@ public class AboutLinkCell extends FrameLayout {
|
|||
Spannable buffer = (Spannable) textLayout.getText();
|
||||
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
|
||||
if (link.length != 0 && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) {
|
||||
resetPressedLink();
|
||||
pressedLink = new LinkSpanDrawable(link[0], parentFragment.getResourceProvider(), ex, ey);
|
||||
links.addLink(pressedLink);
|
||||
int start = buffer.getSpanStart(pressedLink.getSpan());
|
||||
int end = buffer.getSpanEnd(pressedLink.getSpan());
|
||||
LinkPath path = pressedLink.obtainNewPath();
|
||||
LinkSpanDrawable linkDrawable = new LinkSpanDrawable(link[0], parentFragment.getResourceProvider(), ex, ey);
|
||||
int start = buffer.getSpanStart(link[0]);
|
||||
int end = buffer.getSpanEnd(link[0]);
|
||||
LinkPath path = linkDrawable.obtainNewPath();
|
||||
path.setCurrentLayout(textLayout, start, textY);
|
||||
textLayout.getSelectionPath(start, end, path);
|
||||
AndroidUtilities.runOnUIThread(longPressedRunnable, ViewConfiguration.getLongPressTimeout());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
return linkDrawable;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onLinkClick(ClickableSpan pressedLink) {
|
||||
|
|
|
@ -18,6 +18,7 @@ import android.widget.FrameLayout;
|
|||
import android.widget.ImageView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ChatObject;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.R;
|
||||
|
@ -89,7 +90,7 @@ public class AdminedChannelCell extends FrameLayout {
|
|||
currentChannel = channel;
|
||||
avatarDrawable.setInfo(channel);
|
||||
nameTextView.setText(channel.title);
|
||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(url + channel.username);
|
||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(url + ChatObject.getPublicUsername(channel));
|
||||
stringBuilder.setSpan(new URLSpanNoUnderline(""), url.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
statusTextView.setText(stringBuilder);
|
||||
avatarImageView.setForUserOrChat(channel, avatarDrawable);
|
||||
|
|
|
@ -63,6 +63,12 @@ public abstract class BaseCell extends ViewGroup {
|
|||
setDrawableBounds(drawable, (int) x, (int) y, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
}
|
||||
|
||||
public static float setDrawableBounds(Drawable drawable, float x, float y, float h) {
|
||||
float w = drawable.getIntrinsicWidth() * h / drawable.getIntrinsicHeight();
|
||||
setDrawableBounds(drawable, (int) x, (int) y, (int) w, (int) h);
|
||||
return w;
|
||||
}
|
||||
|
||||
public static void setDrawableBounds(Drawable drawable, int x, int y, int w, int h) {
|
||||
if (drawable != null) {
|
||||
drawable.setBounds(x, y, x + w, y + h);
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.telegram.messenger.ImageReceiver;
|
|||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
|
@ -56,10 +57,12 @@ import org.telegram.messenger.browser.Browser;
|
|||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||
import org.telegram.ui.Components.AvatarDrawable;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
import org.telegram.ui.Components.Premium.StarParticlesView;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.TypefaceSpan;
|
||||
|
@ -143,6 +146,22 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
default void needShowEffectOverlay(ChatActionCell cell, TLRPC.Document document, TLRPC.VideoSize videoSize) {
|
||||
}
|
||||
|
||||
default BaseFragment getBaseFragment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default long getDialogId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default int getTopicId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
default boolean canDrawOutboundsContent() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ThemeDelegate extends Theme.ResourcesProvider {
|
||||
|
@ -453,7 +472,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, set == null);
|
||||
}
|
||||
}
|
||||
} else if (messageObject.type == 11) {
|
||||
} else if (messageObject.type == MessageObject.TYPE_ACTION_PHOTO) {
|
||||
imageReceiver.setAllowStartLottieAnimation(true);
|
||||
imageReceiver.setDelegate(null);
|
||||
imageReceiver.setRoundRadius(AndroidUtilities.roundMessageSize / 2);
|
||||
|
@ -499,6 +518,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
imageReceiver.setImageBitmap((Bitmap) null);
|
||||
}
|
||||
rippleView.setVisibility(messageObject.type == MessageObject.TYPE_GIFT_PREMIUM ? VISIBLE : GONE);
|
||||
ForumUtilities.applyTopicToMessage(messageObject);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
|
@ -548,7 +568,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
imageReceiver.onAttachedToWindow();
|
||||
setStarsPaused(false);
|
||||
|
||||
animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, animatedEmojiStack, textLayout);
|
||||
animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, canDrawInParent && (delegate != null && !delegate.canDrawOutboundsContent()), animatedEmojiStack, textLayout);
|
||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didUpdatePremiumGiftStickers);
|
||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad);
|
||||
}
|
||||
|
@ -581,7 +601,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
boolean result = false;
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (delegate != null) {
|
||||
if ((messageObject.type == 11 || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) && imageReceiver.isInsideImage(x, y)) {
|
||||
if ((messageObject.type == MessageObject.TYPE_ACTION_PHOTO || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) && imageReceiver.isInsideImage(x, y)) {
|
||||
imagePressed = true;
|
||||
result = true;
|
||||
}
|
||||
|
@ -694,7 +714,14 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
private void openLink(CharacterStyle link) {
|
||||
if (delegate != null && link instanceof URLSpan) {
|
||||
String url = ((URLSpan) link).getURL();
|
||||
if (url.startsWith("invite") && pressedLink instanceof URLSpanNoUnderline) {
|
||||
if (url.startsWith("topic") && pressedLink instanceof URLSpanNoUnderline) {
|
||||
URLSpanNoUnderline spanNoUnderline = (URLSpanNoUnderline) pressedLink;
|
||||
TLObject object = spanNoUnderline.getObject();
|
||||
if (object instanceof TLRPC.TL_forumTopic) {
|
||||
TLRPC.TL_forumTopic forumTopic = (TLRPC.TL_forumTopic) object;
|
||||
ForumUtilities.openTopic(delegate.getBaseFragment(), -delegate.getDialogId(), forumTopic, 0);
|
||||
}
|
||||
} else if (url.startsWith("invite") && pressedLink instanceof URLSpanNoUnderline) {
|
||||
URLSpanNoUnderline spanNoUnderline = (URLSpanNoUnderline) pressedLink;
|
||||
TLObject object = spanNoUnderline.getObject();
|
||||
if (object instanceof TLRPC.TL_chatInviteExported) {
|
||||
|
@ -738,9 +765,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
spoilersPool.addAll(spoilers);
|
||||
spoilers.clear();
|
||||
if (text instanceof Spannable)
|
||||
if (text instanceof Spannable) {
|
||||
SpoilerEffect.addSpoilers(this, textLayout, (Spannable) text, spoilersPool, spoilers);
|
||||
animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, animatedEmojiStack, textLayout);
|
||||
}
|
||||
animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, canDrawInParent && (delegate != null && !delegate.canDrawOutboundsContent()), animatedEmojiStack, textLayout);
|
||||
|
||||
textHeight = 0;
|
||||
textWidth = 0;
|
||||
|
@ -788,7 +816,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
int additionalHeight = 0;
|
||||
if (messageObject != null) {
|
||||
if (messageObject.type == 11) {
|
||||
if (messageObject.type == MessageObject.TYPE_ACTION_PHOTO) {
|
||||
additionalHeight = AndroidUtilities.roundMessageSize + AndroidUtilities.dp(10);
|
||||
} else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) {
|
||||
additionalHeight = giftRectSize + AndroidUtilities.dp(12);
|
||||
|
@ -813,26 +841,32 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
|
||||
private void buildLayout() {
|
||||
CharSequence text;
|
||||
CharSequence text = null;
|
||||
MessageObject messageObject = currentMessageObject;
|
||||
if (messageObject != null) {
|
||||
if (messageObject.messageOwner != null && messageObject.messageOwner.media != null && messageObject.messageOwner.media.ttl_seconds != 0) {
|
||||
if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photoEmpty) {
|
||||
text = LocaleController.getString("AttachPhotoExpired", R.string.AttachPhotoExpired);
|
||||
} else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_documentEmpty) {
|
||||
text = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired);
|
||||
if (delegate.getTopicId() == 0 && MessageObject.isTopicActionMessage(messageObject)) {
|
||||
TLRPC.TL_forumTopic topic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(-messageObject.getDialogId(), MessageObject.getTopicId(messageObject.messageOwner));
|
||||
text = ForumUtilities.createActionTextWithTopic(topic, messageObject);
|
||||
}
|
||||
if (text == null) {
|
||||
if (messageObject.messageOwner != null && messageObject.messageOwner.media != null && messageObject.messageOwner.media.ttl_seconds != 0) {
|
||||
if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photoEmpty) {
|
||||
text = LocaleController.getString("AttachPhotoExpired", R.string.AttachPhotoExpired);
|
||||
} else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_documentEmpty) {
|
||||
text = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired);
|
||||
} else {
|
||||
text = AnimatedEmojiSpan.cloneSpans(messageObject.messageText);
|
||||
}
|
||||
} else {
|
||||
text = AnimatedEmojiSpan.cloneSpans(messageObject.messageText);
|
||||
}
|
||||
} else {
|
||||
text = AnimatedEmojiSpan.cloneSpans(messageObject.messageText);
|
||||
}
|
||||
} else {
|
||||
text = customText;
|
||||
}
|
||||
createLayout(text, previousWidth);
|
||||
if (messageObject != null) {
|
||||
if (messageObject.type == 11) {
|
||||
if (messageObject.type == MessageObject.TYPE_ACTION_PHOTO) {
|
||||
imageReceiver.setImageCoords((previousWidth - AndroidUtilities.roundMessageSize) / 2f, textHeight + AndroidUtilities.dp(19), AndroidUtilities.roundMessageSize, AndroidUtilities.roundMessageSize);
|
||||
} else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) {
|
||||
createGiftPremiumLayouts(LocaleController.getString(R.string.ActionGiftPremiumTitle), LocaleController.formatString(R.string.ActionGiftPremiumSubtitle, LocaleController.formatPluralString("Months", messageObject.messageOwner.action.months)), LocaleController.getString(R.string.ActionGiftPremiumView), giftRectSize);
|
||||
|
@ -882,7 +916,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
}
|
||||
}
|
||||
if (messageObject != null && (messageObject.type == 11 || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM)) {
|
||||
if (messageObject != null && (messageObject.type == MessageObject.TYPE_ACTION_PHOTO || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM)) {
|
||||
imageReceiver.draw(canvas);
|
||||
}
|
||||
|
||||
|
@ -900,8 +934,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
canvas.save();
|
||||
SpoilerEffect.clipOutCanvas(canvas, spoilers);
|
||||
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f);
|
||||
textLayout.draw(canvas);
|
||||
if (delegate == null || delegate.canDrawOutboundsContent()) {
|
||||
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f);
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
for (SpoilerEffect eff : spoilers) {
|
||||
|
@ -1157,7 +1193,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
@Override
|
||||
public void onSuccessDownload(String fileName) {
|
||||
MessageObject messageObject = currentMessageObject;
|
||||
if (messageObject != null && messageObject.type == 11) {
|
||||
if (messageObject != null && messageObject.type == MessageObject.TYPE_ACTION_PHOTO) {
|
||||
TLRPC.PhotoSize strippedPhotoSize = null;
|
||||
for (int a = 0, N = messageObject.photoThumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = messageObject.photoThumbs.get(a);
|
||||
|
@ -1241,4 +1277,11 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
Paint paint = themeDelegate != null ? themeDelegate.getPaint(paintKey) : null;
|
||||
return paint != null ? paint : Theme.getThemePaint(paintKey);
|
||||
}
|
||||
|
||||
public void drawOutboundsContent(Canvas canvas) {
|
||||
canvas.save();
|
||||
canvas.translate(textXLeft, textY);
|
||||
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -143,7 +143,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
|
|||
linkImageView = new ImageReceiver(this);
|
||||
linkImageView.setLayerNum(1);
|
||||
linkImageView.setUseSharedAnimationQueue(true);
|
||||
letterDrawable = new LetterDrawable(resourcesProvider);
|
||||
letterDrawable = new LetterDrawable(resourcesProvider, LetterDrawable.STYLE_DEFAULT);
|
||||
radialProgress = new RadialProgress2(this);
|
||||
TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
|
||||
setFocusable(true);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,7 +15,6 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
|
@ -29,15 +28,12 @@ import android.util.TypedValue;
|
|||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
|
@ -49,6 +45,7 @@ import org.telegram.messenger.ImageReceiver;
|
|||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
|
@ -59,7 +56,6 @@ import org.telegram.ui.ActionBar.DrawerLayoutContainer;
|
|||
import org.telegram.ui.ActionBar.SimpleTextView;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||
import org.telegram.ui.Components.AnimatedFloat;
|
||||
import org.telegram.ui.Components.AvatarDrawable;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||
|
@ -83,7 +79,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
private ImageView shadowView;
|
||||
private ImageView arrowView;
|
||||
private RLottieImageView darkThemeView;
|
||||
private RLottieDrawable sunDrawable;
|
||||
private static RLottieDrawable sunDrawable;
|
||||
private boolean updateRightDrawable = true;
|
||||
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable status;
|
||||
private AnimatedStatusView animatedStatus;
|
||||
|
@ -139,7 +135,9 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
nameTextView.setTextSize(15);
|
||||
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
nameTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
|
||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 76, 28));
|
||||
nameTextView.setEllipsizeByGradient(true);
|
||||
nameTextView.setRightDrawableOutside(true);
|
||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 52, 28));
|
||||
|
||||
phoneTextView = new TextView(context);
|
||||
phoneTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
|
||||
|
@ -147,7 +145,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
phoneTextView.setMaxLines(1);
|
||||
phoneTextView.setSingleLine(true);
|
||||
phoneTextView.setGravity(Gravity.LEFT);
|
||||
addView(phoneTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 76, 9));
|
||||
addView(phoneTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 52, 9));
|
||||
|
||||
arrowView = new ImageView(context);
|
||||
arrowView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
|
@ -155,14 +153,18 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
addView(arrowView, LayoutHelper.createFrame(59, 59, Gravity.RIGHT | Gravity.BOTTOM));
|
||||
setArrowState(false);
|
||||
|
||||
sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null);
|
||||
if (Theme.isCurrentThemeDay()) {
|
||||
sunDrawable.setCustomEndFrame(36);
|
||||
} else {
|
||||
sunDrawable.setCustomEndFrame(0);
|
||||
sunDrawable.setCurrentFrame(36);
|
||||
boolean playDrawable;
|
||||
if (playDrawable = sunDrawable == null) {
|
||||
sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null);
|
||||
sunDrawable.setPlayInDirectionOfCustomEndFrame(true);
|
||||
if (Theme.isCurrentThemeDay()) {
|
||||
sunDrawable.setCustomEndFrame(0);
|
||||
sunDrawable.setCurrentFrame(0);
|
||||
} else {
|
||||
sunDrawable.setCurrentFrame(35);
|
||||
sunDrawable.setCustomEndFrame(36);
|
||||
}
|
||||
}
|
||||
sunDrawable.setPlayInDirectionOfCustomEndFrame(true);
|
||||
darkThemeView = new RLottieImageView(context) {
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
|
@ -189,6 +191,9 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
darkThemeView.setBackgroundDrawable(Theme.createSelectorDrawable(darkThemeBackgroundColor = Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(17)));
|
||||
Theme.setRippleDrawableForceSoftware((RippleDrawable) darkThemeView.getBackground());
|
||||
}
|
||||
if (!playDrawable && sunDrawable.getCustomEndFrame() != sunDrawable.getCurrentFrame()) {
|
||||
darkThemeView.playAnimation();
|
||||
}
|
||||
darkThemeView.setOnClickListener(v -> {
|
||||
if (switchingTheme) {
|
||||
return;
|
||||
|
@ -719,8 +724,15 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
|
|||
nameTextView.invalidate();
|
||||
} else if (id == NotificationCenter.userEmojiStatusUpdated) {
|
||||
setUser((TLRPC.User) args[0], accountsShown);
|
||||
} else if (id == NotificationCenter.currentUserPremiumStatusChanged || id == NotificationCenter.updateInterfaces) {
|
||||
} else if (id == NotificationCenter.currentUserPremiumStatusChanged) {
|
||||
setUser(UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser(), accountsShown);
|
||||
} else if (id == NotificationCenter.updateInterfaces) {
|
||||
int flags = (int) args[0];
|
||||
if ((flags & MessagesController.UPDATE_MASK_NAME) != 0 || (flags & MessagesController.UPDATE_MASK_AVATAR) != 0 ||
|
||||
(flags & MessagesController.UPDATE_MASK_STATUS) != 0 || (flags & MessagesController.UPDATE_MASK_PHONE) != 0 ||
|
||||
(flags & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 0) {
|
||||
setUser(UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser(), accountsShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
|
|||
super(context);
|
||||
|
||||
avatarDrawable = new AvatarDrawable();
|
||||
avatarDrawable.setTextSize(AndroidUtilities.dp(12));
|
||||
avatarDrawable.setTextSize(AndroidUtilities.dp(20));
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
imageView.setRoundRadius(AndroidUtilities.dp(18));
|
||||
|
@ -63,7 +63,8 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
|
|||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView.setMaxLines(1);
|
||||
textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 72, 0, 60, 0));
|
||||
textView.setEllipsizeByGradient(24);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 72, 0, 14, 0));
|
||||
|
||||
status = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(textView, AndroidUtilities.dp(20));
|
||||
textView.setRightDrawable(status);
|
||||
|
@ -141,14 +142,18 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
|
|||
if (user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
|
||||
textView.setDrawablePadding(AndroidUtilities.dp(4));
|
||||
status.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, true);
|
||||
textView.setRightDrawableOutside(true);
|
||||
} else if (user.emoji_status instanceof TLRPC.TL_emojiStatus) {
|
||||
textView.setDrawablePadding(AndroidUtilities.dp(4));
|
||||
status.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, true);
|
||||
textView.setRightDrawableOutside(true);
|
||||
} else if (MessagesController.getInstance(account).isPremiumUser(user)) {
|
||||
textView.setDrawablePadding(AndroidUtilities.dp(6));
|
||||
status.set(PremiumGradient.getInstance().premiumStarDrawableMini, true);
|
||||
textView.setRightDrawableOutside(true);
|
||||
} else {
|
||||
status.set((Drawable) null, true);
|
||||
textView.setRightDrawableOutside(false);
|
||||
}
|
||||
status.setColor(Theme.getColor(Theme.key_chats_verifiedBackground));
|
||||
imageView.getImageReceiver().setCurrentAccount(account);
|
||||
|
@ -163,10 +168,12 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
|
|||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (UserConfig.getActivatedAccountsCount() <= 1 || !NotificationsController.getInstance(accountNumber).showBadgeNumber) {
|
||||
textView.setRightPadding(0);
|
||||
return;
|
||||
}
|
||||
int counter = MessagesStorage.getInstance(accountNumber).getMainUnreadCount();
|
||||
if (counter <= 0) {
|
||||
textView.setRightPadding(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -181,6 +188,8 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
|
|||
canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, Theme.dialogs_countPaint);
|
||||
|
||||
canvas.drawText(text, rect.left + (rect.width() - textWidth) / 2, countTop + AndroidUtilities.dp(16), Theme.dialogs_countTextPaint);
|
||||
|
||||
textView.setRightPadding(countWidth + AndroidUtilities.dp(14 + 12));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -375,7 +375,7 @@ public class GroupCreateUserCell extends FrameLayout {
|
|||
}
|
||||
} else if (currentChat.has_geo) {
|
||||
statusTextView.setText(LocaleController.getString("MegaLocation", R.string.MegaLocation));
|
||||
} else if (TextUtils.isEmpty(currentChat.username)) {
|
||||
} else if (!ChatObject.isPublic(currentChat)) {
|
||||
if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) {
|
||||
statusTextView.setText(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate));
|
||||
} else {
|
||||
|
|
|
@ -316,7 +316,7 @@ public class ManageChatUserCell extends FrameLayout {
|
|||
}
|
||||
} else if (currentChat.has_geo) {
|
||||
statusTextView.setText(LocaleController.getString("MegaLocation", R.string.MegaLocation));
|
||||
} else if (TextUtils.isEmpty(currentChat.username)) {
|
||||
} else if (!ChatObject.isPublic(currentChat)) {
|
||||
statusTextView.setText(LocaleController.getString("MegaPrivate", R.string.MegaPrivate));
|
||||
} else {
|
||||
statusTextView.setText(LocaleController.getString("MegaPublic", R.string.MegaPublic));
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.widget.LinearLayout;
|
|||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ChatObject;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.Emoji;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
|
@ -131,8 +132,9 @@ public class MentionCell extends LinearLayout {
|
|||
imageView.setImageDrawable(avatarDrawable);
|
||||
}
|
||||
nameTextView.setText(chat.title);
|
||||
if (chat.username != null) {
|
||||
usernameTextView.setText("@" + chat.username);
|
||||
String username;
|
||||
if ((username = ChatObject.getPublicUsername(chat)) != null) {
|
||||
usernameTextView.setText("@" + username);
|
||||
} else {
|
||||
usernameTextView.setText("");
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ import android.text.TextPaint;
|
|||
import android.text.TextUtils;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ChatObject;
|
||||
|
@ -44,6 +42,8 @@ import org.telegram.ui.Components.CombinedDrawable;
|
|||
import org.telegram.ui.Components.Premium.PremiumGradient;
|
||||
import org.telegram.ui.NotificationsSettingsActivity;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class ProfileSearchCell extends BaseCell implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
private CharSequence currentName;
|
||||
|
@ -338,9 +338,10 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
|
||||
if (drawCount) {
|
||||
TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id);
|
||||
if (dialog != null && dialog.unread_count != 0) {
|
||||
lastUnreadCount = dialog.unread_count;
|
||||
String countString = String.format("%d", dialog.unread_count);
|
||||
int unreadCount = MessagesController.getInstance(currentAccount).getDialogUnreadCount(dialog);
|
||||
if (unreadCount != 0) {
|
||||
lastUnreadCount = unreadCount;
|
||||
String countString = String.format(Locale.US, "%d", unreadCount);
|
||||
countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(countString)));
|
||||
countLayout = new StaticLayout(countString, Theme.dialogs_countTextPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
|
||||
int w = countWidth + AndroidUtilities.dp(18);
|
||||
|
@ -410,9 +411,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
} else {
|
||||
if (ChatObject.isChannel(chat) && !chat.megagroup) {
|
||||
if (chat.participants_count != 0) {
|
||||
statusString = LocaleController.formatPluralString("Subscribers", chat.participants_count);
|
||||
statusString = LocaleController.formatPluralStringComma("Subscribers", chat.participants_count);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(chat.username)) {
|
||||
if (!ChatObject.isPublic(chat)) {
|
||||
statusString = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase();
|
||||
} else {
|
||||
statusString = LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase();
|
||||
|
@ -420,11 +421,11 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
}
|
||||
} else {
|
||||
if (chat.participants_count != 0) {
|
||||
statusString = LocaleController.formatPluralString("Members", chat.participants_count);
|
||||
statusString = LocaleController.formatPluralStringComma("Members", chat.participants_count);
|
||||
} else {
|
||||
if (chat.has_geo) {
|
||||
statusString = LocaleController.getString("MegaLocation", R.string.MegaLocation);
|
||||
} else if (TextUtils.isEmpty(chat.username)) {
|
||||
} else if (!ChatObject.isPublic(chat)) {
|
||||
statusString = LocaleController.getString("MegaPrivate", R.string.MegaPrivate).toLowerCase();
|
||||
} else {
|
||||
statusString = LocaleController.getString("MegaPublic", R.string.MegaPublic).toLowerCase();
|
||||
|
@ -554,6 +555,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
avatarImage.setImage(null, null, avatarDrawable, null, null, 0);
|
||||
}
|
||||
|
||||
avatarImage.setRoundRadius(chat != null && chat.forum ? AndroidUtilities.dp(16) : AndroidUtilities.dp(23));
|
||||
if (mask != 0) {
|
||||
boolean continueUpdate = false;
|
||||
if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 && user != null || (mask & MessagesController.UPDATE_MASK_CHAT_AVATAR) != 0 && chat != null) {
|
||||
|
@ -586,7 +588,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
}
|
||||
if (!continueUpdate && drawCount && (mask & MessagesController.UPDATE_MASK_READ_DIALOG_MESSAGE) != 0) {
|
||||
TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id);
|
||||
if (dialog != null && dialog.unread_count != lastUnreadCount) {
|
||||
if (dialog != null && MessagesController.getInstance(currentAccount).getDialogUnreadCount(dialog) != lastUnreadCount) {
|
||||
continueUpdate = true;
|
||||
}
|
||||
}
|
||||
|
@ -667,7 +669,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
|
|||
if (countLayout != null) {
|
||||
int x = countLeft - AndroidUtilities.dp(5.5f);
|
||||
rect.set(x, countTop, x + countWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23));
|
||||
canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id) ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint);
|
||||
canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id, 0) ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint);
|
||||
canvas.save();
|
||||
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
|
||||
countLayout.draw(canvas);
|
||||
|
|
|
@ -11,6 +11,7 @@ package org.telegram.ui.Cells;
|
|||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.SystemClock;
|
||||
import android.text.Layout;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
|
@ -19,10 +20,13 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
|||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.dynamicanimation.animation.FloatValueHolder;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ContactsController;
|
||||
import org.telegram.messenger.DialogObject;
|
||||
import org.telegram.messenger.ImageLocation;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.R;
|
||||
|
@ -30,16 +34,19 @@ import org.telegram.messenger.UserConfig;
|
|||
import org.telegram.messenger.UserObject;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.SimpleTextView;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AvatarDrawable;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.CheckBox2;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class ShareDialogCell extends FrameLayout {
|
||||
|
||||
private BackupImageView imageView;
|
||||
private TextView nameTextView;
|
||||
private SimpleTextView topicTextView;
|
||||
private CheckBox2 checkBox;
|
||||
private AvatarDrawable avatarDrawable = new AvatarDrawable();
|
||||
private TLRPC.User user;
|
||||
|
@ -49,6 +56,8 @@ public class ShareDialogCell extends FrameLayout {
|
|||
private long lastUpdateTime;
|
||||
private long currentDialog;
|
||||
|
||||
private boolean topicWasVisible;
|
||||
|
||||
private int currentAccount = UserConfig.selectedAccount;
|
||||
private final Theme.ResourcesProvider resourcesProvider;
|
||||
|
||||
|
@ -80,6 +89,14 @@ public class ShareDialogCell extends FrameLayout {
|
|||
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, currentType == TYPE_CREATE ? 58 : 66, 6, 0));
|
||||
|
||||
topicTextView = new SimpleTextView(context);
|
||||
topicTextView.setTextColor(getThemedColor(type == TYPE_CALL ? Theme.key_voipgroup_nameText : Theme.key_dialogTextBlack));
|
||||
topicTextView.setTextSize(12);
|
||||
topicTextView.setMaxLines(2);
|
||||
topicTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
|
||||
topicTextView.setAlignment(Layout.Alignment.ALIGN_CENTER);
|
||||
addView(topicTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, currentType == TYPE_CREATE ? 58 : 66, 6, 0));
|
||||
|
||||
checkBox = new CheckBox2(context, 21, resourcesProvider);
|
||||
checkBox.setColor(Theme.key_dialogRoundCheckBox, type == TYPE_CALL ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground, Theme.key_dialogRoundCheckBoxCheck);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
|
@ -122,6 +139,7 @@ public class ShareDialogCell extends FrameLayout {
|
|||
}
|
||||
imageView.setForUserOrChat(user, avatarDrawable);
|
||||
}
|
||||
imageView.setRoundRadius(AndroidUtilities.dp(28));
|
||||
} else {
|
||||
user = null;
|
||||
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-uid);
|
||||
|
@ -134,6 +152,7 @@ public class ShareDialogCell extends FrameLayout {
|
|||
}
|
||||
avatarDrawable.setInfo(chat);
|
||||
imageView.setForUserOrChat(chat, avatarDrawable);
|
||||
imageView.setRoundRadius(chat != null && chat.forum ? AndroidUtilities.dp(16) : AndroidUtilities.dp(28));
|
||||
}
|
||||
currentDialog = uid;
|
||||
checkBox.setChecked(checked, false);
|
||||
|
@ -145,6 +164,59 @@ public class ShareDialogCell extends FrameLayout {
|
|||
|
||||
public void setChecked(boolean checked, boolean animated) {
|
||||
checkBox.setChecked(checked, animated);
|
||||
if (!checked) {
|
||||
setTopic(null, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopic(TLRPC.TL_forumTopic topic, boolean animate) {
|
||||
boolean wasVisible = topicWasVisible;
|
||||
boolean visible = topic != null;
|
||||
if (wasVisible != visible || !animate) {
|
||||
SpringAnimation prevSpring = (SpringAnimation) topicTextView.getTag(R.id.spring_tag);
|
||||
if (prevSpring != null) {
|
||||
prevSpring.cancel();
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
topicTextView.setText(ForumUtilities.getTopicSpannedName(topic, topicTextView.getTextPaint()));
|
||||
topicTextView.requestLayout();
|
||||
}
|
||||
if (animate) {
|
||||
SpringAnimation springAnimation = new SpringAnimation(new FloatValueHolder(visible ? 0f : 1000f))
|
||||
.setSpring(new SpringForce(visible ? 1000f : 0f)
|
||||
.setStiffness(SpringForce.STIFFNESS_MEDIUM)
|
||||
.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY))
|
||||
.addUpdateListener((animation, value, velocity) -> {
|
||||
value /= 1000f;
|
||||
|
||||
topicTextView.setAlpha(value);
|
||||
nameTextView.setAlpha(1f - value);
|
||||
|
||||
topicTextView.setTranslationX((1f - value) * -AndroidUtilities.dp(10));
|
||||
nameTextView.setTranslationX(value * AndroidUtilities.dp(10));
|
||||
})
|
||||
.addEndListener((animation, canceled, value, velocity) -> {
|
||||
topicTextView.setTag(R.id.spring_tag, null);
|
||||
});
|
||||
topicTextView.setTag(R.id.spring_tag, springAnimation);
|
||||
springAnimation.start();
|
||||
} else {
|
||||
if (visible) {
|
||||
topicTextView.setAlpha(1f);
|
||||
nameTextView.setAlpha(0f);
|
||||
topicTextView.setTranslationX(0);
|
||||
nameTextView.setTranslationX(AndroidUtilities.dp(10));
|
||||
} else {
|
||||
topicTextView.setAlpha(0f);
|
||||
nameTextView.setAlpha(1f);
|
||||
topicTextView.setTranslationX(-AndroidUtilities.dp(10));
|
||||
nameTextView.setTranslationX(0);
|
||||
}
|
||||
}
|
||||
|
||||
topicWasVisible = visible;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -198,7 +270,9 @@ public class ShareDialogCell extends FrameLayout {
|
|||
int cy = imageView.getTop() + imageView.getMeasuredHeight() / 2;
|
||||
Theme.checkboxSquare_checkPaint.setColor(getThemedColor(Theme.key_dialogRoundCheckBox));
|
||||
Theme.checkboxSquare_checkPaint.setAlpha((int) (checkBox.getProgress() * 255));
|
||||
canvas.drawCircle(cx, cy, AndroidUtilities.dp(currentType == TYPE_CREATE ? 24 : 28), Theme.checkboxSquare_checkPaint);
|
||||
int radius = AndroidUtilities.dp(currentType == TYPE_CREATE ? 24 : 28);
|
||||
AndroidUtilities.rectTmp.set(cx - radius, cy - radius, cx + radius, cy + radius);
|
||||
canvas.drawRoundRect(AndroidUtilities.rectTmp, imageView.getRoundRadius()[0], imageView.getRoundRadius()[0], Theme.checkboxSquare_checkPaint);
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.CombinedDrawable;
|
||||
import org.telegram.ui.Components.Forum.ForumBubbleDrawable;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.LetterDrawable;
|
||||
|
||||
public class ShareTopicCell extends FrameLayout {
|
||||
|
||||
private BackupImageView imageView;
|
||||
private TextView nameTextView;
|
||||
|
||||
private long currentDialog;
|
||||
private long currentTopic;
|
||||
|
||||
private int currentAccount = UserConfig.selectedAccount;
|
||||
private final Theme.ResourcesProvider resourcesProvider;
|
||||
|
||||
public ShareTopicCell(Context context, Theme.ResourcesProvider resourcesProvider) {
|
||||
super(context);
|
||||
this.resourcesProvider = resourcesProvider;
|
||||
|
||||
setWillNotDraw(false);
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
imageView.setRoundRadius(AndroidUtilities.dp(28));
|
||||
addView(imageView, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 7, 0, 0));
|
||||
|
||||
nameTextView = new TextView(context);
|
||||
nameTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
||||
nameTextView.setMaxLines(2);
|
||||
nameTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
|
||||
nameTextView.setLines(2);
|
||||
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 66, 6, 0));
|
||||
|
||||
setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector), AndroidUtilities.dp(2), AndroidUtilities.dp(2)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(103), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setTopic(TLRPC.Dialog dialog, TLRPC.TL_forumTopic topic, boolean checked, CharSequence name) {
|
||||
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialog.id);
|
||||
if (name != null) {
|
||||
nameTextView.setText(name);
|
||||
} else if (chat != null) {
|
||||
nameTextView.setText(topic.title);
|
||||
} else {
|
||||
nameTextView.setText("");
|
||||
}
|
||||
if (topic.icon_emoji_id != 0) {
|
||||
imageView.setImageDrawable(null);
|
||||
imageView.setAnimatedEmojiDrawable(new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_FORUM_TOPIC, UserConfig.selectedAccount, topic.icon_emoji_id));
|
||||
} else {
|
||||
imageView.setAnimatedEmojiDrawable(null);
|
||||
ForumBubbleDrawable forumBubbleDrawable = new ForumBubbleDrawable(topic.icon_color);
|
||||
LetterDrawable letterDrawable = new LetterDrawable(null, LetterDrawable.STYLE_TOPIC_DRAWABLE);
|
||||
String title = topic.title.trim().toUpperCase();
|
||||
letterDrawable.setTitle(title.length() >= 1 ? title.substring(0, 1) : "");
|
||||
letterDrawable.scale = 1.8f;
|
||||
CombinedDrawable combinedDrawable = new CombinedDrawable(forumBubbleDrawable, letterDrawable, 0, 0);
|
||||
combinedDrawable.setFullsize(true);
|
||||
imageView.setImageDrawable(combinedDrawable);
|
||||
}
|
||||
imageView.setRoundRadius(chat != null && chat.forum && !checked ? AndroidUtilities.dp(16) : AndroidUtilities.dp(28));
|
||||
|
||||
currentDialog = dialog.id;
|
||||
currentTopic = topic.id;
|
||||
}
|
||||
|
||||
public long getCurrentDialog() {
|
||||
return currentDialog;
|
||||
}
|
||||
|
||||
public long getCurrentTopic() {
|
||||
return currentTopic;
|
||||
}
|
||||
|
||||
private int getThemedColor(String key) {
|
||||
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
|
||||
return color != null ? color : Theme.getColor(key);
|
||||
}
|
||||
}
|
|
@ -205,7 +205,7 @@ public class SharedLinkCell extends FrameLayout {
|
|||
setWillNotDraw(false);
|
||||
linkImageView = new ImageReceiver(this);
|
||||
linkImageView.setRoundRadius(AndroidUtilities.dp(4));
|
||||
letterDrawable = new LetterDrawable(resourcesProvider);
|
||||
letterDrawable = new LetterDrawable(resourcesProvider, LetterDrawable.STYLE_DEFAULT);
|
||||
|
||||
checkBox = new CheckBox2(context, 21, resourcesProvider);
|
||||
checkBox.setVisibility(INVISIBLE);
|
||||
|
|
|
@ -314,7 +314,7 @@ public class StickerEmojiCell extends FrameLayout implements NotificationCenter.
|
|||
if (v != null) {
|
||||
v.vibrate(200);
|
||||
}
|
||||
AndroidUtilities.shakeView(premiumIconView, 2, 0);
|
||||
AndroidUtilities.shakeView(premiumIconView);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,18 @@ import org.telegram.messenger.AndroidUtilities;
|
|||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.ui.ActionBar.SimpleTextView;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimatedTextView;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.RLottieDrawable;
|
||||
import org.telegram.ui.Components.RLottieImageView;
|
||||
import org.telegram.ui.Components.Switch;
|
||||
|
||||
public class TextCell extends FrameLayout {
|
||||
|
||||
public final SimpleTextView textView;
|
||||
public final SimpleTextView valueTextView;
|
||||
public final AnimatedTextView valueTextView;
|
||||
public final RLottieImageView imageView;
|
||||
private Switch checkBox;
|
||||
private ImageView valueImageView;
|
||||
private int leftPadding;
|
||||
private boolean needDivider;
|
||||
|
@ -40,20 +43,22 @@ public class TextCell extends FrameLayout {
|
|||
private boolean inDialogs;
|
||||
private boolean prioritizeTitleOverValue;
|
||||
private Theme.ResourcesProvider resourcesProvider;
|
||||
private boolean attached;
|
||||
|
||||
|
||||
public TextCell(Context context) {
|
||||
this(context, 23, false, null);
|
||||
this(context, 23, false, false, null);
|
||||
}
|
||||
|
||||
public TextCell(Context context, Theme.ResourcesProvider resourcesProvider) {
|
||||
this(context, 23, false, resourcesProvider);
|
||||
this(context, 23, false, false, resourcesProvider);
|
||||
}
|
||||
|
||||
public TextCell(Context context, int left, boolean dialog) {
|
||||
this(context, left, dialog, null);
|
||||
this(context, left, dialog, false, null);
|
||||
}
|
||||
|
||||
public TextCell(Context context, int left, boolean dialog, Theme.ResourcesProvider resourcesProvider) {
|
||||
public TextCell(Context context, int left, boolean dialog, boolean needCheck, Theme.ResourcesProvider resourcesProvider) {
|
||||
super(context);
|
||||
|
||||
this.resourcesProvider = resourcesProvider;
|
||||
|
@ -66,9 +71,10 @@ public class TextCell extends FrameLayout {
|
|||
textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
valueTextView = new SimpleTextView(context);
|
||||
valueTextView = new AnimatedTextView(context);
|
||||
valueTextView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlue2 : Theme.key_windowBackgroundWhiteValueText, resourcesProvider));
|
||||
valueTextView.setTextSize(16);
|
||||
valueTextView.setPadding(0, AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18));
|
||||
valueTextView.setTextSize(AndroidUtilities.dp(16));
|
||||
valueTextView.setGravity(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT);
|
||||
valueTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
addView(valueTextView);
|
||||
|
@ -82,9 +88,19 @@ public class TextCell extends FrameLayout {
|
|||
valueImageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
addView(valueImageView);
|
||||
|
||||
if (needCheck) {
|
||||
checkBox = new Switch(context, resourcesProvider);
|
||||
checkBox.setColors(Theme.key_switchTrack, Theme.key_switchTrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite);
|
||||
addView(checkBox, LayoutHelper.createFrame(37, 20, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 22, 0, 22, 0));
|
||||
}
|
||||
|
||||
setFocusable(true);
|
||||
}
|
||||
|
||||
public Switch getCheckBox() {
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
public void setIsInDialogs() {
|
||||
inDialogs = true;
|
||||
}
|
||||
|
@ -97,7 +113,7 @@ public class TextCell extends FrameLayout {
|
|||
return imageView;
|
||||
}
|
||||
|
||||
public SimpleTextView getValueTextView() {
|
||||
public AnimatedTextView getValueTextView() {
|
||||
return valueTextView;
|
||||
}
|
||||
|
||||
|
@ -117,10 +133,10 @@ public class TextCell extends FrameLayout {
|
|||
|
||||
if (prioritizeTitleOverValue) {
|
||||
textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(103 + leftPadding) - textView.getTextWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(103 + leftPadding) - textView.getTextWidth(), LocaleController.isRTL ? MeasureSpec.AT_MOST : MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(leftPadding), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding) - valueTextView.getTextWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(leftPadding), LocaleController.isRTL ? MeasureSpec.AT_MOST : MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding) - valueTextView.width(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
}
|
||||
if (imageView.getVisibility() == VISIBLE) {
|
||||
imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
|
||||
|
@ -128,9 +144,20 @@ public class TextCell extends FrameLayout {
|
|||
if (valueImageView.getVisibility() == VISIBLE) {
|
||||
valueImageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
|
||||
}
|
||||
if (checkBox != null) {
|
||||
checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(37), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
|
||||
}
|
||||
setMeasuredDimension(width, AndroidUtilities.dp(50) + (needDivider ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
if (checkBox != null) {
|
||||
checkBox.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
int height = bottom - top;
|
||||
|
@ -162,6 +189,11 @@ public class TextCell extends FrameLayout {
|
|||
viewLeft = LocaleController.isRTL ? AndroidUtilities.dp(23) : width - valueImageView.getMeasuredWidth() - AndroidUtilities.dp(23);
|
||||
valueImageView.layout(viewLeft, viewTop, viewLeft + valueImageView.getMeasuredWidth(), viewTop + valueImageView.getMeasuredHeight());
|
||||
}
|
||||
if (checkBox != null && checkBox.getVisibility() == VISIBLE) {
|
||||
viewTop = (height - checkBox.getMeasuredHeight()) / 2;
|
||||
viewLeft = LocaleController.isRTL ? AndroidUtilities.dp(22) : width - checkBox.getMeasuredWidth() - AndroidUtilities.dp(22);
|
||||
checkBox.layout(viewLeft, viewTop, viewLeft + checkBox.getMeasuredWidth(), viewTop + checkBox.getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextColor(int color) {
|
||||
|
@ -180,7 +212,7 @@ public class TextCell extends FrameLayout {
|
|||
public void setText(String text, boolean divider) {
|
||||
imageLeft = 21;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(null);
|
||||
valueTextView.setText(null, false);
|
||||
imageView.setVisibility(GONE);
|
||||
valueTextView.setVisibility(GONE);
|
||||
valueImageView.setVisibility(GONE);
|
||||
|
@ -192,7 +224,7 @@ public class TextCell extends FrameLayout {
|
|||
imageLeft = 21;
|
||||
offsetFromImage = 71;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(null);
|
||||
valueTextView.setText(null, false);
|
||||
imageView.setImageResource(resId);
|
||||
imageView.setVisibility(VISIBLE);
|
||||
valueTextView.setVisibility(GONE);
|
||||
|
@ -206,7 +238,7 @@ public class TextCell extends FrameLayout {
|
|||
offsetFromImage = 68;
|
||||
imageLeft = 18;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(null);
|
||||
valueTextView.setText(null, false);
|
||||
imageView.setColorFilter(null);
|
||||
if (drawable instanceof RLottieDrawable) {
|
||||
imageView.setAnimation((RLottieDrawable) drawable);
|
||||
|
@ -230,22 +262,33 @@ public class TextCell extends FrameLayout {
|
|||
}
|
||||
|
||||
public void setTextAndValue(String text, String value, boolean divider) {
|
||||
setTextAndValue(text, value, false, divider);
|
||||
}
|
||||
|
||||
public void setTextAndValue(String text, String value, boolean animated, boolean divider) {
|
||||
imageLeft = 21;
|
||||
offsetFromImage = 71;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(value);
|
||||
valueTextView.setText(value, animated);
|
||||
valueTextView.setVisibility(VISIBLE);
|
||||
imageView.setVisibility(GONE);
|
||||
valueImageView.setVisibility(GONE);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!needDivider);
|
||||
if (checkBox != null) {
|
||||
checkBox.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextAndValueAndIcon(String text, String value, int resId, boolean divider) {
|
||||
setTextAndValueAndIcon(text, value, false, resId, divider);
|
||||
}
|
||||
|
||||
public void setTextAndValueAndIcon(String text, String value, boolean animated, int resId, boolean divider) {
|
||||
imageLeft = 21;
|
||||
offsetFromImage = 71;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(value);
|
||||
valueTextView.setText(value, animated);
|
||||
valueTextView.setVisibility(VISIBLE);
|
||||
valueImageView.setVisibility(GONE);
|
||||
imageView.setVisibility(VISIBLE);
|
||||
|
@ -253,13 +296,33 @@ public class TextCell extends FrameLayout {
|
|||
imageView.setImageResource(resId);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!needDivider);
|
||||
if (checkBox != null) {
|
||||
checkBox.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextAndCheckAndIcon(String text, boolean checked, int resId, boolean divider) {
|
||||
imageLeft = 21;
|
||||
offsetFromImage = 71;
|
||||
textView.setText(text);
|
||||
valueTextView.setVisibility(GONE);
|
||||
valueImageView.setVisibility(GONE);
|
||||
if (checkBox != null) {
|
||||
checkBox.setVisibility(VISIBLE);
|
||||
checkBox.setChecked(checked, false);
|
||||
}
|
||||
imageView.setVisibility(VISIBLE);
|
||||
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
|
||||
imageView.setImageResource(resId);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!needDivider);
|
||||
}
|
||||
|
||||
public void setTextAndValueDrawable(String text, Drawable drawable, boolean divider) {
|
||||
imageLeft = 21;
|
||||
offsetFromImage = 71;
|
||||
textView.setText(text);
|
||||
valueTextView.setText(null);
|
||||
valueTextView.setText(null, false);
|
||||
valueImageView.setVisibility(VISIBLE);
|
||||
valueImageView.setImageDrawable(drawable);
|
||||
valueTextView.setVisibility(GONE);
|
||||
|
@ -267,6 +330,9 @@ public class TextCell extends FrameLayout {
|
|||
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!needDivider);
|
||||
if (checkBox != null) {
|
||||
checkBox.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,4 +364,51 @@ public class TextCell extends FrameLayout {
|
|||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
checkBox.setChecked(checked, true);
|
||||
}
|
||||
|
||||
public void showEnabledAlpha(boolean show) {
|
||||
float alpha = show ? 0.5f : 1f;
|
||||
if (attached) {
|
||||
if (imageView != null) {
|
||||
imageView.animate().alpha(alpha).start();
|
||||
}
|
||||
if (textView != null) {
|
||||
textView.animate().alpha(alpha).start();
|
||||
}
|
||||
if (valueTextView != null) {
|
||||
valueTextView.animate().alpha(alpha).start();
|
||||
}
|
||||
if (valueImageView != null) {
|
||||
valueImageView.animate().alpha(alpha).start();
|
||||
}
|
||||
} else {
|
||||
if (imageView != null) {
|
||||
imageView.setAlpha(alpha);
|
||||
}
|
||||
if (textView != null) {
|
||||
textView.setAlpha(alpha);
|
||||
}
|
||||
if (valueTextView != null) {
|
||||
valueTextView.setAlpha(alpha);
|
||||
}
|
||||
if (valueImageView != null) {
|
||||
valueImageView.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
attached = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
attached = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import android.widget.TextView;
|
|||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.AnimationProperties;
|
||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||
|
@ -144,7 +143,7 @@ public class TextCheckCell extends FrameLayout {
|
|||
public void setTextAndCheck(String text, boolean checked, boolean divider) {
|
||||
textView.setText(text);
|
||||
isMultiline = false;
|
||||
checkBox.setChecked(checked, false);
|
||||
checkBox.setChecked(checked, attached);
|
||||
needDivider = divider;
|
||||
valueTextView.setVisibility(GONE);
|
||||
LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams();
|
||||
|
@ -340,4 +339,18 @@ public class TextCheckCell extends FrameLayout {
|
|||
}
|
||||
info.setContentDescription(sb);
|
||||
}
|
||||
|
||||
boolean attached;
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
attached = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
attached = false;
|
||||
}
|
||||
}
|
|
@ -33,10 +33,14 @@ public class TextCheckCell2 extends FrameLayout {
|
|||
private boolean isMultiline;
|
||||
|
||||
public TextCheckCell2(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TextCheckCell2(Context context, Theme.ResourcesProvider resourcesProvider) {
|
||||
super(context);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
|
@ -46,7 +50,7 @@ public class TextCheckCell2 extends FrameLayout {
|
|||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 64 : 21, 0, LocaleController.isRTL ? 21 : 64, 0));
|
||||
|
||||
valueTextView = new TextView(context);
|
||||
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
||||
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider));
|
||||
valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
|
||||
valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
valueTextView.setLines(1);
|
||||
|
|
|
@ -13,8 +13,11 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.FrameLayout;
|
||||
|
@ -24,17 +27,20 @@ import android.widget.TextView;
|
|||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.Emoji;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.ui.ActionBar.SimpleTextView;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.LinkSpanDrawable;
|
||||
|
||||
public class TextDetailCell extends FrameLayout {
|
||||
|
||||
private final TextView textView;
|
||||
private final TextView valueTextView;
|
||||
private final LinkSpanDrawable.LinksTextView valueTextView;
|
||||
private final TextView showMoreTextView = null;
|
||||
private final ImageView imageView;
|
||||
private boolean needDivider;
|
||||
private boolean contentDescriptionValueFirst;
|
||||
private boolean multiline;
|
||||
|
||||
private Theme.ResourcesProvider resourcesProvider;
|
||||
|
||||
|
@ -43,6 +49,10 @@ public class TextDetailCell extends FrameLayout {
|
|||
}
|
||||
|
||||
public TextDetailCell(Context context, Theme.ResourcesProvider resourcesProvider) {
|
||||
this(context, resourcesProvider, false);
|
||||
}
|
||||
|
||||
public TextDetailCell(Context context, Theme.ResourcesProvider resourcesProvider, boolean multiline) {
|
||||
super(context);
|
||||
this.resourcesProvider = resourcesProvider;
|
||||
|
||||
|
@ -57,15 +67,27 @@ public class TextDetailCell extends FrameLayout {
|
|||
textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 23, 8, 23, 0));
|
||||
|
||||
valueTextView = new TextView(context);
|
||||
valueTextView = new LinkSpanDrawable.LinksTextView(context);
|
||||
valueTextView.setOnLinkLongPressListener(span -> {
|
||||
if (span != null) {
|
||||
try {
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
} catch (Exception ignore) {};
|
||||
span.onClick(valueTextView);
|
||||
}
|
||||
});
|
||||
if (this.multiline = multiline) {
|
||||
setMinimumHeight(AndroidUtilities.dp(60));
|
||||
} else {
|
||||
valueTextView.setLines(1);
|
||||
valueTextView.setSingleLine(true);
|
||||
}
|
||||
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider));
|
||||
valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
|
||||
valueTextView.setLines(1);
|
||||
valueTextView.setMaxLines(1);
|
||||
valueTextView.setSingleLine(true);
|
||||
valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
valueTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 23, 33, 23, 0));
|
||||
valueTextView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 23, 33, 23, 10));
|
||||
|
||||
imageView = new ImageView(context);
|
||||
imageView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
|
@ -73,15 +95,24 @@ public class TextDetailCell extends FrameLayout {
|
|||
addView(imageView, LayoutHelper.createFrameRelatively(48, 48, Gravity.END | Gravity.CENTER_VERTICAL, 0, 0, 12, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
boolean hit = valueTextView.hit((int) ev.getX() - valueTextView.getLeft(), (int) ev.getY() - valueTextView.getTop()) != null;
|
||||
if (hit) {
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(
|
||||
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(60) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)
|
||||
multiline ? heightMeasureSpec : MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(60) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)
|
||||
);
|
||||
}
|
||||
|
||||
public void setTextAndValue(String text, String value, boolean divider) {
|
||||
public void setTextAndValue(CharSequence text, CharSequence value, boolean divider) {
|
||||
textView.setText(text);
|
||||
valueTextView.setText(value);
|
||||
needDivider = divider;
|
||||
|
@ -93,6 +124,7 @@ public class TextDetailCell extends FrameLayout {
|
|||
}
|
||||
|
||||
public void setImage(Drawable drawable, CharSequence imageContentDescription) {
|
||||
((MarginLayoutParams) valueTextView.getLayoutParams()).rightMargin = !LocaleController.isRTL && drawable != null ? AndroidUtilities.dp(28 + 12 + 12 + 6) : AndroidUtilities.dp(23);
|
||||
imageView.setImageDrawable(drawable);
|
||||
imageView.setFocusable(drawable != null);
|
||||
imageView.setContentDescription(imageContentDescription);
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.telegram.messenger.MessageObject;
|
|||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.ActionBarLayout;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.ActionBar.INavigationLayout;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackgroundGradientDrawable;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
@ -47,13 +47,13 @@ public class ThemePreviewMessagesCell extends LinearLayout {
|
|||
private Drawable oldBackgroundDrawable;
|
||||
private ChatMessageCell[] cells = new ChatMessageCell[2];
|
||||
private Drawable shadowDrawable;
|
||||
private ActionBarLayout parentLayout;
|
||||
private INavigationLayout parentLayout;
|
||||
private final int type;
|
||||
|
||||
public BaseFragment fragment;
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public ThemePreviewMessagesCell(Context context, ActionBarLayout layout, int type) {
|
||||
public ThemePreviewMessagesCell(Context context, INavigationLayout layout, int type) {
|
||||
super(context);
|
||||
this.type = type;
|
||||
int currentAccount = UserConfig.selectedAccount;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class TopicExceptionCell extends FrameLayout {
|
||||
|
||||
public boolean drawDivider;
|
||||
BackupImageView backupImageView;
|
||||
TextView title;
|
||||
TextView subtitle;
|
||||
|
||||
public TopicExceptionCell(Context context) {
|
||||
super(context);
|
||||
backupImageView = new BackupImageView(context);
|
||||
addView(backupImageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER_VERTICAL, 20, 0, 0, 0));
|
||||
|
||||
title = new TextView(context);
|
||||
title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
title.setMaxLines(1);
|
||||
addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 72, 8, 12, 0));
|
||||
|
||||
|
||||
subtitle = new TextView(context);
|
||||
subtitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
|
||||
subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||
addView(subtitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 72, 32, 12, 0));
|
||||
|
||||
}
|
||||
|
||||
public void setTopic(long dialogId, TLRPC.TL_forumTopic topic) {
|
||||
ForumUtilities.setTopicIcon(backupImageView, topic);
|
||||
title.setText(topic.title);
|
||||
subtitle.setText(MessagesController.getInstance(UserConfig.selectedAccount).getMutedString(dialogId, topic.id));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
if (drawDivider) {
|
||||
canvas.drawLine(AndroidUtilities.dp(72), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class TopicSearchCell extends FrameLayout {
|
||||
|
||||
BackupImageView backupImageView;
|
||||
TextView textView;
|
||||
TLRPC.TL_forumTopic topic;
|
||||
public boolean drawDivider;
|
||||
|
||||
public TopicSearchCell(@NonNull Context context) {
|
||||
super(context);
|
||||
backupImageView = new BackupImageView(context);
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
|
||||
if (LocaleController.isRTL) {
|
||||
addView(backupImageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 12, 0, 12, 0));
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 12, 0, 56, 0));
|
||||
} else {
|
||||
addView(backupImageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER_VERTICAL, 12, 0, 12, 0));
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 56, 0, 12, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setTopic(TLRPC.TL_forumTopic topic) {
|
||||
this.topic = topic;
|
||||
if (TextUtils.isEmpty(topic.searchQuery)) {
|
||||
textView.setText(topic.title);
|
||||
} else {
|
||||
textView.setText(AndroidUtilities.highlightText(topic.title, topic.searchQuery, null));
|
||||
}
|
||||
ForumUtilities.setTopicIcon(backupImageView, topic);
|
||||
}
|
||||
|
||||
public TLRPC.TL_forumTopic getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
if (drawDivider) {
|
||||
int left = AndroidUtilities.dp(56);
|
||||
if (LocaleController.isRTL) {
|
||||
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - left, getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
} else {
|
||||
canvas.drawLine(left, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -275,7 +275,7 @@ public class UserCell2 extends FrameLayout {
|
|||
if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) {
|
||||
if (currentChat.participants_count != 0) {
|
||||
statusTextView.setText(LocaleController.formatPluralString("Subscribers", currentChat.participants_count));
|
||||
} else if (TextUtils.isEmpty(currentChat.username)) {
|
||||
} else if (!ChatObject.isPublic(currentChat)) {
|
||||
statusTextView.setText(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate));
|
||||
} else {
|
||||
statusTextView.setText(LocaleController.getString("ChannelPublic", R.string.ChannelPublic));
|
||||
|
@ -285,7 +285,7 @@ public class UserCell2 extends FrameLayout {
|
|||
statusTextView.setText(LocaleController.formatPluralString("Members", currentChat.participants_count));
|
||||
} else if (currentChat.has_geo) {
|
||||
statusTextView.setText(LocaleController.getString("MegaLocation", R.string.MegaLocation));
|
||||
} else if (TextUtils.isEmpty(currentChat.username)) {
|
||||
} else if (!ChatObject.isPublic(currentChat)) {
|
||||
statusTextView.setText(LocaleController.getString("MegaPrivate", R.string.MegaPrivate));
|
||||
} else {
|
||||
statusTextView.setText(LocaleController.getString("MegaPublic", R.string.MegaPublic));
|
||||
|
|
|
@ -120,7 +120,7 @@ public class ChangeBioActivity extends BaseFragment {
|
|||
if (v != null) {
|
||||
v.vibrate(200);
|
||||
}
|
||||
AndroidUtilities.shakeView(checkTextView, 2, 0);
|
||||
AndroidUtilities.shakeView(checkTextView);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1097,7 +1097,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
AndroidUtilities.updateViewVisibilityAnimated(progressView, false, 0.3f, true);
|
||||
chatListView.setEmptyView(emptyViewContainer);
|
||||
}
|
||||
chatListView.setAnimateEmptyView(true, 1);
|
||||
chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE);
|
||||
|
||||
undoView = new UndoView(context);
|
||||
undoView.setAdditionalTranslationY(AndroidUtilities.dp(51));
|
||||
|
@ -1128,7 +1128,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
ArrayList<CharSequence> items = new ArrayList<>();
|
||||
final ArrayList<Integer> options = new ArrayList<>();
|
||||
|
||||
if (selectedObject.type == 0 || selectedObject.caption != null) {
|
||||
if (selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.caption != null) {
|
||||
items.add(LocaleController.getString("Copy", R.string.Copy));
|
||||
options.add(3);
|
||||
}
|
||||
|
@ -1385,13 +1385,13 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
if (path == null || path.length() == 0) {
|
||||
path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString();
|
||||
}
|
||||
if (selectedObject.type == 3 || selectedObject.type == 1) {
|
||||
if (selectedObject.type == MessageObject.TYPE_VIDEO || selectedObject.type == MessageObject.TYPE_PHOTO) {
|
||||
if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4);
|
||||
selectedObject = null;
|
||||
return;
|
||||
}
|
||||
MediaController.saveFile(path, getParentActivity(), selectedObject.type == 3 ? 1 : 0, null, null);
|
||||
MediaController.saveFile(path, getParentActivity(), selectedObject.type == MessageObject.TYPE_VIDEO ? 1 : 0, null, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1571,7 +1571,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
}
|
||||
if (messageObject.type == 6) {
|
||||
return -1;
|
||||
} else if (messageObject.type == 10 || messageObject.type == 11 || messageObject.type == 16) {
|
||||
} else if (messageObject.type == 10 || messageObject.type == MessageObject.TYPE_ACTION_PHOTO || messageObject.type == MessageObject.TYPE_PHONE_CALL) {
|
||||
if (messageObject.getId() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1619,7 +1619,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
}
|
||||
return 4;
|
||||
}
|
||||
} else if (messageObject.type == 12) {
|
||||
} else if (messageObject.type == MessageObject.TYPE_CONTACT) {
|
||||
return 8;
|
||||
} else if (messageObject.isMediaEmpty()) {
|
||||
return 3;
|
||||
|
@ -1649,7 +1649,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onRemoveFromParent() {
|
||||
public void onRemoveFromParent() {
|
||||
MediaController.getInstance().setTextureView(videoTextureView, null, null, false);
|
||||
}
|
||||
|
||||
|
@ -1910,7 +1910,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onBecomeFullyHidden() {
|
||||
public void onBecomeFullyHidden() {
|
||||
if (undoView != null) {
|
||||
undoView.hide(true, 0);
|
||||
}
|
||||
|
@ -1944,7 +1944,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
if (message.type == 3) {
|
||||
if (message.type == MessageObject.TYPE_VIDEO) {
|
||||
builder.setMessage(LocaleController.getString("NoPlayerInstalled", R.string.NoPlayerInstalled));
|
||||
} else {
|
||||
builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type));
|
||||
|
@ -2063,9 +2063,9 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean needPlayMessage(MessageObject messageObject) {
|
||||
public boolean needPlayMessage(MessageObject messageObject, boolean muted) {
|
||||
if (messageObject.isVoice() || messageObject.isRoundVideo()) {
|
||||
boolean result = MediaController.getInstance().playMessage(messageObject);
|
||||
boolean result = MediaController.getInstance().playMessage(messageObject, muted);
|
||||
MediaController.getInstance().setVoiceMessagesPlaylist(null, false);
|
||||
return result;
|
||||
} else if (messageObject.isMusic()) {
|
||||
|
@ -2253,10 +2253,10 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
MessageObject message = cell.getMessageObject();
|
||||
if (message.getInputStickerSet() != null) {
|
||||
showDialog(new StickersAlert(getParentActivity(), ChannelAdminLogActivity.this, message.getInputStickerSet(), null, null));
|
||||
} else if (message.isVideo() || message.type == 1 || message.type == 0 && !message.isWebpageDocument() || message.isGif()) {
|
||||
} else if (message.isVideo() || message.type == MessageObject.TYPE_PHOTO || message.type == MessageObject.TYPE_TEXT && !message.isWebpageDocument() || message.isGif()) {
|
||||
PhotoViewer.getInstance().setParentActivity(ChannelAdminLogActivity.this);
|
||||
PhotoViewer.getInstance().openPhoto(message, null, 0, 0, provider);
|
||||
} else if (message.type == 3) {
|
||||
PhotoViewer.getInstance().openPhoto(message, null, 0, 0, 0, provider);
|
||||
} else if (message.type == MessageObject.TYPE_VIDEO) {
|
||||
try {
|
||||
File f = null;
|
||||
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
|
||||
|
@ -2276,14 +2276,14 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
} catch (Exception e) {
|
||||
alertUserOpenError(message);
|
||||
}
|
||||
} else if (message.type == 4) {
|
||||
} else if (message.type == MessageObject.TYPE_GEO) {
|
||||
if (!AndroidUtilities.isMapsInstalled(ChannelAdminLogActivity.this)) {
|
||||
return;
|
||||
}
|
||||
LocationActivity fragment = new LocationActivity(0);
|
||||
fragment.setMessageObject(message);
|
||||
presentFragment(fragment);
|
||||
} else if (message.type == 9 || message.type == 0) {
|
||||
} else if (message.type == MessageObject.TYPE_FILE || message.type == MessageObject.TYPE_TEXT) {
|
||||
if (message.getDocumentName().toLowerCase().endsWith("attheme")) {
|
||||
File locFile = null;
|
||||
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
|
||||
|
@ -2366,7 +2366,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
ImageLocation imageLocation = ImageLocation.getForPhoto(photoSize, message.messageOwner.action.photo);
|
||||
PhotoViewer.getInstance().openPhoto(photoSize.location, imageLocation, provider);
|
||||
} else {
|
||||
PhotoViewer.getInstance().openPhoto(message, null, 0, 0, provider);
|
||||
PhotoViewer.getInstance().openPhoto(message, null, 0, 0, 0, provider);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2450,6 +2450,16 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseFragment getBaseFragment() {
|
||||
return ChannelAdminLogActivity.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDialogId() {
|
||||
return -currentChat.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didPressReplyMessage(ChatActionCell cell, int id) {
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue