Merge branch 'dev'

This commit is contained in:
DrKLO 2014-10-23 19:31:55 +04:00
commit cd9d188fe2
184 changed files with 13661 additions and 7260 deletions

View File

@ -1,21 +1,30 @@
## Telegram messenger for Android
[Telegram](http://telegram.org) is a messaging app with a focus on speed and security. Its superfast, simple and free.
This repo contains the official source code for [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger).
This repo contains official [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger) source code.
##Creating your Telegram Application
We welcome all developers to use our API and source code to create applications on our platform.
There are several things we require from **all developers** for the moment.
1. [**Obtain your own api_id**](https://core.telegram.org/api/obtaining_api_id) for your application.
2. Please **do not** use the name Telegram for your app — or make sure your users understand that it is unofficial.
3. Kindly **do not** use our standard logo (white paper plane in a blue circle) as your app's logo.
3. Please study our [**security guidelines**](https://core.telegram.org/mtproto/security_guidelines) and take good care of your users' data and privacy.
4. Please remember to publish **your** code too in order to comply with the licences.
### API, Protocol documentation
Documentation for Telegram API is available here: http://core.telegram.org/api
Telegram API manuals: http://core.telegram.org/api
Documentation for MTproto protocol is available here: http://core.telegram.org/mtproto
MTproto protocol manuals: http://core.telegram.org/mtproto
### Usage
**Beware of using dev branch and uploading it to any markets, in most cases it will work as you expecting**
First of all your should take a look to **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
**Beware of using the dev branch and uploading it to any markets, in many cases it not will work as expected**.
First of all, take a look at **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
Import the root folder into your IDE (tested on Android Studio), then run project.
### Localization

View File

@ -19,13 +19,13 @@ tasks.withType(JavaCompile) {
dependencies {
compile 'com.android.support:support-v4:20.0.+'
compile 'com.google.android.gms:play-services:3.2.+'
compile 'net.hockeyapp.android:HockeySDK:3.0.1'
compile 'net.hockeyapp.android:HockeySDK:3.0.2'
compile 'com.googlecode.mp4parser:isoparser:1.0.+'
}
android {
compileSdkVersion 19
buildToolsVersion '20.0.0'
compileSdkVersion 21
buildToolsVersion '21.0.2'
signingConfigs {
debug {
@ -80,7 +80,7 @@ android {
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 355
versionName "1.9.4"
versionCode 374
versionName "1.9.6"
}
}

View File

@ -9,12 +9,11 @@ static inline uint64_t get_colors (const uint8_t *p) {
return p[0] + (p[1] << 16) + ((uint64_t)p[2] << 32);
}
static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pixels) {
static void fastBlurMore(int imageWidth, int imageHeight, int imageStride, void *pixels, int radius) {
uint8_t *pix = (uint8_t *)pixels;
const int w = imageWidth;
const int h = imageHeight;
const int stride = imageStride;
const int radius = 3;
const int r1 = radius + 1;
const int div = radius * 2 + 1;
@ -23,6 +22,98 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix
}
uint64_t *rgb = malloc(imageWidth * imageHeight * sizeof(uint64_t));
if (rgb == NULL) {
return;
}
int x, y, i;
int yw = 0;
const int we = w - r1;
for (y = 0; y < h; y++) {
uint64_t cur = get_colors (&pix[yw]);
uint64_t rgballsum = -radius * cur;
uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1);
for (i = 1; i <= radius; i++) {
uint64_t cur = get_colors (&pix[yw + i * 4]);
rgbsum += cur * (r1 - i);
rgballsum += cur;
}
x = 0;
#define update(start, middle, end) \
rgb[y * w + x] = (rgbsum >> 6) & 0x00FF00FF00FF00FF; \
rgballsum += get_colors (&pix[yw + (start) * 4]) - 2 * get_colors (&pix[yw + (middle) * 4]) + get_colors (&pix[yw + (end) * 4]); \
rgbsum += rgballsum; \
x++; \
while (x < r1) {
update (0, x, x + r1);
}
while (x < we) {
update (x - r1, x, x + r1);
}
while (x < w) {
update (x - r1, x, w - 1);
}
#undef update
yw += stride;
}
const int he = h - r1;
for (x = 0; x < w; x++) {
uint64_t rgballsum = -radius * rgb[x];
uint64_t rgbsum = rgb[x] * ((r1 * (r1 + 1)) >> 1);
for (i = 1; i <= radius; i++) {
rgbsum += rgb[i * w + x] * (r1 - i);
rgballsum += rgb[i * w + x];
}
y = 0;
int yi = x * 4;
#define update(start, middle, end) \
int64_t res = rgbsum >> 6; \
pix[yi] = res; \
pix[yi + 1] = res >> 16; \
pix[yi + 2] = res >> 32; \
rgballsum += rgb[x + (start) * w] - 2 * rgb[x + (middle) * w] + rgb[x + (end) * w]; \
rgbsum += rgballsum; \
y++; \
yi += stride;
while (y < r1) {
update (0, y, y + r1);
}
while (y < he) {
update (y - r1, y, y + r1);
}
while (y < h) {
update (y - r1, y, h - 1);
}
#undef update
}
}
static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pixels, int radius) {
uint8_t *pix = (uint8_t *)pixels;
const int w = imageWidth;
const int h = imageHeight;
const int stride = imageStride;
const int r1 = radius + 1;
const int div = radius * 2 + 1;
if (radius > 15 || div >= w || div >= h || w * h > 90 * 90 || imageStride > imageWidth * 4) {
return;
}
uint64_t *rgb = malloc(imageWidth * imageHeight * sizeof(uint64_t));
if (rgb == NULL) {
return;
}
int x, y, i;
@ -111,7 +202,7 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
longjmp(myerr->setjmp_buffer, 1);
}
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap) {
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius) {
if (!bitmap) {
return;
}
@ -130,7 +221,11 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl
if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
return;
}
fastBlur(info.width, info.height, info.stride, pixels);
if (radius <= 3) {
fastBlur(info.width, info.height, info.stride, pixels, radius);
} else {
fastBlurMore(info.width, info.height, info.stride, pixels, radius);
}
AndroidBitmap_unlockPixels(env, bitmap);
}

File diff suppressed because it is too large Load Diff

View File

@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.4.1"
#define SQLITE_VERSION_NUMBER 3008004
#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"
#define SQLITE_VERSION "3.8.6"
#define SQLITE_VERSION_NUMBER 3008006
#define SQLITE_SOURCE_ID "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -269,7 +269,7 @@ typedef sqlite_uint64 sqlite3_uint64;
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated.
**
@ -277,7 +277,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
** and unfinished sqlite3_backups, then the database connection becomes
** and/or unfinished sqlite3_backups, then the database connection becomes
** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is
** finished. The sqlite3_close_v2() interface is intended for use with
@ -290,7 +290,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** with the [sqlite3] object prior to attempting to close the object. ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed.
**
@ -386,16 +386,14 @@ SQLITE_API int sqlite3_exec(
/*
** CAPI3REF: Result Codes
** KEYWORDS: SQLITE_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
** KEYWORDS: {result code definitions}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE_IOERR_READ | extended result codes],
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
** See also: [extended result code definitions]
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
@ -433,26 +431,19 @@ SQLITE_API int sqlite3_exec(
/*
** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
** KEYWORDS: {extended result code definitions}
**
** In its default configuration, SQLite API routines return one of 26 integer
** [SQLITE_OK | result codes]. However, experience has shown that many of
** In its default configuration, SQLite API routines return one of 30 integer
** [result codes]. However, experience has shown that many of
** these result codes are too coarse-grained. They do not provide as
** much information about problems as programmers might like. In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information
** about errors. The extended result codes are enabled or disabled
** about errors. These [extended result codes] are enabled or disabled
** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will increase
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
** The SQLITE_OK result code will never be extended. It will always
** be exactly zero.
** [sqlite3_extended_result_codes()] API. Or, the extended code for
** the most recent error can be obtained using
** [sqlite3_extended_errcode()].
*/
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
@ -560,7 +551,10 @@ SQLITE_API int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open.
** flag indicate that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@ -575,6 +569,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
/*
** CAPI3REF: File Locking Levels
@ -681,7 +676,7 @@ struct sqlite3_file {
** locking strategy (for example to use dot-file locks), to inquire
** about the status of a lock, or to break stale locks. The SQLite
** core reserves all opcodes less than 100 for its own use.
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
** A [file control opcodes | list of opcodes] less than 100 is available.
** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts. VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@ -754,6 +749,7 @@ struct sqlite3_io_methods {
/*
** CAPI3REF: Standard File Control Opcodes
** KEYWORDS: {file control opcodes} {file control opcode}
**
** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
@ -943,6 +939,12 @@ struct sqlite3_io_methods {
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@ -966,6 +968,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
/*
** CAPI3REF: Mutex Handle
@ -2026,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
**
** ^This routine sets a callback function that might be invoked whenever
** an attempt is made to open a database table that another thread
** or process has locked.
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock. ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler(). ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked for this locking event. ^If the
** been invoked for the same locking event. ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
** access the database and [SQLITE_BUSY] is returned
** to the application.
** ^If the callback returns non-zero, then another attempt
** is made to open the database for reading and the cycle repeats.
** is made to access the database and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
** when there is lock contention. ^If SQLite determines that invoking the busy
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
** to the application instead of invoking the
** busy handler.
** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying
@ -2060,28 +2069,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
**
** ^The default busy callback is NULL.
**
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
** when SQLite is in the middle of a large transaction where all the
** changes will not fit into the in-memory cache. SQLite will
** already hold a RESERVED lock on the database file, but it needs
** to promote this lock to EXCLUSIVE so that it can spill cache
** pages into the database file without harm to concurrent
** readers. ^If it is unable to promote the lock, then the in-memory
** cache will be left in an inconsistent state and so the error
** code is promoted from the relatively benign [SQLITE_BUSY] to
** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
** forces an automatic rollback of the changes. See the
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
** this is important.
**
** ^(There can only be a single busy handler defined for each
** [database connection]. Setting a new busy handler clears any
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
** or evaluating [PRAGMA busy_timeout=N] will change the
** busy handler and thus clear any previously set busy handler.
**
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler. Any such actions
** database connection that invoked the busy handler. In other words,
** the busy handler is not reentrant. Any such actions
** result in undefined behavior.
**
** A busy handler must not close the database connection
@ -2097,7 +2093,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated. ^After at least "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
** [SQLITE_BUSY].
**
** ^Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
@ -2106,6 +2102,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
** [database connection] any any given moment. If another busy handler
** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^
**
** See also: [PRAGMA busy_timeout]
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
@ -2507,8 +2505,8 @@ SQLITE_API int sqlite3_set_authorizer(
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
** from the [sqlite3_vtab_on_conflict()] interface.
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
** returned from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
@ -2779,6 +2777,30 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
** "1") or "false" (or "off" or "no" or "0") to indicate that the
** [powersafe overwrite] property does or does not apply to the
** storage media on which the database file resides. ^The psow query
** parameter only works for the built-in unix and Windows VFSes.
**
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
** which if set disables file locking in rollback journal modes. This
** is useful for accessing a database on a filesystem that does not
** support locking. Caution: Database corruption might result if two
** or more processes write to the same database and any one of those
** processes uses nolock=1.
**
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
** parameter that indicates that the database file is stored on
** read-only media. ^When immutable is set, SQLite assumes that the
** database file cannot be changed, even by a process with higher
** privilege, and so the database is opened read-only and all locking
** and change detection is disabled. Caution: Setting the immutable
** property on a database file that does in fact change can result
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
** See also: [SQLITE_IOCAP_IMMUTABLE].
**
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
@ -2808,8 +2830,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
@ -4670,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.
**
** Applications are strongly discouraged from using this global variable.
** It is required to set a temporary folder on Windows Runtime (WinRT).
** But for all other platforms, it is highly recommended that applications
** neither read nor write this variable. This global variable is a relic
** that exists for backwards compatibility of legacy applications and should
** be avoided in new projects.
**
** It is not safe to read or modify this variable in more than one
** thread at a time. It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
@ -4688,6 +4718,11 @@ SQLITE_API int sqlite3_sleep(int);
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
** Except when requested by the [temp_store_directory pragma], SQLite
** does not free the memory that sqlite3_temp_directory points to. If
** the application wants that memory to be freed, it must do
** so itself, taking care to only do so after all [database connection]
** objects have been destroyed.
**
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
@ -5822,10 +5857,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** <li> SQLITE_MUTEX_STATIC_PMEM
** <li> SQLITE_MUTEX_STATIC_APP1
** <li> SQLITE_MUTEX_STATIC_APP2
** </ul>)^
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@ -6029,6 +6066,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
/*
** CAPI3REF: Retrieve the mutex for a database connection
@ -6123,7 +6163,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_LAST 21
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_LAST 23
/*
** CAPI3REF: SQLite Runtime Status
@ -7107,6 +7149,9 @@ SQLITE_API void *sqlite3_wal_hook(
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages. The use of this interface
@ -7123,6 +7168,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
** empty string, then a checkpoint is run on all databases of
** connection D. ^If the database connection D is not in
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
** or RESET checkpoint.
**
** ^The [wal_checkpoint pragma] can be used to invoke this interface
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
@ -7145,10 +7194,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** Checkpoint as many frames as possible without waiting for any database
** readers or writers to finish. Sync the db file if all frames in the log
** are checkpointed. This mode is the same as calling
** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
** is never invoked.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
** This mode blocks (calls the busy-handler callback) until there is no
** This mode blocks (it invokes the
** [sqlite3_busy_handler|busy-handler callback]) until there is no
** database writer and all readers are reading from the most recent database
** snapshot. It then checkpoints all frames in the log file and syncs the
** database file. This call blocks database writers while it is running,
@ -7156,7 +7207,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
** checkpointing the log file it blocks (calls the busy-handler callback)
** checkpointing the log file it blocks (calls the
** [sqlite3_busy_handler|busy-handler callback])
** until all readers are reading from the database file only. This ensures
** that the next client to write to the database file restarts the log file
** from the beginning. This call blocks database writers while it is running,
@ -7294,6 +7346,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
@ -7346,6 +7399,16 @@ extern "C" {
#endif
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
/* The double-precision datatype used by RTree depends on the
** SQLITE_RTREE_INT_ONLY compile-time option.
*/
#ifdef SQLITE_RTREE_INT_ONLY
typedef sqlite3_int64 sqlite3_rtree_dbl;
#else
typedef double sqlite3_rtree_dbl;
#endif
/*
** Register a geometry callback named zGeom that can be used as part of an
@ -7356,11 +7419,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
SQLITE_API int sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
#ifdef SQLITE_RTREE_INT_ONLY
int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
#else
int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
#endif
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
void *pContext
);
@ -7372,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */
double *aParam; /* Parameters passed to SQL geom function */
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
void *pUser; /* Callback implementation user data */
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
/*
** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
SQLITE_API int sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (*xDestructor)(void*)
);
/*
** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
** Note that the first 5 fields of this structure are identical to
** sqlite3_rtree_geometry. This structure is a subclass of
** sqlite3_rtree_geometry.
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (*xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
};
/*
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
*/
#define NOT_WITHIN 0 /* Object completely outside of query region */
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
#define FULLY_WITHIN 2 /* Object fully contained within query region */
#ifdef __cplusplus
} /* end of the 'extern "C"' block */

View File

@ -9,7 +9,9 @@
package org.telegram.android;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
@ -21,17 +23,23 @@ import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.ApplicationLoader;
import org.telegram.ui.Views.NumberPicker;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Locale;
public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<String, Typeface>();
private static int prevOrientation = -10;
private static boolean waitingForSms = false;
@ -210,7 +218,7 @@ public class AndroidUtilities {
}
public static File getCacheDir() {
if (Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
if (Environment.getExternalStorageState() == null || Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
try {
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
if (file != null) {
@ -239,6 +247,10 @@ public class AndroidUtilities {
return (int)Math.ceil(density * value);
}
public static float dpf2(float value) {
return density * value;
}
public static void checkDisplaySize() {
try {
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
@ -262,6 +274,22 @@ public class AndroidUtilities {
return 0x0000000100000000L | ((long)id & 0x00000000FFFFFFFFL);
}
public static int getMyLayerVersion(int layer) {
return layer & 0xffff;
}
public static int getPeerLayerVersion(int layer) {
return (layer >> 16) & 0xffff;
}
public static int setMyLayerVersion(int layer, int version) {
return layer & 0xffff0000 | version;
}
public static int setPeerLayerVersion(int layer, int version) {
return layer & 0x0000ffff | (version << 16);
}
public static void RunOnUIThread(Runnable runnable) {
RunOnUIThread(runnable, 0);
}
@ -274,6 +302,10 @@ public class AndroidUtilities {
}
}
public static void CancelRunOnUIThread(Runnable runnable) {
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
}
public static boolean isTablet() {
if (isTablet == null) {
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
@ -367,4 +399,106 @@ public class AndroidUtilities {
}
return photoSize;
}
public static String formatTTLString(int ttl) {
if (ttl < 60) {
return LocaleController.formatPluralString("Seconds", ttl);
} else if (ttl < 60 * 60) {
return LocaleController.formatPluralString("Minutes", ttl / 60);
} else if (ttl < 60 * 60 * 24) {
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
} else if (ttl < 60 * 60 * 24 * 7) {
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
} else {
int days = ttl / 60 / 60 / 24;
if (ttl % 7 == 0) {
return LocaleController.formatPluralString("Weeks", days / 7);
} else {
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
}
}
}
public static AlertDialog.Builder buildTTLAlert(final Context context, final TLRPC.EncryptedChat encryptedChat) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
final NumberPicker numberPicker = new NumberPicker(context);
numberPicker.setMinValue(0);
numberPicker.setMaxValue(20);
if (encryptedChat.ttl > 0 && encryptedChat.ttl < 16) {
numberPicker.setValue(encryptedChat.ttl);
} else if (encryptedChat.ttl == 30) {
numberPicker.setValue(16);
} else if (encryptedChat.ttl == 60) {
numberPicker.setValue(17);
} else if (encryptedChat.ttl == 60 * 60) {
numberPicker.setValue(18);
} else if (encryptedChat.ttl == 60 * 60 * 24) {
numberPicker.setValue(19);
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
numberPicker.setValue(20);
} else if (encryptedChat.ttl == 0) {
numberPicker.setValue(5);
}
numberPicker.setFormatter(new NumberPicker.Formatter() {
@Override
public String format(int value) {
if (value == 0) {
return LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever);
} else if (value >= 1 && value < 16) {
return AndroidUtilities.formatTTLString(value);
} else if (value == 16) {
return AndroidUtilities.formatTTLString(30);
} else if (value == 17) {
return AndroidUtilities.formatTTLString(60);
} else if (value == 18) {
return AndroidUtilities.formatTTLString(60 * 60);
} else if (value == 19) {
return AndroidUtilities.formatTTLString(60 * 60 * 24);
} else if (value == 20) {
return AndroidUtilities.formatTTLString(60 * 60 * 24 * 7);
}
return "";
}
});
builder.setView(numberPicker);
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int oldValue = encryptedChat.ttl;
which = numberPicker.getValue();
if (which >= 0 && which < 16) {
encryptedChat.ttl = which;
} else if (which == 16) {
encryptedChat.ttl = 30;
} else if (which == 17) {
encryptedChat.ttl = 60;
} else if (which == 18) {
encryptedChat.ttl = 60 * 60;
} else if (which == 19) {
encryptedChat.ttl = 60 * 60 * 24;
} else if (which == 20) {
encryptedChat.ttl = 60 * 60 * 24 * 7;
}
if (oldValue != encryptedChat.ttl) {
SendMessagesHelper.getInstance().sendTTLMessage(encryptedChat, null);
MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat);
}
}
});
return builder;
}
public static void clearCursorDrawable(EditText editText) {
if (editText == null || Build.VERSION.SDK_INT < 12) {
return;
}
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.setInt(editText, 0);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}

View File

@ -236,7 +236,7 @@ public class ContactsController {
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
HashMap<String, Contact> shortContacts = new HashMap<String, Contact>();
String ids = "";
StringBuilder ids = new StringBuilder();
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
if (pCur != null) {
if (pCur.getCount() > 0) {
@ -262,9 +262,9 @@ public class ContactsController {
Integer id = pCur.getInt(0);
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += id;
ids.append(id);
int type = pCur.getInt(2);
Contact contact = contactsMap.get(id);
@ -299,7 +299,7 @@ public class ContactsController {
pCur.close();
}
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids.toString() + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
if (pCur != null && pCur.getCount() > 0) {
while (pCur.moveToNext()) {
int id = pCur.getInt(0);
@ -844,14 +844,14 @@ public class ContactsController {
return 0;
}
});
String ids = "";
StringBuilder ids = new StringBuilder();
for (TLRPC.TL_contact aContactsArr : contactsArr) {
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += aContactsArr.user_id;
ids.append(aContactsArr.user_id);
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.contactsHash = Utilities.MD5(ids.toString());
UserConfig.saveConfig(false);
}
@ -1084,7 +1084,7 @@ public class ContactsController {
});
}
String ids = "";
StringBuilder ids = new StringBuilder();
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
@ -1114,11 +1114,11 @@ public class ContactsController {
}
arr.add(value);
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += value.user_id;
ids.append(value.user_id);
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.contactsHash = Utilities.MD5(ids.toString());
UserConfig.saveConfig(false);
Collections.sort(sortedSectionsArray, new Comparator<String>() {
@ -1189,8 +1189,8 @@ public class ContactsController {
}
FileLog.e("tmessages", "process update - contacts add = " + newC.size() + " delete = " + contactsTD.size());
String toAdd = "";
String toDelete = "";
StringBuilder toAdd = new StringBuilder();
StringBuilder toDelete = new StringBuilder();
boolean reloadContacts = false;
for (TLRPC.TL_contact newContact : newC) {
@ -1216,9 +1216,9 @@ public class ContactsController {
}
}
if (toAdd.length() != 0) {
toAdd += ",";
toAdd.append(",");
}
toAdd += user.phone;
toAdd.append(user.phone);
}
for (final Integer uid : contactsTD) {
@ -1252,14 +1252,14 @@ public class ContactsController {
}
}
if (toDelete.length() != 0) {
toDelete += ",";
toDelete.append(",");
}
toDelete += user.phone;
toDelete.append(user.phone);
}
}
if (toAdd.length() != 0 || toDelete.length() != 0) {
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd, toDelete);
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd.toString(), toDelete.toString());
}
if (reloadContacts) {

View File

@ -28,7 +28,6 @@ import android.provider.MediaStore;
import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
@ -293,7 +292,7 @@ public class ImageLoader {
}
}
if (image != null && blur && bitmapH < 100 && bitmapW < 100) {
Utilities.blurBitmap(image);
Utilities.blurBitmap(image, 3);
}
}
if (runtimeHack != null) {
@ -832,6 +831,10 @@ public class ImageLoader {
});
}
public void putImageToCache(BitmapDrawable bitmap, String key) {
memCache.put(key, bitmap);
}
public void loadImage(final TLRPC.FileLocation fileLocation, final String httpUrl, final ImageReceiver imageView, final int size, final boolean cacheOnly) {
if ((fileLocation == null && httpUrl == null) || imageView == null || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation))) {
return;

View File

@ -9,8 +9,13 @@
package org.telegram.android;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
@ -35,6 +40,13 @@ public class ImageReceiver {
private boolean isVisible = true;
private boolean isAspectFit = false;
private boolean lastCacheOnly = false;
private boolean forcePreview = false;
private int roundRadius = 0;
private BitmapShader bitmapShader = null;
private Paint roundPaint = null;
private RectF roundRect = null;
private RectF bitmapRect = null;
private Matrix shaderMatrix = null;
public ImageReceiver() {
@ -65,6 +77,7 @@ public class ImageReceiver {
last_httpUrl = null;
last_filter = null;
lastCacheOnly = false;
bitmapShader = null;
last_placeholder = placeholder;
last_size = 0;
currentImage = null;
@ -104,9 +117,13 @@ public class ImageReceiver {
last_placeholder = placeholder;
last_size = size;
lastCacheOnly = cacheOnly;
bitmapShader = null;
if (img == null) {
isPlaceholder = true;
ImageLoader.getInstance().loadImage(fileLocation, httpUrl, this, size, cacheOnly);
if (parentView != null) {
parentView.invalidate();
}
} else {
setImageBitmap(img, currentPath);
}
@ -119,6 +136,11 @@ public class ImageReceiver {
isPlaceholder = false;
ImageLoader.getInstance().incrementUseCount(currentPath);
currentImage = bitmap;
if (roundRadius != 0) {
bitmapShader = new BitmapShader(bitmap.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
roundPaint.setShader(bitmapShader);
bitmapRect.set(0, 0, bitmap.getIntrinsicWidth(), bitmap.getIntrinsicHeight());
}
if (parentView != null) {
parentView.invalidate();
}
@ -138,6 +160,7 @@ public class ImageReceiver {
last_httpUrl = null;
last_filter = null;
currentImage = null;
bitmapShader = null;
last_size = 0;
lastCacheOnly = false;
if (parentView != null) {
@ -155,6 +178,7 @@ public class ImageReceiver {
last_path = null;
last_httpUrl = null;
last_filter = null;
bitmapShader = null;
last_size = 0;
lastCacheOnly = false;
if (parentView != null) {
@ -192,24 +216,32 @@ public class ImageReceiver {
}
}
public boolean draw(Canvas canvas, int x, int y, int w, int h) {
public boolean draw(Canvas canvas) {
try {
Drawable bitmapDrawable = currentImage;
if (bitmapDrawable == null && last_placeholder != null && last_placeholder instanceof BitmapDrawable) {
if (forcePreview || bitmapDrawable == null && last_placeholder != null && last_placeholder instanceof BitmapDrawable) {
bitmapDrawable = last_placeholder;
}
if (bitmapDrawable != null) {
if (bitmapShader != null) {
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
roundRect.set(imageX, imageY, imageX + imageW, imageY + imageH);
shaderMatrix.reset();
shaderMatrix.setScale(1.5f, 1.5f);
bitmapShader.setLocalMatrix(shaderMatrix);
canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint);
} else {
int bitmapW = bitmapDrawable.getIntrinsicWidth();
int bitmapH = bitmapDrawable.getIntrinsicHeight();
float scaleW = bitmapW / (float)w;
float scaleH = bitmapH / (float)h;
float scaleW = bitmapW / (float) imageW;
float scaleH = bitmapH / (float) imageH;
if (isAspectFit) {
float scale = Math.max(scaleW, scaleH);
canvas.save();
bitmapW /= scale;
bitmapH /= scale;
drawRegion.set(x + (w - bitmapW) / 2, y + (h - bitmapH) / 2, x + (w + bitmapW) / 2, y + (h + bitmapH) / 2);
drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2);
bitmapDrawable.setBounds(drawRegion);
try {
bitmapDrawable.draw(canvas);
@ -225,14 +257,14 @@ public class ImageReceiver {
} else {
if (Math.abs(scaleW - scaleH) > 0.00001f) {
canvas.save();
canvas.clipRect(x, y, x + w, y + h);
canvas.clipRect(imageX, imageY, imageX + imageW, imageY + imageH);
if (bitmapW / scaleH > w) {
if (bitmapW / scaleH > imageW) {
bitmapW /= scaleH;
drawRegion.set(x - (bitmapW - w) / 2, y, x + (bitmapW + w) / 2, y + h);
drawRegion.set(imageX - (bitmapW - imageW) / 2, imageY, imageX + (bitmapW + imageW) / 2, imageY + imageH);
} else {
bitmapH /= scaleW;
drawRegion.set(x, y - (bitmapH - h) / 2, x + w, y + (bitmapH + h) / 2);
drawRegion.set(imageX, imageY - (bitmapH - imageH) / 2, imageX + imageW, imageY + (bitmapH + imageH) / 2);
}
bitmapDrawable.setBounds(drawRegion);
if (isVisible) {
@ -250,7 +282,7 @@ public class ImageReceiver {
canvas.restore();
} else {
drawRegion.set(x, y, x + w, y + h);
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
bitmapDrawable.setBounds(drawRegion);
if (isVisible) {
try {
@ -266,9 +298,10 @@ public class ImageReceiver {
}
}
}
}
return true;
} else if (last_placeholder != null) {
drawRegion.set(x, y, x + w, y + h);
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
last_placeholder.setBounds(drawRegion);
if (isVisible) {
try {
@ -371,4 +404,23 @@ public class ImageReceiver {
public String getKey() {
return currentPath;
}
public void setForcePreview(boolean value) {
forcePreview = value;
}
public void setRoundRadius(int value) {
roundRadius = value;
if (roundRadius != 0) {
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
roundRect = new RectF();
shaderMatrix = new Matrix();
bitmapRect = new RectF();
} else {
roundPaint = null;
roundRect = null;
shaderMatrix = null;
bitmapRect = null;
}
}
}

View File

@ -18,6 +18,8 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
@ -36,7 +38,9 @@ import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import org.telegram.android.video.InputSurface;
import org.telegram.android.video.MP4Builder;
@ -58,6 +62,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
@ -340,13 +345,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
}
}
private String[] mediaProjections = new String[] {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.TITLE
};
private String[] mediaProjections = null;
private static volatile MediaController Instance = null;
public static MediaController getInstance() {
@ -400,6 +399,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileLoadProgressChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog);
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
@Override
@ -413,6 +414,26 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
if (UserConfig.isClientActivated()) {
checkAutodownloadSettings();
}
if (Build.VERSION.SDK_INT >= 16) {
mediaProjections = new String[] {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.TITLE,
MediaStore.Images.ImageColumns.WIDTH,
MediaStore.Images.ImageColumns.HEIGHT
};
} else {
mediaProjections = new String[] {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.TITLE
};
}
}
private void startProgressTimer() {
@ -684,7 +705,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
public void startMediaObserver() {
if (android.os.Build.VERSION.SDK_INT > 0) { //disable while it's not perferct
if (android.os.Build.VERSION.SDK_INT < 14) {
return;
}
ApplicationLoader.applicationHandler.removeCallbacks(stopMediaObserverRunnable);
@ -706,7 +727,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
public void stopMediaObserver() {
if (android.os.Build.VERSION.SDK_INT > 0) { //disable while it's not perferct
if (android.os.Build.VERSION.SDK_INT < 14) {
return;
}
if (stopMediaObserverRunnable == null) {
@ -718,6 +739,30 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
public void processMediaObserver(Uri uri) {
try {
int width = 0;
int height = 0;
try {
WindowManager windowManager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Point size = new Point();
windowManager.getDefaultDisplay().getRealSize(size);
width = size.x;
height = size.y;
} else {
try {
Method mGetRawW = Display.class.getMethod("getRawWidth");
Method mGetRawH = Display.class.getMethod("getRawHeight");
width = (Integer) mGetRawW.invoke(windowManager.getDefaultDisplay());
height = (Integer) mGetRawH.invoke(windowManager.getDefaultDisplay());
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, mediaProjections, null, null, "date_added DESC LIMIT 1");
final ArrayList<Long> screenshotDates = new ArrayList<Long>();
if (cursor != null) {
@ -726,75 +771,33 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
String data = cursor.getString(0);
String display_name = cursor.getString(1);
String album_name = cursor.getString(2);
String title = cursor.getString(4);
long date = cursor.getLong(3);
String title = cursor.getString(4);
int photoW = 0;
int photoH = 0;
if (Build.VERSION.SDK_INT >= 16) {
photoW = cursor.getInt(5);
photoH = cursor.getInt(6);
}
if (data != null && data.toLowerCase().contains("screenshot") ||
display_name != null && display_name.toLowerCase().contains("screenshot") ||
album_name != null && album_name.toLowerCase().contains("screenshot") ||
title != null && title.toLowerCase().contains("screenshot")) {
/*BitmapRegionDecoder bitmapRegionDecoder = null;
boolean added = false;
try {
int waitCount = 0;
while (waitCount < 5 && bitmapRegionDecoder == null) {
try {
bitmapRegionDecoder = BitmapRegionDecoder.newInstance(data, true);
if (bitmapRegionDecoder != null) {
break;
if (photoW == 0 || photoH == 0) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(data, bmOptions);
photoW = bmOptions.outWidth;
photoH = bmOptions.outHeight;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
Thread.sleep(1000);
}
if (bitmapRegionDecoder != null) {
Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(0, 0, AndroidUtilities.dp(44), AndroidUtilities.dp(44)), null);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
for (int y = 0; y < h; y++) {
int rowCount = 0;
for (int x = 0; x < w; x++) {
int px = bitmap.getPixel(x, y);
if (px == 0xffffffff) {
rowCount++;
} else {
rowCount = 0;
}
if (rowCount > 8) {
break;
}
}
if (rowCount > 8) {
screenshotDates.add(date);
added = true;
break;
}
}
bitmapRegionDecoder.recycle();
try {
if (bitmap != null) {
bitmap.recycle();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
try {
if (bitmapRegionDecoder != null) {
bitmapRegionDecoder.recycle();
}
} catch (Exception e2) {
FileLog.e("tmessages", e2);
}
if (!added) {
if (photoW <= 0 || photoH <= 0 || (photoW == width && photoH == height || photoH == width && photoW == height)) {
screenshotDates.add(date);
}
}*/
} catch (Exception e) {
screenshotDates.add(date);
}
FileLog.e("tmessages", "screenshot!");
}
}
cursor.close();
}
@ -831,7 +834,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
}
if (send) {
SendMessagesHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages);
SendMessagesHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages, null);
}
}
@ -898,6 +901,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
deleteLaterArray.clear();
}
@SuppressWarnings("unchecked")
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.FileDidFailedLoad) {
@ -961,6 +965,18 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
listenerInProgress = false;
processLaterArrays();
} else if (id == NotificationCenter.messagesDeleted) {
if (playingMessageObject != null) {
ArrayList<Integer> markAsDeletedMessages = (ArrayList<Integer>)args[0];
if (markAsDeletedMessages.contains(playingMessageObject.messageOwner.id)) {
clenupPlayer(false);
}
}
} else if (id == NotificationCenter.removeAllMessagesFromDialog) {
long did = (Long)args[0];
if (playingMessageObject != null && playingMessageObject.getDialogId() == did) {
clenupPlayer(false);
}
}
}
@ -1180,6 +1196,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
return true;
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject);
clenupPlayer(true);
final File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner);
@ -1205,7 +1222,6 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
audioTrackPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, playerBufferSize, AudioTrack.MODE_STREAM);
audioTrackPlayer.setStereoVolume(1.0f, 1.0f);
//audioTrackPlayer.setNotificationMarkerPosition((int)currentTotalPcmDuration);
audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() {
@Override
public void onMarkerReached(AudioTrack audioTrack) {
@ -2081,12 +2097,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
if (end < 0 || info.presentationTimeUs < end) {
info.offset = 0;
info.flags = extractor.getSampleFlags();
if (!isAudio) {
buffer.limit(info.offset + info.size);
buffer.position(info.offset);
buffer.putInt(info.size - 4);
}
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info, isAudio)) {
didWriteData(messageObject, file, false, false);
}
extractor.advance();
@ -2168,10 +2179,28 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
resultWidth = temp;
rotationValue = 90;
rotateRender = 270;
} else if (Build.VERSION.SDK_INT > 20) {
if (rotationValue == 90) {
int temp = resultHeight;
resultHeight = resultWidth;
resultWidth = temp;
rotationValue = 0;
rotateRender = 270;
} else if (rotationValue == 180) {
rotateRender = 180;
rotationValue = 0;
} else if (rotationValue == 270) {
int temp = resultHeight;
resultHeight = resultWidth;
resultWidth = temp;
rotationValue = 0;
rotateRender = 90;
}
}
File inputFile = new File(videoPath);
if (!inputFile.canRead()) {
didWriteData(messageObject, cacheFile, true, true);
return false;
}
@ -2374,10 +2403,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
}
if (info.size > 1) {
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
encodedData.limit(info.offset + info.size);
encodedData.position(info.offset);
encodedData.putInt(Integer.reverseBytes(info.size - 4));
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) {
didWriteData(messageObject, cacheFile, false, false);
}
} else if (videoTrackIndex == -5) {
@ -2552,6 +2578,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
}
} else {
didWriteData(messageObject, cacheFile, true, true);
return false;
}
didWriteData(messageObject, cacheFile, true, error);

View File

@ -12,15 +12,20 @@ import android.graphics.Bitmap;
import android.graphics.Paint;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.util.Linkify;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.Views.URLSpanNoUnderline;
import java.util.AbstractMap;
import java.util.ArrayList;
@ -90,7 +95,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouCreateGroup", R.string.ActionYouCreateGroup);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", "");
}
@ -101,26 +106,27 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouLeftUser", R.string.ActionYouLeftUser);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", "");
}
}
} else {
TLRPC.User who = null;
TLRPC.User whoUser = null;
if (users != null) {
who = users.get(message.action.user_id);
whoUser = users.get(message.action.user_id);
}
if (who == null) {
who = MessagesController.getInstance().getUser(message.action.user_id);
if (whoUser == null) {
whoUser = MessagesController.getInstance().getUser(message.action.user_id);
}
if (who != null && fromUser != null) {
if (whoUser != null && fromUser != null) {
if (isFromMe()) {
messageText = LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser), "un2", whoUser);
} else if (message.action.user_id == UserConfig.getClientUserId()) {
messageText = LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionKickUser", R.string.ActionKickUser), "un2", whoUser);
messageText = replaceWithLink(messageText, "un1", fromUser);
}
} else {
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", "").replace("un1", "");
@ -136,11 +142,12 @@ public class MessageObject {
}
if (whoUser != null && fromUser != null) {
if (isFromMe()) {
messageText = LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser), "un2", whoUser);
} else if (message.action.user_id == UserConfig.getClientUserId()) {
messageText = LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionAddUser", R.string.ActionAddUser), "un2", whoUser);
messageText = replaceWithLink(messageText, "un1", fromUser);
}
} else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", "").replace("un1", "");
@ -150,7 +157,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouChangedPhoto", R.string.ActionYouChangedPhoto);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", "");
}
@ -160,7 +167,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouChangedTitle", R.string.ActionYouChangedTitle).replace("un2", message.action.title);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
messageText = replaceWithLink(LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un2", message.action.title), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", "").replace("un2", message.action.title);
}
@ -170,36 +177,20 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouRemovedPhoto", R.string.ActionYouRemovedPhoto);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
messageText = replaceWithLink(LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto), "un1", fromUser);
} else {
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", "");
}
}
} else if (message.action instanceof TLRPC.TL_messageActionTTLChange) {
if (message.action.ttl != 0) {
String timeString;
if (message.action.ttl == 2) {
timeString = LocaleController.getString("MessageLifetime2s", R.string.MessageLifetime2s);
} else if (message.action.ttl == 5) {
timeString = LocaleController.getString("MessageLifetime5s", R.string.MessageLifetime5s);
} else if (message.action.ttl == 60) {
timeString = LocaleController.getString("MessageLifetime1m", R.string.MessageLifetime1m);
} else if (message.action.ttl == 60 * 60) {
timeString = LocaleController.getString("MessageLifetime1h", R.string.MessageLifetime1h);
} else if (message.action.ttl == 60 * 60 * 24) {
timeString = LocaleController.getString("MessageLifetime1d", R.string.MessageLifetime1d);
} else if (message.action.ttl == 60 * 60 * 24 * 7) {
timeString = LocaleController.getString("MessageLifetime1w", R.string.MessageLifetime1w);
} else {
timeString = String.format("%d", message.action.ttl);
}
if (isFromMe()) {
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, timeString);
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, AndroidUtilities.formatTTLString(message.action.ttl));
} else {
if (fromUser != null) {
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, timeString);
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, AndroidUtilities.formatTTLString(message.action.ttl));
} else {
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", timeString);
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", AndroidUtilities.formatTTLString(message.action.ttl));
}
}
} else {
@ -241,17 +232,40 @@ public class MessageObject {
} else {
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, "");
}
} else if (message.action instanceof TLRPC.TL_messageEcryptedAction) {
} else if (message.action instanceof TLRPC.TL_messageEncryptedAction) {
if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
if (isFromMe()) {
messageText = LocaleController.formatString("ActionTakeScreenshootYou", R.string.ActionTakeScreenshootYou);
} else {
if (fromUser != null) {
messageText = LocaleController.formatString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot).replace("un1", fromUser.first_name);
messageText = replaceWithLink(LocaleController.getString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot), "un1", fromUser);
} else {
messageText = LocaleController.formatString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot).replace("un1", "");
}
}
} else if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL) message.action.encryptedAction;
if (action.ttl_seconds != 0) {
if (isFromMe()) {
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, AndroidUtilities.formatTTLString(action.ttl_seconds));
} else {
if (fromUser != null) {
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, AndroidUtilities.formatTTLString(action.ttl_seconds));
} else {
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", AndroidUtilities.formatTTLString(action.ttl_seconds));
}
}
} else {
if (isFromMe()) {
messageText = LocaleController.getString("MessageLifetimeYouRemoved", R.string.MessageLifetimeYouRemoved);
} else {
if (fromUser != null) {
messageText = LocaleController.formatString("MessageLifetimeRemoved", R.string.MessageLifetimeRemoved, fromUser.first_name);
} else {
messageText = LocaleController.formatString("MessageLifetimeRemoved", R.string.MessageLifetimeRemoved, "");
}
}
}
}
} else if (message.action instanceof TLRPC.TL_messageActionCreatedBroadcastList) {
messageText = LocaleController.formatString("YouCreatedBroadcastList", R.string.YouCreatedBroadcastList);
@ -278,7 +292,7 @@ public class MessageObject {
}
messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20));
if (message instanceof TLRPC.TL_message || (message instanceof TLRPC.TL_messageForwarded && (message.media == null || !(message.media instanceof TLRPC.TL_messageMediaEmpty)))) {
if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded) {
if (message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty) {
contentType = type = 0;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) {
@ -290,13 +304,8 @@ public class MessageObject {
contentType = 1;
type = 3;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaContact) {
if (isFromMe()) {
contentType = 3;
type = 12;
} else {
contentType = 4;
type = 13;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaUnsupported) {
contentType = type = 0;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaDocument) {
@ -313,14 +322,20 @@ public class MessageObject {
if (message.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
contentType = type = 0;
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto || message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
contentType = 8;
contentType = 4;
type = 11;
} else if (message.action instanceof TLRPC.TL_messageEncryptedAction) {
if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
contentType = 4;
type = 10;
} else {
contentType = 7;
contentType = -1;
type = -1;
}
} else {
contentType = 4;
type = 10;
}
} else if (message instanceof TLRPC.TL_messageForwarded) {
contentType = type = 0;
}
Calendar rightNow = new GregorianCalendar();
@ -334,13 +349,22 @@ public class MessageObject {
generateThumbs(false, preview);
}
public CharSequence replaceWithLink(CharSequence source, String param, TLRPC.User user) {
String name = ContactsController.formatName(user.first_name, user.last_name);
int start = TextUtils.indexOf(source, param);
URLSpanNoUnderline span = new URLSpanNoUnderline("" + user.id);
SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new String[]{name}));
builder.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return builder;
}
public void generateThumbs(boolean update, int preview) {
if (messageOwner instanceof TLRPC.TL_messageService) {
if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
if (!update) {
photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : messageOwner.action.photo.sizes) {
photoThumbs.add(new PhotoObject(size, preview));
photoThumbs.add(new PhotoObject(size, preview, isSecretMedia()));
}
} else if (photoThumbs != null && !photoThumbs.isEmpty()) {
for (PhotoObject photoObject : photoThumbs) {
@ -361,7 +385,7 @@ public class MessageObject {
if (!update) {
photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : messageOwner.media.photo.sizes) {
PhotoObject obj = new PhotoObject(size, preview);
PhotoObject obj = new PhotoObject(size, preview, isSecretMedia());
photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) {
imagePreview = obj.image;
@ -383,7 +407,7 @@ public class MessageObject {
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
if (!update) {
photoThumbs = new ArrayList<PhotoObject>();
PhotoObject obj = new PhotoObject(messageOwner.media.video.thumb, preview);
PhotoObject obj = new PhotoObject(messageOwner.media.video.thumb, preview, isSecretMedia());
photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) {
imagePreview = obj.image;
@ -396,7 +420,7 @@ public class MessageObject {
if (!(messageOwner.media.document.thumb instanceof TLRPC.TL_photoSizeEmpty)) {
if (!update) {
photoThumbs = new ArrayList<PhotoObject>();
PhotoObject obj = new PhotoObject(messageOwner.media.document.thumb, preview);
PhotoObject obj = new PhotoObject(messageOwner.media.document.thumb, preview, isSecretMedia());
photoThumbs.add(obj);
} else if (photoThumbs != null && !photoThumbs.isEmpty() && messageOwner.media.document.thumb != null) {
PhotoObject photoObject = photoThumbs.get(0);
@ -599,15 +623,46 @@ public class MessageObject {
}
public boolean isOut() {
return messageOwner.out;
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
}
public boolean isFromMe() {
return messageOwner.from_id == UserConfig.getClientUserId();
}
public boolean isUnread () {
return messageOwner.unread;
public boolean isUnread() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
}
public void setIsRead() {
messageOwner.flags &=~ TLRPC.MESSAGE_FLAG_UNREAD;
}
public boolean isSecretPhoto() {
return messageOwner instanceof TLRPC.TL_message_secret && messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60;
}
public boolean isSecretMedia() {
return messageOwner instanceof TLRPC.TL_message_secret &&
(messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60 ||
messageOwner.media instanceof TLRPC.TL_messageMediaAudio ||
messageOwner.media instanceof TLRPC.TL_messageMediaVideo);
}
public static void setIsUnread(TLRPC.Message message, boolean unread) {
if (unread) {
message.flags |= TLRPC.MESSAGE_FLAG_UNREAD;
} else {
message.flags &=~ TLRPC.MESSAGE_FLAG_UNREAD;
}
}
public static boolean isUnread(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
}
public static boolean isOut(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
}
public long getDialogId() {
@ -635,4 +690,21 @@ public class MessageObject {
public boolean isSent() {
return messageOwner.send_state == MESSAGE_SEND_STATE_SENT;
}
public String getSecretTimeString() {
if (!isSecretMedia()) {
return null;
}
int secondsLeft = messageOwner.ttl;
if (messageOwner.destroyTime != 0) {
secondsLeft = Math.max(0, messageOwner.destroyTime - ConnectionsManager.getInstance().getCurrentTime());
}
String str;
if (secondsLeft < 60) {
str = secondsLeft + "s";
} else {
str = secondsLeft / 60 + "m";
}
return str;
}
}

View File

@ -17,6 +17,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.text.Html;
import android.util.SparseArray;
import org.telegram.messenger.BuffersStorage;
import org.telegram.messenger.ByteBufferDesc;
@ -66,11 +67,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
private long updatesStartWaitTime = 0;
public ArrayList<TLRPC.Update> delayedEncryptedChatUpdates = new ArrayList<TLRPC.Update>();
private boolean startingSecretChat = false;
private ArrayList<Integer> loadingFullUsers = new ArrayList<Integer>();
private ArrayList<Integer> loadedFullUsers = new ArrayList<Integer>();
private boolean gettingNewDeleteTask = false;
private int currentDeletingTaskTime = 0;
private Long currentDeletingTask = null;
private ArrayList<Integer> currentDeletingTaskMids = null;
private Runnable currentDeleteTaskRunnable = null;
public int totalDialogsCount = 0;
public boolean loadingDialogs = false;
@ -317,12 +320,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
delayedEncryptedChatUpdates.clear();
blockedUsers.clear();
sendingTypings.clear();
loadingFullUsers.clear();
loadedFullUsers.clear();
updatesStartWaitTime = 0;
currentDeletingTaskTime = 0;
currentDeletingTaskMids = null;
gettingNewDeleteTask = false;
currentDeletingTask = null;
loadingDialogs = false;
dialogsEndReached = false;
gettingDifference = false;
@ -337,6 +341,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter
startingSecretChat = false;
statusRequest = 0;
statusSettingState = 0;
if (currentDeleteTaskRunnable != null) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
currentDeleteTaskRunnable = null;
}
addSupportUser();
}
@ -383,6 +393,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
users.put(user.id, user);
if (user.id == UserConfig.getClientUserId()) {
UserConfig.setCurrentUser(user);
UserConfig.saveConfig(true);
}
if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) {
return true;
@ -453,10 +464,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void cancelLoadFullUser(int uid) {
loadingFullUsers.remove((Integer) uid);
}
public void loadFullUser(final TLRPC.User user, final int classGuid) {
if (user == null) {
if (user == null || loadingFullUsers.contains(user.id) || loadedFullUsers.contains(user.id)) {
return;
}
loadingFullUsers.add(user.id);
TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser();
req.id = getInputUser(user);
long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@ -466,10 +482,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
loadingFullUsers.remove((Integer)user.id);
loadedFullUsers.add(user.id);
String names = user.first_name + user.last_name + user.username;
TLRPC.TL_userFull userFull = (TLRPC.TL_userFull)response;
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(userFull.user);
putUsers(users, false);
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
if (!names.equals(userFull.user.first_name + userFull.user.last_name + userFull.user.username)) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_NAME);
}
}
});
} else {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
loadingFullUsers.remove((Integer)user.id);
}
});
}
@ -504,18 +534,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void didAddedNewTask(final int minDate) {
public void didAddedNewTask(final int minDate, final SparseArray<ArrayList<Integer>> mids) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (currentDeletingTask == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
if (currentDeletingTaskMids == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
getNewDeleteTask(null);
}
}
});
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didCreatedNewDeleteTask, mids);
}
});
}
public void getNewDeleteTask(final Long oldTask) {
public void getNewDeleteTask(final ArrayList<Integer> oldTask) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -525,11 +561,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
});
}
private void checkDeletingTask() {
private boolean checkDeletingTask(boolean runnable) {
int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
if (currentDeletingTask != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) {
if (currentDeletingTaskMids != null && (runnable || currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime)) {
currentDeletingTaskTime = 0;
if (currentDeleteTaskRunnable != null && !runnable) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
}
currentDeleteTaskRunnable = null;
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
@ -538,30 +578,44 @@ public class MessagesController implements NotificationCenter.NotificationCenter
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
getNewDeleteTask(currentDeletingTask);
getNewDeleteTask(currentDeletingTaskMids);
currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null;
}
});
}
});
return true;
}
return false;
}
public void processLoadedDeleteTask(final Long taskId, final int taskTime, final ArrayList<Integer> messages) {
public void processLoadedDeleteTask(final int taskTime, final ArrayList<Integer> messages) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
gettingNewDeleteTask = false;
if (taskId != null) {
if (messages != null) {
currentDeletingTaskTime = taskTime;
currentDeletingTask = taskId;
currentDeletingTaskMids = messages;
checkDeletingTask();
if (currentDeleteTaskRunnable != null) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
currentDeleteTaskRunnable = null;
}
if (!checkDeletingTask(false)) {
currentDeleteTaskRunnable = new Runnable() {
@Override
public void run() {
checkDeletingTask(true);
}
};
int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
Utilities.stageQueue.postRunnable(currentDeleteTaskRunnable, (long)Math.abs(currentServerTime - currentDeletingTaskTime) * 1000);
}
} else {
currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null;
}
}
@ -926,7 +980,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, messages);
if (randoms != null && encryptedChat != null && !randoms.isEmpty()) {
SendMessagesHelper.getInstance().sendMessagesDeleteMessage(randoms, encryptedChat);
SendMessagesHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, randoms, null);
}
ArrayList<Integer> toSend = new ArrayList<Integer>();
@ -1017,7 +1071,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
});
} else {
if (onlyHistory) {
SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id));
SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id), null);
} else {
declineSecretChat(high_id);
}
@ -1066,7 +1120,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public void updateTimerProc() {
long currentTime = System.currentTimeMillis();
checkDeletingTask();
checkDeletingTask(false);
if (UserConfig.isClientActivated()) {
if (ConnectionsManager.getInstance().getPauseTime() == 0 && ApplicationLoader.isScreenOn && !ApplicationLoader.mainInterfacePaused) {
@ -1275,10 +1329,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward) {
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward, final Semaphore semaphore) {
int lower_part = (int)dialog_id;
if (fromCache || lower_part == 0) {
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward);
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward, semaphore);
} else {
TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory();
if (lower_part < 0) {
@ -1303,7 +1357,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false);
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false, semaphore);
}
}
});
@ -1311,7 +1365,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward) {
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward, final Semaphore semaphore) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -1320,10 +1374,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
MessagesStorage.getInstance().putMessages(messagesRes, dialog_id);
}
if (lower_id != 0 && isCache && messagesRes.messages.size() == 0 && !isForward) {
if (semaphore != null) {
semaphore.release();
}
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false);
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false, null);
}
});
return;
@ -1337,6 +1394,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.dialog_id = dialog_id;
objects.add(new MessageObject(message, usersLocal, 2));
}
if (semaphore != null) {
putUsers(messagesRes.users, isCache);
putChats(messagesRes.chats, isCache);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDidLoaded, dialog_id, count, objects, isCache, first_unread, last_unread, unread_count, last_date, isForward);
semaphore.release();
} else {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
@ -1346,6 +1409,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
});
}
}
});
}
@ -1579,6 +1643,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
putChats(dialogsRes.chats, isCache);
if (encChats != null) {
for (TLRPC.EncryptedChat encryptedChat : encChats) {
if (encryptedChat instanceof TLRPC.TL_encryptedChat && AndroidUtilities.getMyLayerVersion(encryptedChat.layer) < SendMessagesHelper.CURRENT_SECRET_CHAT_LAYER) {
SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null);
}
putEncryptedChat(encryptedChat, true);
}
}
@ -1643,6 +1710,26 @@ public class MessagesController implements NotificationCenter.NotificationCenter
});
}
public void markMessageAsRead(final long dialog_id, final long random_id, int ttl) {
if (random_id == 0 || dialog_id == 0 || ttl <= 0) {
return;
}
int lower_part = (int)dialog_id;
int high_id = (int)(dialog_id >> 32);
if (lower_part != 0) {
return;
}
TLRPC.EncryptedChat chat = getEncryptedChat(high_id);
if (chat == null) {
return;
}
ArrayList<Long> random_ids = new ArrayList<Long>();
random_ids.add(random_id);
SendMessagesHelper.getInstance().sendMessagesReadMessage(chat, random_ids, null);
int time = ConnectionsManager.getInstance().getCurrentTime();
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, time, time, 0, random_ids);
}
public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int offset, final int max_date, final boolean was, final boolean popup) {
int lower_part = (int)dialog_id;
int high_id = (int)(dialog_id >> 32);
@ -1756,19 +1843,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (chat.ttl > 0 && was) {
int serverTime = Math.max(ConnectionsManager.getInstance().getCurrentTime(), max_date);
MessagesStorage.getInstance().createTaskForDate(chat.id, serverTime, serverTime, 0);
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, serverTime, serverTime, 0, null);
}
}
}
private void processPendingEncMessages() {
if (pendingEncMessagesToDelete.isEmpty()) {
return;
}
if (!pendingEncMessagesToDelete.isEmpty()) {
ArrayList<Long> arr = new ArrayList<Long>(pendingEncMessagesToDelete);
MessagesStorage.getInstance().markMessagesAsDeletedByRandoms(arr);
pendingEncMessagesToDelete.clear();
}
}
public long createChat(String title, ArrayList<Integer> selectedContacts, final TLRPC.InputFile uploadedAvatar, boolean isBroadcast) {
if (isBroadcast) {
@ -1803,11 +1889,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMsg.action = new TLRPC.TL_messageActionCreatedBroadcastList();
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.getClientUserId();
newMsg.unread = false;
newMsg.dialog_id = AndroidUtilities.makeBroadcastId(chat.id);
newMsg.to_id = new TLRPC.TL_peerChat();
newMsg.to_id.chat_id = chat.id;
newMsg.out = false;
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
newMsg.random_id = 0;
UserConfig.saveConfig(false);
@ -2570,7 +2654,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.message = updates.message;
message.date = updates.date;
message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
message.unread = true;
message.media = new TLRPC.TL_messageMediaEmpty();
MessagesStorage.lastSeqValue = updates.seq;
MessagesStorage.lastPtsValue = updates.pts;
@ -2635,7 +2718,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.to_id.user_id = updates.from_id;
message.message = updates.message;
message.date = updates.date;
message.unread = true;
message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
message.media = new TLRPC.TL_messageMediaEmpty();
MessagesStorage.lastSeqValue = updates.seq;
@ -2914,13 +2996,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.action = new TLRPC.TL_messageActionUserJoined();
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false);
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.date = update.date;
newMessage.from_id = update.user_id;
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = update.user_id;
messagesArr.add(newMessage);
@ -2960,13 +3040,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.action.address = update.location;
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false);
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.date = update.date;
newMessage.from_id = 777000;
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = 777000;
messagesArr.add(newMessage);
@ -3099,6 +3177,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newChat.user_id = exist.user_id;
newChat.auth_key = exist.auth_key;
newChat.ttl = exist.ttl;
newChat.seq_in = exist.seq_in;
newChat.seq_out = exist.seq_out;
putEncryptedChat(newChat, false);
}
MessagesStorage.getInstance().updateEncryptedChat(newChat);
@ -3135,6 +3215,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
});
} else if (update instanceof TLRPC.TL_updateNotifySettings) {
updatesOnMainThread.add(update);
} else if (update instanceof TLRPC.TL_updateServiceNotification) {
//TODO
}
}
if (!messages.isEmpty()) {
@ -3203,9 +3285,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (currentUser != null) {
currentUser.first_name = update.first_name;
currentUser.last_name = update.last_name;
currentUser.username = update.username;
}
toDbUser.first_name = update.first_name;
toDbUser.last_name = update.last_name;
toDbUser.username = update.username;
dbUsers.add(toDbUser);
} else if (update instanceof TLRPC.TL_updateUserPhoto) {
if (currentUser != null) {
@ -3295,7 +3379,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
for (Integer id : markAsReadMessages) {
MessageObject obj = dialogMessage.get(id);
if (obj != null) {
obj.messageOwner.unread = false;
obj.setIsRead();
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
}
}
@ -3308,7 +3392,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (dialog != null) {
MessageObject message = dialogMessage.get(dialog.top_message);
if (message != null && message.messageOwner.date <= entry.getValue()) {
message.messageOwner.unread = false;
message.setIsRead();
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
}
}
@ -3345,7 +3429,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
if (!tasks.isEmpty()) {
for (TLRPC.TL_updateEncryptedMessagesRead update : tasks) {
MessagesStorage.getInstance().createTaskForDate(update.chat_id, update.max_date, update.date, 1);
MessagesStorage.getInstance().createTaskForSecretChat(update.chat_id, update.max_date, update.date, 1, null);
}
}
@ -3473,8 +3557,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
public TLRPC.Message decryptMessage(TLRPC.EncryptedMessage message) {
TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id);
if (chat == null) {
final TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id);
if (chat == null || chat instanceof TLRPC.TL_encryptedChatDiscarded) {
return null;
}
ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length);
@ -3496,9 +3580,53 @@ public class MessagesController implements NotificationCenter.NotificationCenter
from_id = chat.participant_id;
}
if (object instanceof TLRPC.TL_decryptedMessageLayer) {
final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer)object;
if (chat.seq_in == 0 && chat.seq_out == 0) {
if (chat.admin_id == UserConfig.getClientUserId()) {
chat.seq_out = 1;
} else {
chat.seq_in = 1;
}
}
if (chat.seq_in != layer.out_seq_no && chat.seq_in != layer.out_seq_no - 2) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded();
newChat.id = chat.id;
newChat.user_id = chat.user_id;
newChat.auth_key = chat.auth_key;
newChat.seq_in = chat.seq_in;
newChat.seq_out = chat.seq_out;
MessagesStorage.getInstance().updateEncryptedChat(newChat);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
putEncryptedChat(newChat, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
}
});
declineSecretChat(chat.id);
}
});
return null;
}
chat.seq_in = layer.out_seq_no;
MessagesStorage.getInstance().updateEncryptedChatSeq(chat);
object = layer.message;
}
if (object instanceof TLRPC.TL_decryptedMessage) {
TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object;
TLRPC.TL_message newMessage = new TLRPC.TL_message();
TLRPC.TL_message newMessage = null;
if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) {
newMessage = new TLRPC.TL_message_secret();
newMessage.ttl = decryptedMessage.ttl;
} else {
newMessage = new TLRPC.TL_message();
newMessage.ttl = chat.ttl;
}
newMessage.message = decryptedMessage.message;
newMessage.date = message.date;
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
@ -3508,10 +3636,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.random_id = message.random_id;
newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.out = false;
newMessage.unread = true;
newMessage.dialog_id = ((long)chat.id) << 32;
newMessage.ttl = chat.ttl;
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) {
newMessage.media = new TLRPC.TL_messageMediaEmpty();
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) {
@ -3535,7 +3660,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.media.photo.date = newMessage.date;
newMessage.media.photo.caption = "";
newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty();
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize();
small.w = decryptedMessage.media.thumb_w;
small.h = decryptedMessage.media.thumb_h;
@ -3564,7 +3689,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
newMessage.media = new TLRPC.TL_messageMediaVideo();
newMessage.media.video = new TLRPC.TL_videoEncrypted();
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize();
newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb;
newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w;
@ -3588,6 +3713,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.media.video.key = decryptedMessage.media.key;
newMessage.media.video.iv = decryptedMessage.media.iv;
newMessage.media.video.mime_type = decryptedMessage.media.mime_type;
if (newMessage.ttl != 0) {
newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl);
}
if (newMessage.media.video.mime_type == null) {
newMessage.media.video.mime_type = "video/mp4";
}
@ -3606,7 +3734,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.media.document.size = message.file.size;
newMessage.media.document.key = decryptedMessage.media.key;
newMessage.media.document.iv = decryptedMessage.media.iv;
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize();
newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb;
newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w;
@ -3634,6 +3762,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.media.audio.dc_id = message.file.dc_id;
newMessage.media.audio.duration = decryptedMessage.media.duration;
newMessage.media.audio.mime_type = decryptedMessage.media.mime_type;
if (newMessage.ttl != 0) {
newMessage.ttl = Math.max(newMessage.media.audio.duration + 1, newMessage.ttl);
}
if (newMessage.media.audio.mime_type == null) {
newMessage.media.audio.mime_type = "audio/ogg";
}
@ -3642,29 +3773,29 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
return newMessage;
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object;
final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object;
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService();
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
newMessage.action = new TLRPC.TL_messageActionTTLChange();
newMessage.action.ttl = chat.ttl = serviceMessage.action.ttl_seconds;
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
newMessage.action = new TLRPC.TL_messageEcryptedAction();
newMessage.action = new TLRPC.TL_messageEncryptedAction();
if (serviceMessage.action.ttl_seconds < 0 || serviceMessage.action.ttl_seconds > 60 * 60 * 24 * 365) {
serviceMessage.action.ttl_seconds = 60 * 60 * 24 * 365;
}
chat.ttl = serviceMessage.action.ttl_seconds;
newMessage.action.encryptedAction = serviceMessage.action;
MessagesStorage.getInstance().updateEncryptedChatTTL(chat);
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
newMessage.action = new TLRPC.TL_messageEncryptedAction();
newMessage.action.encryptedAction = serviceMessage.action;
} else {
return null;
}
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false);
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.unread = true;
newMessage.date = message.date;
newMessage.from_id = from_id;
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = ((long)chat.id) << 32;
MessagesStorage.getInstance().updateEncryptedChatTTL(chat);
return newMessage;
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) {
final long did = ((long)chat.id) << 32;
@ -3701,6 +3832,25 @@ public class MessagesController implements NotificationCenter.NotificationCenter
pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids);
}
return null;
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionReadMessages) {
if (!serviceMessage.action.random_ids.isEmpty()) {
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, ConnectionsManager.getInstance().getCurrentTime(), ConnectionsManager.getInstance().getCurrentTime(), 1, serviceMessage.action.random_ids);
}
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
int currentPeerLayer = AndroidUtilities.getPeerLayerVersion(chat.layer);
chat.layer = 0;
chat.layer = AndroidUtilities.setPeerLayerVersion(chat.layer, serviceMessage.action.layer);
MessagesStorage.getInstance().updateEncryptedChatLayer(chat);
if (currentPeerLayer < 17) {
SendMessagesHelper.getInstance().sendNotifyLayerMessage(chat, null);
}
}
});
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionResend) {
} else {
return null;
}
@ -3747,12 +3897,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
long fingerprint = Utilities.bytesToLong(authKeyId);
if (encryptedChat.key_fingerprint == fingerprint) {
encryptedChat.auth_key = authKey;
encryptedChat.seq_in = 0;
encryptedChat.seq_out = 1;
MessagesStorage.getInstance().updateEncryptedChat(encryptedChat);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
putEncryptedChat(encryptedChat, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat);
SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null);
}
});
} else {
@ -3760,6 +3913,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newChat.id = encryptedChat.id;
newChat.user_id = encryptedChat.user_id;
newChat.auth_key = encryptedChat.auth_key;
newChat.seq_in = encryptedChat.seq_in;
newChat.seq_out = encryptedChat.seq_out;
MessagesStorage.getInstance().updateEncryptedChat(newChat);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
@ -3813,6 +3968,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]);
}
encryptedChat.a_or_b = salt;
encryptedChat.seq_in = 1;
encryptedChat.seq_out = 0;
BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes);
BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG);
g_b = g_b.modPow(new BigInteger(1, salt), p);
@ -3865,12 +4022,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat) response;
newChat.auth_key = encryptedChat.auth_key;
newChat.user_id = encryptedChat.user_id;
newChat.seq_in = encryptedChat.seq_in;
newChat.seq_out = encryptedChat.seq_out;
MessagesStorage.getInstance().updateEncryptedChat(newChat);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
putEncryptedChat(newChat, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
SendMessagesHelper.getInstance().sendNotifyLayerMessage(newChat, null);
}
});
}
@ -3956,8 +4116,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) response;
chat.user_id = chat.participant_id;
putEncryptedChat(chat, false);
chat.seq_in = 0;
chat.seq_out = 1;
chat.a_or_b = salt;
putEncryptedChat(chat, false);
TLRPC.TL_dialog dialog = new TLRPC.TL_dialog();
dialog.id = ((long) chat.id) << 32;
dialog.unread_count = 0;
@ -4012,7 +4174,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setMessage(LocaleController.formatString("CreateEncryptedChatOutdatedError", R.string.CreateEncryptedChatOutdatedError, user.first_name, user.first_name));
builder.setMessage(LocaleController.getString("CreateEncryptedChatError", R.string.CreateEncryptedChatError));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
builder.show().setCanceledOnTouchOutside(true);
}

View File

@ -24,9 +24,9 @@ import java.util.zip.ZipFile;
public class NativeLoader {
private static final long sizes[] = new long[] {
946908, //armeabi
1028848, //armeabi-v7a
1603780, //x86
955148, //armeabi
1041184, //armeabi-v7a
1616116, //x86
0, //mips
};

View File

@ -41,6 +41,7 @@ public class NotificationCenter {
public static final int openedChatChanged = 29;
public static final int hideEmojiKeyboard = 30;
public static final int stopEncodingService = 31;
public static final int didCreatedNewDeleteTask = 32;
public static final int wallpapersDidLoaded = 171;
public static final int closeOtherAppActivities = 702;
@ -67,6 +68,7 @@ public class NotificationCenter {
public final static int screenshotTook = 50007;
public final static int albumsDidLoaded = 50008;
public final static int audioDidSent = 50009;
public final static int audioDidStarted = 50010;
final private HashMap<Integer, ArrayList<Object>> observers = new HashMap<Integer, ArrayList<Object>>();

View File

@ -21,7 +21,7 @@ public class PhotoObject {
public TLRPC.PhotoSize photoOwner;
public Bitmap image;
public PhotoObject(TLRPC.PhotoSize photo, int preview) {
public PhotoObject(TLRPC.PhotoSize photo, int preview, boolean secret) {
photoOwner = photo;
if (preview != 0 && photo instanceof TLRPC.TL_photoCachedSize) {
@ -34,7 +34,13 @@ public class PhotoObject {
image = BitmapFactory.decodeByteArray(photoOwner.bytes, 0, photoOwner.bytes.length, opts);
if (image != null) {
if (preview == 2) {
Utilities.blurBitmap(image);
if (secret) {
Utilities.blurBitmap(image, 7);
Utilities.blurBitmap(image, 7);
Utilities.blurBitmap(image, 7);
} else {
Utilities.blurBitmap(image, 3);
}
}
if (ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackFree(image.getRowBytes() * image.getHeight());

View File

@ -45,7 +45,7 @@ public class VideoEncodingService extends Service implements NotificationCenter.
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.FileUploadProgressChanged) {
String fileName = (String)args[0];
if (path.equals(fileName)) {
if (path != null && path.equals(fileName)) {
Float progress = (Float) args[1];
Boolean enc = (Boolean) args[2];
currentProgress = (int)(progress * 100);

View File

@ -54,12 +54,13 @@ public class MP4Builder {
private InterleaveChunkMdat mdat = null;
private Mp4Movie currentMp4Movie = null;
FileOutputStream fos = null;
private FileOutputStream fos = null;
private FileChannel fc = null;
private long dataOffset = 0;
private long writedSinceLastMdat = 0;
private boolean writeNewMdat = true;
HashMap<Track, long[]> track2SampleSizes = new HashMap<Track, long[]>();
private HashMap<Track, long[]> track2SampleSizes = new HashMap<Track, long[]>();
private ByteBuffer sizeBuffer = null;
public MP4Builder createMovie(Mp4Movie mp4Movie) throws Exception {
currentMp4Movie = mp4Movie;
@ -74,6 +75,8 @@ public class MP4Builder {
mdat = new InterleaveChunkMdat();
sizeBuffer = ByteBuffer.allocateDirect(4);
return this;
}
@ -87,7 +90,7 @@ public class MP4Builder {
fos.flush();
}
public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) throws Exception {
public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo, boolean isAudio) throws Exception {
if (writeNewMdat) {
mdat.setContentSize(0);
mdat.getBox(fc);
@ -109,9 +112,16 @@ public class MP4Builder {
}
currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo);
byteBuf.position(bufferInfo.offset);
byteBuf.position(bufferInfo.offset + (isAudio ? 0 : 4));
byteBuf.limit(bufferInfo.offset + bufferInfo.size);
if (!isAudio) {
sizeBuffer.position(0);
sizeBuffer.putInt(bufferInfo.size - 4);
sizeBuffer.position(0);
fc.write(sizeBuffer);
}
fc.write(byteBuf);
dataOffset += bufferInfo.size;

View File

@ -833,7 +833,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
}
object = invoke;
}
TLRPC.invokeWithLayer17 invoke = new TLRPC.invokeWithLayer17();
TLRPC.invokeWithLayer18 invoke = new TLRPC.invokeWithLayer18();
invoke.query = object;
FileLog.d("wrap in layer", "" + object);
return invoke;
@ -997,6 +997,10 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
return (int)(System.currentTimeMillis() / 1000) + timeDifference;
}
public int getTimeDifference() {
return timeDifference;
}
private void processRequestQueue(int requestClass, int _datacenterId) {
boolean haveNetwork = true;//isNetworkOnline();
@ -1382,7 +1386,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
if (rawRequest != null && (rawRequest instanceof TLRPC.TL_messages_sendMessage ||
rawRequest instanceof TLRPC.TL_messages_sendMedia ||
rawRequest instanceof TLRPC.TL_messages_forwardMessages ||
rawRequest instanceof TLRPC.TL_messages_sendEncrypted)) {
rawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
rawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
rawRequest instanceof TLRPC.TL_messages_sendEncryptedService)) {
if (rawRequest instanceof TLRPC.TL_messages_sendMessage) {
hasSendMessage = true;
@ -1400,7 +1406,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
if (currentRawRequest instanceof TLRPC.TL_messages_sendMessage ||
currentRawRequest instanceof TLRPC.TL_messages_sendMedia ||
currentRawRequest instanceof TLRPC.TL_messages_forwardMessages ||
currentRawRequest instanceof TLRPC.TL_messages_sendEncrypted) {
currentRawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
currentRawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
currentRawRequest instanceof TLRPC.TL_messages_sendEncryptedService) {
currentRequests.add(currentMessage.msg_id);
}
}
@ -1410,7 +1418,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
if (request.rawRequest instanceof TLRPC.TL_messages_sendMessage ||
request.rawRequest instanceof TLRPC.TL_messages_sendMedia ||
request.rawRequest instanceof TLRPC.TL_messages_forwardMessages ||
request.rawRequest instanceof TLRPC.TL_messages_sendEncrypted) {
request.rawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
request.rawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
request.rawRequest instanceof TLRPC.TL_messages_sendEncryptedService) {
if (!currentRequests.contains(request.runningMessageId)) {
maxRequestId = Math.max(maxRequestId, request.runningMessageId);
}
@ -1604,12 +1614,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
TLRPC.TL_protoMessage message = networkMessage.protoMessage;
if (BuildVars.DEBUG_VERSION) {
if (message.body instanceof TLRPC.invokeWithLayer17) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)message.body).query);
if (message.body instanceof TLRPC.invokeWithLayer18) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)message.body).query);
} else if (message.body instanceof TLRPC.initConnection) {
TLRPC.initConnection r = (TLRPC.initConnection)message.body;
if (r.query instanceof TLRPC.invokeWithLayer17) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)r.query).query);
if (r.query instanceof TLRPC.invokeWithLayer18) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)r.query).query);
} else {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + r.query);
}
@ -1644,12 +1654,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
TLRPC.TL_protoMessage message = networkMessage.protoMessage;
containerMessages.add(message);
if (BuildVars.DEBUG_VERSION) {
if (message.body instanceof TLRPC.invokeWithLayer17) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)message.body).query);
if (message.body instanceof TLRPC.invokeWithLayer18) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)message.body).query);
} else if (message.body instanceof TLRPC.initConnection) {
TLRPC.initConnection r = (TLRPC.initConnection)message.body;
if (r.query instanceof TLRPC.invokeWithLayer17) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)r.query).query);
if (r.query instanceof TLRPC.invokeWithLayer18) {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)r.query).query);
} else {
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + r.query);
}
@ -2066,12 +2076,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
int errorCode = ((TLRPC.RpcError) resultContainer.result).error_code;
if (errorCode == 500 || errorCode < 0) {
if ((request.flags & RPCRequest.RPCRequestClassFailOnServerErrors) != 0) {
if (request.serverFailureCount < 1) {
discardResponse = true;
request.runningMinStartTime = request.runningStartTime + 1;
}
} else {
if ((request.flags & RPCRequest.RPCRequestClassFailOnServerErrors) == 0) {
discardResponse = true;
int delay = Math.min(1, request.serverFailureCount * 2);
request.runningMinStartTime = request.runningStartTime + delay;
@ -2433,6 +2438,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
}
});
} else if ((connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
FileLog.e("tmessages", "call connection closed");
sendingPushPing = false;
lastPushPingTime = System.currentTimeMillis() - 60000 * 3 + 4000;
}

View File

@ -63,7 +63,7 @@ public class DispatchQueue extends Thread {
postRunnable(runnable, 0);
}
public void postRunnable(Runnable runnable, int delay) {
public void postRunnable(Runnable runnable, long delay) {
if (handler == null) {
synchronized (handlerSyncObject) {
if (handler == null) {

View File

@ -176,7 +176,7 @@ public class FileLoader {
}
if (small) {
currentUploadSmallOperationsCount--;
if (currentUploadSmallOperationsCount < 2) {
if (currentUploadSmallOperationsCount < 1) {
FileUploadOperation operation = uploadSmallOperationQueue.poll();
if (operation != null) {
currentUploadSmallOperationsCount++;
@ -185,7 +185,7 @@ public class FileLoader {
}
} else {
currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) {
if (currentUploadOperationsCount < 1) {
FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) {
currentUploadOperationsCount++;
@ -227,7 +227,7 @@ public class FileLoader {
});
if (small) {
currentUploadSmallOperationsCount--;
if (currentUploadSmallOperationsCount < 2) {
if (currentUploadSmallOperationsCount < 1) {
FileUploadOperation operation = uploadSmallOperationQueue.poll();
if (operation != null) {
currentUploadSmallOperationsCount++;
@ -236,7 +236,7 @@ public class FileLoader {
}
} else {
currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) {
if (currentUploadOperationsCount < 1) {
FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) {
currentUploadOperationsCount++;
@ -259,14 +259,14 @@ public class FileLoader {
}
};
if (small) {
if (currentUploadSmallOperationsCount < 2) {
if (currentUploadSmallOperationsCount < 1) {
currentUploadSmallOperationsCount++;
operation.start();
} else {
uploadSmallOperationQueue.add(operation);
}
} else {
if (currentUploadOperationsCount < 2) {
if (currentUploadOperationsCount < 1) {
currentUploadOperationsCount++;
operation.start();
} else {
@ -564,6 +564,17 @@ public class FileLoader {
if (message == null) {
return new File("");
}
if (message instanceof TLRPC.TL_messageService) {
if (message.action.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
if (sizeFull != null) {
return getPathToAttach(sizeFull);
}
}
}
} else {
if (message.media instanceof TLRPC.TL_messageMediaVideo) {
return getPathToAttach(message.media.video);
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
@ -579,6 +590,7 @@ public class FileLoader {
}
}
}
}
return new File("");
}
@ -692,4 +704,26 @@ public class FileLoader {
}
return "";
}
public void deleteFiles(final ArrayList<File> files) {
if (files == null || files.isEmpty()) {
return;
}
fileLoaderQueue.postRunnable(new Runnable() {
@Override
public void run() {
for (File file : files) {
if (file.exists()) {
try {
if (!file.delete()) {
file.deleteOnExit();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
}
});
}
}

View File

@ -198,6 +198,7 @@ public class TLClassStore {
classStore.put(TLRPC.TL_updateReadMessages.constructor, TLRPC.TL_updateReadMessages.class);
classStore.put(TLRPC.TL_updateChatParticipantDelete.constructor, TLRPC.TL_updateChatParticipantDelete.class);
classStore.put(TLRPC.TL_updateRestoreMessages.constructor, TLRPC.TL_updateRestoreMessages.class);
classStore.put(TLRPC.TL_updateServiceNotification.constructor, TLRPC.TL_updateServiceNotification.class);
classStore.put(TLRPC.TL_updateNotifySettings.constructor, TLRPC.TL_updateNotifySettings.class);
classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class);
classStore.put(TLRPC.TL_updateChatUserTyping.constructor, TLRPC.TL_updateChatUserTyping.class);
@ -226,6 +227,7 @@ public class TLClassStore {
classStore.put(TLRPC.TL_inputEncryptedFileEmpty.constructor, TLRPC.TL_inputEncryptedFileEmpty.class);
classStore.put(TLRPC.TL_inputEncryptedFileUploaded.constructor, TLRPC.TL_inputEncryptedFileUploaded.class);
classStore.put(TLRPC.TL_decryptedMessageActionFlushHistory.constructor, TLRPC.TL_decryptedMessageActionFlushHistory.class);
classStore.put(TLRPC.TL_decryptedMessageActionResend.constructor, TLRPC.TL_decryptedMessageActionResend.class);
classStore.put(TLRPC.TL_decryptedMessageActionNotifyLayer.constructor, TLRPC.TL_decryptedMessageActionNotifyLayer.class);
classStore.put(TLRPC.TL_decryptedMessageActionSetMessageTTL.constructor, TLRPC.TL_decryptedMessageActionSetMessageTTL.class);
classStore.put(TLRPC.TL_decryptedMessageActionDeleteMessages.constructor, TLRPC.TL_decryptedMessageActionDeleteMessages.class);
@ -362,6 +364,13 @@ public class TLClassStore {
classStore.put(TLRPC.TL_messageService_old.constructor, TLRPC.TL_messageService_old.class);
classStore.put(TLRPC.TL_decryptedMessageService_old.constructor, TLRPC.TL_decryptedMessageService_old.class);
classStore.put(TLRPC.TL_decryptedMessage_old.constructor, TLRPC.TL_decryptedMessage_old.class);
classStore.put(TLRPC.TL_message_secret.constructor, TLRPC.TL_message_secret.class);
classStore.put(TLRPC.TL_userSelf_old.constructor, TLRPC.TL_userSelf_old.class);
classStore.put(TLRPC.TL_userContact_old.constructor, TLRPC.TL_userContact_old.class);
classStore.put(TLRPC.TL_userRequest_old.constructor, TLRPC.TL_userRequest_old.class);
classStore.put(TLRPC.TL_userForeign_old.constructor, TLRPC.TL_userForeign_old.class);
classStore.put(TLRPC.TL_userDeleted_old.constructor, TLRPC.TL_userDeleted_old.class);
classStore.put(TLRPC.TL_messageEncryptedAction.constructor, TLRPC.TL_messageEncryptedAction.class);
}
static TLClassStore store = null;

View File

@ -2084,13 +2084,14 @@ public class TLRPC {
}
public static class TL_userContact extends User {
public static int constructor = 0xf2fb8319;
public static int constructor = 0xcab35e18;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
access_hash = stream.readInt64();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -2102,6 +2103,7 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
stream.writeInt64(access_hash);
stream.writeString(phone);
photo.serializeToStream(stream);
@ -2110,13 +2112,14 @@ public class TLRPC {
}
public static class TL_userRequest extends User {
public static int constructor = 0x22e8ceb0;
public static int constructor = 0xd9ccc4ef;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
access_hash = stream.readInt64();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -2128,6 +2131,7 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
stream.writeInt64(access_hash);
stream.writeString(phone);
photo.serializeToStream(stream);
@ -2136,13 +2140,14 @@ public class TLRPC {
}
public static class TL_userForeign extends User {
public static int constructor = 0x5214c89d;
public static int constructor = 0x75cf7a8;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
access_hash = stream.readInt64();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -2153,6 +2158,7 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
stream.writeInt64(access_hash);
photo.serializeToStream(stream);
status.serializeToStream(stream);
@ -2160,13 +2166,14 @@ public class TLRPC {
}
public static class TL_userDeleted extends User {
public static int constructor = 0xb29ad7cc;
public static int constructor = 0xd6016d7a;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
}
public void serializeToStream(AbsSerializedData stream) {
@ -2174,17 +2181,19 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
}
}
public static class TL_userSelf extends User {
public static int constructor = 0x720535ec;
public static int constructor = 0x7007b451;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -2196,6 +2205,7 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
stream.writeString(phone);
photo.serializeToStream(stream);
status.serializeToStream(stream);
@ -2557,8 +2567,6 @@ public class TLRPC {
public static class DecryptedMessage extends TLObject {
public long random_id;
public byte[] random_bytes;
public int in_seq_no;
public int out_seq_no;
public DecryptedMessageAction action;
public int ttl;
public String message;
@ -2566,36 +2574,27 @@ public class TLRPC {
}
public static class TL_decryptedMessageService extends DecryptedMessage {
public static int constructor = 0xda431693;
public static int constructor = 0x73164160;
public void readParams(AbsSerializedData stream) {
random_id = stream.readInt64();
random_bytes = stream.readByteArray();
in_seq_no = stream.readInt32();
out_seq_no = stream.readInt32();
action = (DecryptedMessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(random_id);
stream.writeByteArray(random_bytes);
stream.writeInt32(in_seq_no);
stream.writeInt32(out_seq_no);
action.serializeToStream(stream);
}
}
public static class TL_decryptedMessage extends DecryptedMessage {
public static int constructor = 0x4e748938;
public static int constructor = 0x204d3878;
public void readParams(AbsSerializedData stream) {
random_id = stream.readInt64();
random_bytes = stream.readByteArray();
in_seq_no = stream.readInt32();
out_seq_no = stream.readInt32();
ttl = stream.readInt32();
message = stream.readString();
media = (DecryptedMessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -2604,9 +2603,6 @@ public class TLRPC {
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(random_id);
stream.writeByteArray(random_bytes);
stream.writeInt32(in_seq_no);
stream.writeInt32(out_seq_no);
stream.writeInt32(ttl);
stream.writeString(message);
media.serializeToStream(stream);
@ -3439,11 +3435,15 @@ public class TLRPC {
public ArrayList<Integer> messages = new ArrayList<Integer>();
public int pts;
public int version;
public String type;
public MessageMedia media;
public boolean popup;
public NotifyPeer peer;
public PeerNotifySettings notify_settings;
public SendMessageAction action;
public String first_name;
public String last_name;
public String username;
public int qts;
public int id;
public long random_id;
@ -3564,6 +3564,27 @@ public class TLRPC {
}
}
public static class TL_updateServiceNotification extends Update {
public static int constructor = 0x382dd3e4;
public String message;
public void readParams(AbsSerializedData stream) {
type = stream.readString();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
popup = stream.readBool();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(type);
stream.writeString(message);
media.serializeToStream(stream);
stream.writeBool(popup);
}
}
public static class TL_updateNotifySettings extends Update {
public static int constructor = 0xbec268ef;
@ -3615,13 +3636,14 @@ public class TLRPC {
}
public static class TL_updateUserName extends Update {
public static int constructor = 0xda22d9ad;
public static int constructor = 0xa7332b73;
public void readParams(AbsSerializedData stream) {
user_id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
username = stream.readString();
}
public void serializeToStream(AbsSerializedData stream) {
@ -3629,6 +3651,7 @@ public class TLRPC {
stream.writeInt32(user_id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(username);
}
}
@ -4051,6 +4074,8 @@ public class TLRPC {
}
public static class DecryptedMessageAction extends TLObject {
public int start_seq_no;
public int end_seq_no;
public int layer;
public int ttl_seconds;
public ArrayList<Long> random_ids = new ArrayList<Long>();
@ -4078,6 +4103,22 @@ public class TLRPC {
}
}
public static class TL_decryptedMessageActionResend extends DecryptedMessageAction {
public static int constructor = 0x511110b0;
public void readParams(AbsSerializedData stream) {
start_seq_no = stream.readInt32();
end_seq_no = stream.readInt32();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(start_seq_no);
stream.writeInt32(end_seq_no);
}
}
public static class TL_decryptedMessageActionNotifyLayer extends DecryptedMessageAction {
public static int constructor = 0xf3048883;
@ -4586,6 +4627,44 @@ public class TLRPC {
}
}
public static class TL_account_checkUsername extends TLObject {
public static int constructor = 0x2714d86c;
public String username;
public Class responseClass () {
return Bool.class;
}
public void readParams(AbsSerializedData stream) {
username = stream.readString();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(username);
}
}
public static class TL_account_updateUsername extends TLObject {
public static int constructor = 0x3e0bdd7c;
public String username;
public Class responseClass () {
return User.class;
}
public void readParams(AbsSerializedData stream) {
username = stream.readString();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(username);
}
}
public static class InputAudio extends TLObject {
public long id;
public long access_hash;
@ -6281,19 +6360,28 @@ public class TLRPC {
}
public static class TL_decryptedMessageLayer extends TLObject {
public static int constructor = 0x99a438cf;
public static int constructor = 0x1be31789;
public byte[] random_bytes;
public int layer;
public int in_seq_no;
public int out_seq_no;
public DecryptedMessage message;
public void readParams(AbsSerializedData stream) {
random_bytes = stream.readByteArray();
layer = stream.readInt32();
in_seq_no = stream.readInt32();
out_seq_no = stream.readInt32();
message = (DecryptedMessage)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeByteArray(random_bytes);
stream.writeInt32(layer);
stream.writeInt32(in_seq_no);
stream.writeInt32(out_seq_no);
message.serializeToStream(stream);
}
}
@ -8341,32 +8429,157 @@ public class TLRPC {
}
}
//manually created
public static class TL_messages_sendEncryptedService extends TLObject {
public static int constructor = 0x32d439a4;
public TL_inputEncryptedChat peer;
public long random_id;
public byte[] data;
public ByteBufferDesc data;
public Class responseClass () {
return messages_SentEncryptedMessage.class;
}
public void readParams(AbsSerializedData stream) {
peer = (TL_inputEncryptedChat)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
random_id = stream.readInt64();
data = stream.readByteArray();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
peer.serializeToStream(stream);
stream.writeInt64(random_id);
stream.writeByteArray(data);
stream.writeByteBuffer(data);
}
@Override
public void freeResources() {
if (disableFree) {
return;
}
if (data != null) {
BuffersStorage.getInstance().reuseFreeBuffer(data);
data = null;
}
}
}
//manually created
public static class TL_userDeleted_old extends TL_userDeleted {
public static int constructor = 0xb29ad7cc;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
}
}
public static class TL_userForeign_old extends TL_userForeign {
public static int constructor = 0x5214c89d;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
access_hash = stream.readInt64();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeInt64(access_hash);
photo.serializeToStream(stream);
status.serializeToStream(stream);
}
}
public static class TL_userRequest_old extends TL_userRequest {
public static int constructor = 0x22e8ceb0;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
access_hash = stream.readInt64();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeInt64(access_hash);
stream.writeString(phone);
photo.serializeToStream(stream);
status.serializeToStream(stream);
}
}
public static class TL_userContact_old extends TL_userContact {
public static int constructor = 0xf2fb8319;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
access_hash = stream.readInt64();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeInt64(access_hash);
stream.writeString(phone);
photo.serializeToStream(stream);
status.serializeToStream(stream);
}
}
public static class TL_userSelf_old extends TL_userSelf {
public static int constructor = 0x720535ec;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
first_name = stream.readString();
last_name = stream.readString();
phone = stream.readString();
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
inactive = stream.readBool();
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeString(first_name);
stream.writeString(last_name);
stream.writeString(phone);
photo.serializeToStream(stream);
status.serializeToStream(stream);
stream.writeBool(inactive);
}
}
public static class TL_set_client_DH_params extends TLObject {
public static int constructor = 0xf5045f1f;
@ -8769,8 +8982,6 @@ public class TLRPC {
public int fwd_date;
public int from_id;
public Peer to_id;
public boolean out;
public boolean unread;
public int date;
public String message;
public MessageMedia media;
@ -8782,6 +8993,10 @@ public class TLRPC {
public int local_id = 0;
public long dialog_id;
public int ttl;
public int destroyTime;
public int layer;
public int seq_in;
public int seq_out;
public VideoEditedInfo videoEditedInfo = null;
}
@ -8799,8 +9014,6 @@ public class TLRPC {
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = (flags & MESSAGE_FLAG_OUT) != 0;
unread = (flags & MESSAGE_FLAG_UNREAD) != 0;
if (id < 0) {
fwd_msg_id = stream.readInt32();
}
@ -8843,8 +9056,6 @@ public class TLRPC {
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = (flags & 2) != 0;
unread = (flags & 1) != 0;
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
attachPath = stream.readString();
}
@ -8878,8 +9089,6 @@ public class TLRPC {
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
date = stream.readInt32();
action = (MessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = (flags & 2) != 0;
unread = (flags & 1) != 0;
}
public void serializeToStream(AbsSerializedData stream) {
@ -8901,8 +9110,8 @@ public class TLRPC {
id = stream.readInt32();
from_id = stream.readInt32();
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = stream.readBool();
unread = stream.readBool();
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
date = stream.readInt32();
action = (MessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
@ -8912,8 +9121,8 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeInt32(from_id);
to_id.serializeToStream(stream);
stream.writeBool(out);
stream.writeBool(unread);
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
stream.writeInt32(date);
action.serializeToStream(stream);
}
@ -8929,8 +9138,8 @@ public class TLRPC {
fwd_date = stream.readInt32();
from_id = stream.readInt32();
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = stream.readBool();
unread = stream.readBool();
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -8953,8 +9162,8 @@ public class TLRPC {
stream.writeInt32(fwd_date);
stream.writeInt32(from_id);
to_id.serializeToStream(stream);
stream.writeBool(out);
stream.writeBool(unread);
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
stream.writeInt32(date);
stream.writeString(message);
media.serializeToStream(stream);
@ -8972,8 +9181,8 @@ public class TLRPC {
id = stream.readInt32();
from_id = stream.readInt32();
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = stream.readBool();
unread = stream.readBool();
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -8991,8 +9200,43 @@ public class TLRPC {
stream.writeInt32(id);
stream.writeInt32(from_id);
to_id.serializeToStream(stream);
stream.writeBool(out);
stream.writeBool(unread);
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
stream.writeInt32(date);
stream.writeString(message);
media.serializeToStream(stream);
stream.writeString(attachPath);
}
}
public static class TL_message_secret extends TL_message {
public static int constructor = 0x555555F8;
public void readParams(AbsSerializedData stream) {
flags = stream.readInt32();
id = stream.readInt32();
ttl = stream.readInt32();
from_id = stream.readInt32();
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
attachPath = stream.readString();
}
if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) {
videoEditedInfo = new VideoEditedInfo();
videoEditedInfo.parseString(message);
}
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeInt32(id);
stream.writeInt32(ttl);
stream.writeInt32(from_id);
to_id.serializeToStream(stream);
stream.writeInt32(date);
stream.writeString(message);
media.serializeToStream(stream);
@ -9105,6 +9349,7 @@ public class TLRPC {
public int id;
public String first_name;
public String last_name;
public String username;
public long access_hash;
public String phone;
public UserProfilePhoto photo;
@ -9305,6 +9550,9 @@ public class TLRPC {
public byte[] auth_key;
public int user_id;
public int ttl;
public int layer;
public int seq_in;
public int seq_out;
}
public static class FileLocation extends TLObject {
@ -9602,8 +9850,8 @@ public class TLRPC {
}
}
public static class invokeWithLayer17 extends TLObject {
public static int constructor = 0x50858a19;
public static class invokeWithLayer18 extends TLObject {
public static int constructor = 0x1c900537;
public TLObject query;
@ -9634,24 +9882,6 @@ public class TLRPC {
}
}
public static class decryptedMessageLayer extends TLObject {
public static int constructor = 0x99a438cf;
public int layer;
public TLObject message;
public void readParams(AbsSerializedData stream) {
layer = stream.readInt32();
message = TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(layer);
message.serializeToStream(stream);
}
}
public static class TL_encryptedChat_old extends TL_encryptedChat {
public static int constructor = 0x6601d14f;
@ -9738,7 +9968,7 @@ public class TLRPC {
}
public static class TL_decryptedMessageActionScreenshotMessages extends DecryptedMessageAction {
public static int constructor = 0x954bd30;
public static int constructor = 0x8ac1f475;
public void readParams(AbsSerializedData stream) {
@ -9770,7 +10000,7 @@ public class TLRPC {
}
}
public static class TL_messageEcryptedAction extends MessageAction {
public static class TL_messageEncryptedAction extends MessageAction {
public static int constructor = 0x555555F7;
public void readParams(AbsSerializedData stream) {

View File

@ -9,7 +9,6 @@
package org.telegram.messenger;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
@ -28,7 +27,6 @@ import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.CrashManagerListener;
import net.hockeyapp.android.UpdateManager;
import org.telegram.android.LocaleController;
import org.telegram.ui.ApplicationLoader;
import java.io.ByteArrayInputStream;
@ -74,8 +72,6 @@ public class Utilities {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static ProgressDialog progressDialog;
static {
try {
File URANDOM_FILE = new File("/dev/urandom");
@ -112,7 +108,7 @@ public class Utilities {
public native static long doPQNative(long _what);
public native static void loadBitmap(String path, int[] bitmap, int scale, int format, int width, int height);
public native static void blurBitmap(Object bitmap);
public native static void blurBitmap(Object bitmap, int radius);
public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap);
private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length);
@ -427,34 +423,6 @@ public class Utilities {
return packedData;
}
public static void ShowProgressDialog(final Activity activity, final String message) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if(!activity.isFinishing()) {
progressDialog = new ProgressDialog(activity);
if (message != null) {
progressDialog.setMessage(message);
}
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
}
});
}
public static void HideProgressDialog(Activity activity) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
});
}
public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException {
OutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[4096];

View File

@ -0,0 +1,61 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui.Adapters;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC;
import java.util.ArrayList;
public class BaseContactsSearchAdapter extends BaseFragmentAdapter {
protected ArrayList<TLRPC.User> globalSearch = new ArrayList<TLRPC.User>();
private long reqId = 0;
private int lastReqId;
protected String lastFoundUsername = null;
public void queryServerSearch(final String query) {
if (query == null || query.length() < 5) {
if (reqId != 0) {
ConnectionsManager.getInstance().cancelRpc(reqId, true);
reqId = 0;
}
globalSearch.clear();
lastReqId = 0;
notifyDataSetChanged();
return;
}
TLRPC.TL_contacts_search req = new TLRPC.TL_contacts_search();
req.q = query;
req.limit = 50;
final int currentReqId = ++lastReqId;
reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (currentReqId == lastReqId) {
if (error == null) {
TLRPC.TL_contacts_found res = (TLRPC.TL_contacts_found) response;
globalSearch = res.users;
lastFoundUsername = query;
notifyDataSetChanged();
}
}
reqId = 0;
}
});
}
}, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
}

View File

@ -14,6 +14,7 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
public class BaseFragmentAdapter extends BaseAdapter {
public void onFragmentCreate() {
}

View File

@ -21,6 +21,7 @@ import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.ui.Cells.ChatOrUserCell;
import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.HashMap;
@ -202,12 +203,10 @@ public class ContactsActivityAdapter extends SectionedBaseAdapter {
if (usersAsSections) {
if (section < ContactsController.getInstance().sortedUsersSectionsArray.size()) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView = new SettingsSectionLayout(mContext);
convertView.setBackgroundColor(0xffffffff);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
textView.setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
return convertView;
}
} else {
@ -221,12 +220,10 @@ public class ContactsActivityAdapter extends SectionedBaseAdapter {
}
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView = new SettingsSectionLayout(mContext);
convertView.setBackgroundColor(0xffffffff);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
textView.setText(ContactsController.getInstance().sortedContactsSectionsArray.get(section - 1));
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedContactsSectionsArray.get(section - 1));
return convertView;
}
}

View File

@ -9,10 +9,13 @@
package org.telegram.ui.Adapters;
import android.content.Context;
import android.text.Html;
import android.view.View;
import android.view.ViewGroup;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.android.ContactsController;
import org.telegram.messenger.FileLog;
@ -20,28 +23,34 @@ import org.telegram.android.MessagesController;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Cells.ChatOrUserCell;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
public class ContactsActivitySearchAdapter extends BaseContactsSearchAdapter {
private Context mContext;
private HashMap<Integer, TLRPC.User> ignoreUsers;
private ArrayList<TLRPC.User> searchResult;
private ArrayList<CharSequence> searchResultNames;
private Timer searchTimer;
private boolean allowUsernameSearch;
public ContactsActivitySearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1) {
public ContactsActivitySearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1, boolean usernameSearch) {
mContext = context;
ignoreUsers = arg1;
allowUsernameSearch = usernameSearch;
}
public void searchDialogs(final String query) {
if (query == null) {
searchResult = null;
searchResultNames = null;
searchResult.clear();
searchResultNames.clear();
if (allowUsernameSearch) {
queryServerSearch(null);
}
notifyDataSetChanged();
} else {
try {
@ -63,7 +72,7 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
}
processSearch(query);
}
}, 100, 300);
}, 200, 300);
}
}
@ -71,6 +80,9 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (allowUsernameSearch) {
queryServerSearch(query);
}
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<TLRPC.TL_contact>();
contactsCopy.addAll(ContactsController.getInstance().contacts);
Utilities.searchQueue.postRunnable(new Runnable() {
@ -87,12 +99,25 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
for (TLRPC.TL_contact contact : contactsCopy) {
TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id);
String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
if (name.startsWith(q) || name.contains(" " + q)) {
if (user.id == UserConfig.getClientUserId()) {
continue;
}
String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
int found = 0;
if (name.startsWith(q) || name.contains(" " + q)) {
found = 1;
} else if (user.username != null && user.username.startsWith(q)) {
found = 2;
}
if (found != 0) {
if (found == 1) {
resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q));
} else {
resultArrayNames.add(Utilities.generateSearchName("@" + user.username, null, "@" + q));
}
resultArray.add(user);
}
}
@ -117,28 +142,43 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override
public boolean areAllItemsEnabled() {
return true;
return false;
}
@Override
public boolean isEnabled(int i) {
return true;
return i != searchResult.size();
}
@Override
public int getCount() {
if (searchResult == null) {
return 0;
int count = searchResult.size();
int globalCount = globalSearch.size();
if (globalCount != 0) {
count += globalCount + 1;
}
return searchResult.size();
return count;
}
public boolean isGlobalSearch(int i) {
int localCount = searchResult.size();
int globalCount = globalSearch.size();
if (i >= 0 && i < localCount) {
return false;
} else if (i > localCount && i <= globalCount + localCount) {
return true;
}
return false;
}
@Override
public TLRPC.User getItem(int i) {
if (searchResult != null) {
if (i >= 0 && i < searchResult.size()) {
int localCount = searchResult.size();
int globalCount = globalSearch.size();
if (i >= 0 && i < localCount) {
return searchResult.get(i);
}
} else if (i > localCount && i <= globalCount + localCount) {
return globalSearch.get(i - localCount - 1);
}
return null;
}
@ -155,24 +195,47 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (i == searchResult.size()) {
if (view == null) {
view = new SettingsSectionLayout(mContext);
((SettingsSectionLayout) view).setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
}
} else {
if (view == null) {
view = new ChatOrUserCell(mContext);
((ChatOrUserCell)view).usePadding = false;
((ChatOrUserCell) view).usePadding = false;
}
((ChatOrUserCell) view).useSeparator = i != searchResult.size() - 1;
Object obj = searchResult.get(i);
TLRPC.User user = MessagesController.getInstance().getUser(((TLRPC.User)obj).id);
((ChatOrUserCell) view).useSeparator = (i != getCount() - 1 && i != searchResult.size() - 1);
TLRPC.User user = getItem(i);
if (user != null) {
((ChatOrUserCell)view).setData(user, null, null, searchResultNames.get(i), null);
CharSequence username = null;
CharSequence name = null;
if (i < searchResult.size()) {
name = searchResultNames.get(i);
if (name != null && user != null && user.username != null && user.username.length() > 0) {
if (name.toString().startsWith("@" + user.username)) {
username = name;
name = null;
}
}
} else if (i > searchResult.size() && user.username != null) {
try {
username = Html.fromHtml(String.format("<font color=\"#357aa8\">@%s</font>%s", user.username.substring(0, lastFoundUsername.length()), user.username.substring(lastFoundUsername.length())));
} catch (Exception e) {
username = user.username;
FileLog.e("tmessages", e);
}
}
((ChatOrUserCell) view).setData(user, null, null, name, username);
if (ignoreUsers != null) {
if (ignoreUsers.containsKey(user.id)) {
((ChatOrUserCell)view).drawAlpha = 0.5f;
((ChatOrUserCell) view).drawAlpha = 0.5f;
} else {
((ChatOrUserCell)view).drawAlpha = 1.0f;
((ChatOrUserCell) view).drawAlpha = 1.0f;
}
}
}
}
@ -181,16 +244,19 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override
public int getItemViewType(int i) {
if (i == searchResult.size()) {
return 1;
}
return 0;
}
@Override
public int getViewTypeCount() {
return 1;
return 2;
}
@Override
public boolean isEmpty() {
return searchResult == null || searchResult.size() == 0;
return searchResult.isEmpty() && globalSearch.isEmpty();
}
}

View File

@ -10,10 +10,43 @@ package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
public class BaseCell extends View {
private final class CheckForTap implements Runnable {
public void run() {
if (pendingCheckForLongPress == null) {
pendingCheckForLongPress = new CheckForLongPress();
}
pendingCheckForLongPress.currentPressCount = ++pressCount;
postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout());
}
}
class CheckForLongPress implements Runnable {
public int currentPressCount;
public void run() {
if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) {
checkingForLongPress = false;
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
onTouchEvent(event);
event.recycle();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
onLongPress();
}
}
}
private boolean checkingForLongPress = false;
private CheckForLongPress pendingCheckForLongPress = null;
private int pressCount = 0;
private CheckForTap pendingCheckForTap = null;
public BaseCell(Context context) {
super(context);
}
@ -25,4 +58,29 @@ public class BaseCell extends View {
protected void setDrawableBounds(Drawable drawable, int x, int y, int w, int h) {
drawable.setBounds(x, y, x + w, y + h);
}
protected void startCheckLongPress() {
if (checkingForLongPress) {
return;
}
checkingForLongPress = true;
if (pendingCheckForTap == null) {
pendingCheckForTap = new CheckForTap();
}
postDelayed(pendingCheckForTap, ViewConfiguration.getTapTimeout());
}
protected void cancelCheckLongPress() {
checkingForLongPress = false;
if (pendingCheckForLongPress != null) {
removeCallbacks(pendingCheckForLongPress);
}
if (pendingCheckForTap != null) {
removeCallbacks(pendingCheckForTap);
}
}
protected void onLongPress() {
}
}

View File

@ -0,0 +1,288 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.Spannable;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.style.URLSpan;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ImageReceiver;
import org.telegram.android.MessageObject;
import org.telegram.android.MessagesController;
import org.telegram.android.PhotoObject;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.PhotoViewer;
public class ChatActionCell extends BaseCell {
public static interface ChatActionCellDelegate {
public abstract void didClickedImage(ChatActionCell cell);
public abstract void didLongPressed(ChatActionCell cell);
public abstract void needOpenUserProfile(int uid);
}
private static Drawable backgroundBlack;
private static Drawable backgroundBlue;
private static TextPaint textPaint;
private URLSpan pressedLink;
private ImageReceiver imageReceiver;
private StaticLayout textLayout;
private int textWidth = 0;
private int textHeight = 0;
private int textX = 0;
private int textY = 0;
private int textXLeft = 0;
private boolean useBlackBackground = false;
private int previousWidth = 0;
private boolean imagePressed = false;
private MessageObject currentMessageObject;
private ChatActionCellDelegate delegate;
public ChatActionCell(Context context) {
super(context);
if (backgroundBlack == null) {
backgroundBlack = getResources().getDrawable(R.drawable.system_black);
backgroundBlue = getResources().getDrawable(R.drawable.system_blue);
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(0xffffffff);
textPaint.linkColor = 0xffffffff;
}
imageReceiver = new ImageReceiver(this);
textPaint.setTextSize(AndroidUtilities.dp(MessagesController.getInstance().fontSize));
}
public void setDelegate(ChatActionCellDelegate delegate) {
this.delegate = delegate;
}
public void setMessageObject(MessageObject messageObject) {
if (currentMessageObject == messageObject) {
return;
}
currentMessageObject = messageObject;
previousWidth = 0;
if (currentMessageObject.type == 11) {
int id = 0;
if (messageObject.messageOwner.to_id != null) {
if (messageObject.messageOwner.to_id.chat_id != 0) {
id = messageObject.messageOwner.to_id.chat_id;
} else {
id = messageObject.messageOwner.to_id.user_id;
if (id == UserConfig.getClientUserId()) {
id = messageObject.messageOwner.from_id;
}
}
}
if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
imageReceiver.setImage(currentMessageObject.messageOwner.action.newUserPhoto.photo_small, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(id)), false);
} else {
PhotoObject photo = PhotoObject.getClosestImageWithSize(currentMessageObject.photoThumbs, AndroidUtilities.dp(64));
if (photo != null) {
if (photo.image != null) {
imageReceiver.setImageBitmap(photo.image);
} else {
imageReceiver.setImage(photo.photoOwner.location, "50_50", getResources().getDrawable(AndroidUtilities.getGroupAvatarForId(id)), false);
}
} else {
imageReceiver.setImageBitmap(getResources().getDrawable(AndroidUtilities.getGroupAvatarForId(id)));
}
}
imageReceiver.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false);
} else {
imageReceiver.setImageBitmap((Bitmap)null);
}
requestLayout();
}
public void setUseBlackBackground(boolean value) {
useBlackBackground = value;
}
public MessageObject getMessageObject() {
return currentMessageObject;
}
public ImageReceiver getPhotoImage() {
return imageReceiver;
}
@Override
protected void onLongPress() {
if (delegate != null) {
delegate.didLongPressed(this);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean result = false;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (delegate != null) {
if (currentMessageObject.type == 11 && imageReceiver.isInsideImage(x, y)) {
imagePressed = true;
result = true;
}
if (result) {
startCheckLongPress();
}
}
} else {
if (event.getAction() != MotionEvent.ACTION_MOVE) {
cancelCheckLongPress();
}
if (imagePressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
imagePressed = false;
if (delegate != null) {
delegate.didClickedImage(this);
playSoundEffect(SoundEffectConstants.CLICK);
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
imagePressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!imageReceiver.isInsideImage(x, y)) {
imagePressed = false;
}
}
}
}
if (!result) {
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
if (x >= textX && y >= textY && x <= textX + textWidth && y <= textY + textHeight) {
y -= textY;
x -= textXLeft;
final int line = textLayout.getLineForVertical((int)y);
final int off = textLayout.getOffsetForHorizontal(line, x);
final float left = textLayout.getLineLeft(line);
if (left <= x && left + textLayout.getLineWidth(line) >= x) {
Spannable buffer = (Spannable)currentMessageObject.messageText;
URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
if (link.length != 0) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pressedLink = link[0];
result = true;
} else {
if (link[0] == pressedLink) {
if (delegate != null) {
delegate.needOpenUserProfile(Integer.parseInt(link[0].getURL()));
}
result = true;
}
}
} else {
pressedLink = null;
}
} else {
pressedLink = null;
}
} else {
pressedLink = null;
}
}
}
if (!result) {
result = super.onTouchEvent(event);
}
return result;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (currentMessageObject == null) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), textHeight + AndroidUtilities.dp(14));
return;
}
int width = MeasureSpec.getSize(widthMeasureSpec);
if (width != previousWidth) {
previousWidth = width;
textLayout = new StaticLayout(currentMessageObject.messageText, textPaint, width - AndroidUtilities.dp(30), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
textHeight = 0;
textWidth = 0;
try {
int linesCount = textLayout.getLineCount();
for (int a = 0; a < linesCount; a++) {
float lineWidth = 0;
float lineLeft = 0;
try {
lineWidth = textLayout.getLineWidth(a);
textHeight = (int)Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a)));
} catch (Exception e) {
FileLog.e("tmessages", e);
return;
}
textWidth = (int)Math.max(textWidth, Math.ceil(lineWidth));
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
textX = (width - textWidth) / 2;
textY = AndroidUtilities.dp(7);
textXLeft = (width - textLayout.getWidth()) / 2;
if (currentMessageObject.type == 11) {
imageReceiver.setImageCoords((width - AndroidUtilities.dp(64)) / 2, textHeight + AndroidUtilities.dp(15), AndroidUtilities.dp(64), AndroidUtilities.dp(64));
}
}
setMeasuredDimension(width, textHeight + AndroidUtilities.dp(14 + (currentMessageObject.type == 11 ? 70 : 0)));
}
@Override
protected void onDraw(Canvas canvas) {
if (currentMessageObject == null) {
return;
}
Drawable backgroundDrawable = null;
if (useBlackBackground) {
backgroundDrawable = backgroundBlack;
} else {
backgroundDrawable = backgroundBlue;
}
backgroundDrawable.setBounds(textX - AndroidUtilities.dp(5), AndroidUtilities.dp(5), textX + textWidth + AndroidUtilities.dp(5), AndroidUtilities.dp(9) + textHeight);
backgroundDrawable.draw(canvas);
if (currentMessageObject.type == 11) {
imageReceiver.draw(canvas);
}
if (textLayout != null) {
canvas.save();
canvas.translate(textXLeft, textY);
textLayout.draw(canvas);
canvas.restore();
}
}
}

View File

@ -36,6 +36,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
private static TextPaint timePaint;
private ImageReceiver avatarImage;
private boolean needAvatarImage = false;
private SeekBar seekBar;
private ProgressView progressView;
private int seekBarX;
@ -44,9 +45,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
private int buttonState = 0;
private int buttonX;
private int buttonY;
private int buttonPressed = 0;
private boolean buttonPressed = false;
private int avatarPressed = 0;
private boolean avatarPressed = false;
private StaticLayout timeLayout;
private int timeX;
@ -56,7 +57,6 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
public TLRPC.User audioUser;
private TLRPC.FileLocation currentPhoto;
private String currentNameString;
public ChatAudioCell(Context context) {
super(context);
@ -115,40 +115,40 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
int side = AndroidUtilities.dp(36);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
buttonPressed = 1;
buttonPressed = true;
invalidate();
result = true;
} else if (avatarImage.isInsideImage(x, y)) {
avatarPressed = 1;
} else if (needAvatarImage && avatarImage.isInsideImage(x, y)) {
avatarPressed = true;
result = true;
}
} else if (buttonPressed == 1) {
} else if (buttonPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
buttonPressed = 0;
buttonPressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
didPressedButton();
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
buttonPressed = 0;
buttonPressed = false;
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) {
buttonPressed = 0;
buttonPressed = false;
invalidate();
}
}
} else if (avatarPressed == 1) {
} else if (avatarPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
avatarPressed = 0;
avatarPressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
if (delegate != null) {
delegate.didPressedUserAvatar(this, audioUser);
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
avatarPressed = 0;
avatarPressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!avatarImage.isInsideImage(x, y)) {
avatarPressed = 0;
avatarPressed = false;
}
}
}
@ -301,7 +301,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
int x;
if (currentMessageObject.isOut()) {
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(9);
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(8);
seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(97);
buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67);
timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(71);
@ -318,11 +318,19 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
timeX = AndroidUtilities.dp(80);
}
}
int diff = 0;
if (needAvatarImage) {
avatarImage.setImageCoords(x, AndroidUtilities.dp(9), AndroidUtilities.dp(50), AndroidUtilities.dp(50));
} else {
diff = AndroidUtilities.dp(56);
seekBarX -= diff;
buttonX -= diff;
timeX -= diff;
}
seekBar.width = backgroundWidth - AndroidUtilities.dp(112);
seekBar.width = backgroundWidth - AndroidUtilities.dp(112) + diff;
seekBar.height = AndroidUtilities.dp(30);
progressView.width = backgroundWidth - AndroidUtilities.dp(136);
progressView.width = backgroundWidth - AndroidUtilities.dp(136) + diff;
progressView.height = AndroidUtilities.dp(30);
seekBarY = AndroidUtilities.dp(13);
buttonY = AndroidUtilities.dp(10);
@ -349,14 +357,18 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
if (uid == 0) {
uid = messageObject.messageOwner.from_id;
}
needAvatarImage = !(messageObject.messageOwner.to_id != null && messageObject.messageOwner.to_id.chat_id != 0 && !messageObject.isOut() && messageObject.messageOwner.media.audio.user_id == messageObject.messageOwner.from_id);
audioUser = MessagesController.getInstance().getUser(uid);
if (needAvatarImage) {
if (audioUser != null) {
if (audioUser.photo != null) {
currentPhoto = audioUser.photo.photo_small;
}
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
} else {
avatarImage.setImage((TLRPC.FileLocation)null, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
avatarImage.setImage(null, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
}
}
if (messageObject.isOut()) {
@ -380,7 +392,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
return;
}
avatarImage.draw(canvas, avatarImage.getImageX(), avatarImage.getImageY(), AndroidUtilities.dp(50), AndroidUtilities.dp(50));
if (needAvatarImage) {
avatarImage.draw(canvas);
}
canvas.save();
if (buttonState == 0 || buttonState == 1) {
@ -399,7 +413,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
} else {
timePaint.setColor(0xff70b15c);
}
Drawable buttonDrawable = statesDrawable[state][buttonPressed];
Drawable buttonDrawable = statesDrawable[state][buttonPressed ? 1 : 0];
int side = AndroidUtilities.dp(36);
int x = (side - buttonDrawable.getIntrinsicWidth()) / 2;
int y = (side - buttonDrawable.getIntrinsicHeight()) / 2;

View File

@ -17,10 +17,8 @@ import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.ViewConfiguration;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController;
@ -96,7 +94,7 @@ public class ChatBaseCell extends BaseCell {
private StaticLayout timeLayout;
protected int timeWidth;
protected int timeX;
private int timeX;
private TextPaint currentTimePaint;
private String currentTimeString;
protected boolean drawTime = true;
@ -108,58 +106,15 @@ public class ChatBaseCell extends BaseCell {
private TLRPC.User currentForwardUser;
private String currentForwardNameString;
public ChatBaseCellDelegate delegate;
protected ChatBaseCellDelegate delegate;
protected int namesOffset = 0;
private boolean checkingForLongPress = false;
private int pressCount = 0;
private CheckForLongPress pendingCheckForLongPress = null;
private CheckForTap pendingCheckForTap = null;
private int last_send_state = 0;
private final class CheckForTap implements Runnable {
public void run() {
if (pendingCheckForLongPress == null) {
pendingCheckForLongPress = new CheckForLongPress();
}
pendingCheckForLongPress.currentPressCount = ++pressCount;
postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout());
}
}
class CheckForLongPress implements Runnable {
public int currentPressCount;
public void run() {
if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) {
if (delegate != null) {
checkingForLongPress = false;
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
onTouchEvent(event);
event.recycle();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
delegate.didLongPressed(ChatBaseCell.this);
}
}
}
}
private int last_delete_date = 0;
public ChatBaseCell(Context context) {
super(context);
init();
avatarImage = new ImageReceiver(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
avatarImage.clearImage();
currentPhoto = null;
}
private void init() {
if (backgroundDrawableIn == null) {
backgroundDrawableIn = getResources().getDrawable(R.drawable.msg_in);
backgroundDrawableInSelected = getResources().getDrawable(R.drawable.msg_in_selected);
@ -198,6 +153,14 @@ public class ChatBaseCell extends BaseCell {
forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
forwardNamePaint.setTextSize(AndroidUtilities.dp(14));
}
avatarImage = new ImageReceiver(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
avatarImage.clearImage();
currentPhoto = null;
}
@Override
@ -206,6 +169,10 @@ public class ChatBaseCell extends BaseCell {
invalidate();
}
public void setDelegate(ChatBaseCellDelegate delegate) {
this.delegate = delegate;
}
public void setCheckPressed(boolean value, boolean pressed) {
isCheckPressed = value;
isPressed = pressed;
@ -219,6 +186,9 @@ public class ChatBaseCell extends BaseCell {
if (last_send_state != currentMessageObject.messageOwner.send_state) {
return true;
}
if (last_delete_date != currentMessageObject.messageOwner.destroyTime) {
return true;
}
TLRPC.User newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id);
TLRPC.FileLocation newPhoto = null;
@ -251,6 +221,7 @@ public class ChatBaseCell extends BaseCell {
public void setMessageObject(MessageObject messageObject) {
currentMessageObject = messageObject;
last_send_state = messageObject.messageOwner.send_state;
last_delete_date = messageObject.messageOwner.destroyTime;
isPressed = false;
isCheckPressed = true;
isAvatarVisible = false;
@ -344,27 +315,6 @@ public class ChatBaseCell extends BaseCell {
return backgroundWidth - AndroidUtilities.dp(8);
}
protected void startCheckLongPress() {
if (checkingForLongPress) {
return;
}
checkingForLongPress = true;
if (pendingCheckForTap == null) {
pendingCheckForTap = new CheckForTap();
}
postDelayed(pendingCheckForTap, ViewConfiguration.getTapTimeout());
}
protected void cancelCheckLongPress() {
checkingForLongPress = false;
if (pendingCheckForLongPress != null) {
removeCallbacks(pendingCheckForLongPress);
}
if (pendingCheckForTap != null) {
removeCallbacks(pendingCheckForTap);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = false;
@ -461,6 +411,12 @@ public class ChatBaseCell extends BaseCell {
}
@Override
protected void onLongPress() {
if (delegate != null) {
delegate.didLongPressed(this);
}
}
@Override
protected void onDraw(Canvas canvas) {
@ -474,7 +430,7 @@ public class ChatBaseCell extends BaseCell {
}
if (isAvatarVisible) {
avatarImage.draw(canvas, AndroidUtilities.dp(6), layoutHeight - AndroidUtilities.dp(45), AndroidUtilities.dp(42), AndroidUtilities.dp(42));
avatarImage.draw(canvas);
}
Drawable currentBackgroundDrawable = null;

View File

@ -0,0 +1,290 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController;
import org.telegram.android.ImageReceiver;
import org.telegram.android.LocaleController;
import org.telegram.android.MessageObject;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
public class ChatContactCell extends ChatBaseCell {
public static interface ChatContactCellDelegate {
public abstract void didClickAddButton(ChatContactCell cell, TLRPC.User user);
public abstract void didClickPhone(ChatContactCell cell);
}
private static TextPaint namePaint;
private static TextPaint phonePaint;
private static Drawable addContactDrawableIn;
private static Drawable addContactDrawableOut;
private ImageReceiver avatarImage;
private StaticLayout nameLayout;
private StaticLayout phoneLayout;
private TLRPC.User contactUser;
private TLRPC.FileLocation currentPhoto;
private boolean avatarPressed = false;
private boolean buttonPressed = false;
private boolean drawAddButton = false;
private int namesWidth = 0;
private ChatContactCellDelegate contactDelegate = null;
public ChatContactCell(Context context) {
super(context);
if (namePaint == null) {
namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
namePaint.setTextSize(AndroidUtilities.dp(15));
phonePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
phonePaint.setTextSize(AndroidUtilities.dp(15));
phonePaint.setColor(0xff000000);
addContactDrawableIn = getResources().getDrawable(R.drawable.addcontact_blue);
addContactDrawableOut = getResources().getDrawable(R.drawable.addcontact_green);
}
avatarImage = new ImageReceiver(this);
}
public void setContactDelegate(ChatContactCellDelegate delegate) {
this.contactDelegate = delegate;
}
@Override
protected boolean isUserDataChanged() {
if (currentMessageObject == null) {
return false;
}
int uid = currentMessageObject.messageOwner.media.user_id;
boolean newDrawAdd = contactUser != null && uid != UserConfig.getClientUserId() && ContactsController.getInstance().contactsDict.get(uid) == null;
if (newDrawAdd != drawAddButton) {
return true;
}
contactUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.media.user_id);
TLRPC.FileLocation newPhoto = null;
if (contactUser != null && contactUser.photo != null) {
newPhoto = contactUser.photo.photo_small;
}
return currentPhoto == null && newPhoto != null || currentPhoto != null && newPhoto == null || currentPhoto != null && newPhoto != null && (currentPhoto.local_id != newPhoto.local_id || currentPhoto.volume_id != newPhoto.volume_id) || super.isUserDataChanged();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean result = false;
int side = AndroidUtilities.dp(36);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x >= avatarImage.getImageX() && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42) && y >= avatarImage.getImageY() && y <= avatarImage.getImageY() + avatarImage.getImageHeight()) {
avatarPressed = true;
result = true;
} else if (x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52)) {
buttonPressed = true;
result = true;
}
if (result) {
startCheckLongPress();
}
} else {
if (event.getAction() != MotionEvent.ACTION_MOVE) {
cancelCheckLongPress();
}
if (avatarPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
avatarPressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
if (contactUser != null) {
if (delegate != null) {
delegate.didPressedUserAvatar(this, contactUser);
}
} else {
if (contactDelegate != null) {
contactDelegate.didClickPhone(this);
}
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
avatarPressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(x >= avatarImage.getImageX() && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42) && y >= avatarImage.getImageY() && y <= avatarImage.getImageY() + avatarImage.getImageHeight())) {
avatarPressed = false;
}
}
} else if (buttonPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
buttonPressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
if (contactUser != null && contactDelegate != null) {
contactDelegate.didClickAddButton(this, contactUser);
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
buttonPressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52))) {
buttonPressed = false;
}
}
}
}
if (!result) {
result = super.onTouchEvent(event);
}
return result;
}
@Override
public void setMessageObject(MessageObject messageObject) {
if (currentMessageObject != messageObject || isUserDataChanged()) {
int uid = messageObject.messageOwner.media.user_id;
contactUser = MessagesController.getInstance().getUser(uid);
drawAddButton = contactUser != null && uid != UserConfig.getClientUserId() && ContactsController.getInstance().contactsDict.get(uid) == null;
int maxWidth;
if (AndroidUtilities.isTablet()) {
maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
} else {
maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
}
maxWidth -= AndroidUtilities.dp(58 + (drawAddButton ? 42 : 0));
if (contactUser != null) {
if (contactUser.photo != null) {
currentPhoto = contactUser.photo.photo_small;
}
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
} else {
avatarImage.setImage(null, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
}
String currentNameString = ContactsController.formatName(messageObject.messageOwner.media.first_name, messageObject.messageOwner.media.last_name);
int nameWidth = Math.min((int) Math.ceil(namePaint.measureText(currentNameString)), maxWidth);
CharSequence stringFinal = TextUtils.ellipsize(currentNameString.replace("\n", " "), namePaint, nameWidth, TextUtils.TruncateAt.END);
nameLayout = new StaticLayout(stringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (nameLayout.getLineCount() > 0) {
nameWidth = (int)Math.ceil(nameLayout.getLineWidth(0));
} else {
nameWidth = 0;
}
String phone = messageObject.messageOwner.media.phone_number;
if (phone != null && phone.length() != 0) {
if (!phone.startsWith("+")) {
phone = "+" + phone;
}
phone = PhoneFormat.getInstance().format(phone);
} else {
phone = LocaleController.getString("NumberUnknown", R.string.NumberUnknown);
}
int phoneWidth = Math.min((int) Math.ceil(phonePaint.measureText(phone)), maxWidth);
stringFinal = TextUtils.ellipsize(phone.replace("\n", " "), phonePaint, phoneWidth, TextUtils.TruncateAt.END);
phoneLayout = new StaticLayout(stringFinal, phonePaint, phoneWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (phoneLayout.getLineCount() > 0) {
phoneWidth = (int)Math.ceil(phoneLayout.getLineWidth(0));
} else {
phoneWidth = 0;
}
namesWidth = Math.max(nameWidth, phoneWidth);
backgroundWidth = AndroidUtilities.dp(77 + (drawAddButton ? 42 : 0)) + namesWidth;
super.setMessageObject(messageObject);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(71));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (currentMessageObject == null) {
return;
}
int x;
if (currentMessageObject.isOut()) {
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(8);
} else {
if (isChat) {
x = AndroidUtilities.dp(69);
} else {
x = AndroidUtilities.dp(16);
}
}
avatarImage.setImageCoords(x, AndroidUtilities.dp(9), AndroidUtilities.dp(42), AndroidUtilities.dp(42));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (currentMessageObject == null) {
return;
}
avatarImage.draw(canvas);
if (nameLayout != null) {
canvas.save();
canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(10));
namePaint.setColor(AndroidUtilities.getColorForId(currentMessageObject.messageOwner.media.user_id));
nameLayout.draw(canvas);
canvas.restore();
}
if (phoneLayout != null) {
canvas.save();
canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(31));
phoneLayout.draw(canvas);
canvas.restore();
}
if (drawAddButton) {
Drawable addContactDrawable;
if (currentMessageObject.isOut()) {
addContactDrawable = addContactDrawableOut;
} else {
addContactDrawable = addContactDrawableIn;
}
setDrawableBounds(addContactDrawable, avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(78), AndroidUtilities.dp(13));
addContactDrawable.draw(canvas);
}
}
}

View File

@ -25,6 +25,7 @@ import android.view.animation.DecelerateInterpolator;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ImageLoader;
import org.telegram.android.LocaleController;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader;
import org.telegram.android.MediaController;
import org.telegram.messenger.R;
@ -41,7 +42,7 @@ import java.util.Locale;
public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener {
public static interface ChatMediaCellDelegate {
public abstract void didPressedImage(ChatMediaCell cell);
public abstract void didClickedImage(ChatMediaCell cell);
public abstract void didPressedOther(ChatMediaCell cell);
}
@ -52,13 +53,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private static Drawable videoIconDrawable;
private static Drawable docMenuInDrawable;
private static Drawable docMenuOutDrawable;
private static Drawable[] buttonStatesDrawables = new Drawable[5];
private static Drawable[] buttonStatesDrawables = new Drawable[8];
private static Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][2];
private static TextPaint infoPaint;
private static MessageObject lastDownloadedGifMessage = null;
private static TextPaint namePaint;
private static Paint docBackPaint;
private static Paint progressPaint;
private static Paint deleteProgressPaint;
private static DecelerateInterpolator decelerateInterpolator;
private GifDrawable gifDrawable = null;
@ -91,7 +93,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private int nameWidth = 0;
private String currentNameString;
public ChatMediaCellDelegate mediaDelegate = null;
private ChatMediaCellDelegate mediaDelegate = null;
private float currentProgress = 0;
private RectF progressRect = new RectF();
@ -101,6 +103,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private float animatedProgressValue = 0;
private long currentProgressTime = 0;
private float animationProgressStart = 0;
private RectF deleteProgressRect = new RectF();
private int lastSecretSecondsLeft = 0;
public ChatMediaCell(Context context) {
super(context);
@ -115,6 +119,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
buttonStatesDrawables[2] = getResources().getDrawable(R.drawable.photogif);
buttonStatesDrawables[3] = getResources().getDrawable(R.drawable.playvideo);
buttonStatesDrawables[4] = getResources().getDrawable(R.drawable.photopause);
buttonStatesDrawables[5] = getResources().getDrawable(R.drawable.burn);
buttonStatesDrawables[6] = getResources().getDrawable(R.drawable.circle);
buttonStatesDrawables[7] = getResources().getDrawable(R.drawable.photocheck);
buttonStatesDrawablesDoc[0][0] = getResources().getDrawable(R.drawable.docload_b);
buttonStatesDrawablesDoc[1][0] = getResources().getDrawable(R.drawable.doccancel_b);
buttonStatesDrawablesDoc[2][0] = getResources().getDrawable(R.drawable.docpause_b);
@ -139,6 +146,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
progressPaint.setStrokeCap(Paint.Cap.ROUND);
progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
deleteProgressPaint.setColor(0xffe4e2e0);
decelerateInterpolator = new DecelerateInterpolator();
}
@ -155,6 +165,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
}
public void setMediaDelegate(ChatMediaCellDelegate delegate) {
this.mediaDelegate = delegate;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@ -199,7 +213,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
}
}
if (result) {
if (imagePressed && currentMessageObject.isSecretPhoto()) {
imagePressed = false;
} else if (result) {
startCheckLongPress();
}
}
@ -225,8 +241,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} else if (imagePressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
imagePressed = false;
if (buttonState == -1 || buttonState == 2 || buttonState == 3) {
playSoundEffect(SoundEffectConstants.CLICK);
didPressedImage();
didClickedImage();
}
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
imagePressed = false;
@ -269,11 +287,11 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
return result;
}
private void didPressedImage() {
private void didClickedImage() {
if (currentMessageObject.type == 1) {
if (buttonState == -1) {
if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this);
mediaDelegate.didClickedImage(this);
}
} else if (buttonState == 0) {
didPressedButton();
@ -294,12 +312,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
} else if (currentMessageObject.type == 4) {
if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this);
mediaDelegate.didClickedImage(this);
}
} else if (currentMessageObject.type == 9) {
if (buttonState == -1) {
if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this);
mediaDelegate.didClickedImage(this);
}
}
}
@ -358,7 +376,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
} else if (buttonState == 3) {
if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this);
mediaDelegate.didClickedImage(this);
}
}
}
@ -467,6 +485,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
currentNameString = null;
infoLayout = null;
nameLayout = null;
updateSecretTimeText();
}
if (messageObject.type == 9) {
@ -549,6 +568,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
w = timeWidthTotal;
}
if (currentMessageObject.isSecretPhoto()) {
if (AndroidUtilities.isTablet()) {
w = h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f);
} else {
w = h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f);
}
}
photoWidth = w;
photoHeight = h;
backgroundWidth = w + AndroidUtilities.dp(12);
@ -589,6 +616,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
photoImage.setImageBitmap(messageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable);
}
}
photoImage.setForcePreview(messageObject.isSecretPhoto());
invalidate();
}
@ -754,6 +782,25 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
buttonX = (int)(x + (photoWidth - size) / 2.0f);
buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f);
progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(47), buttonY + AndroidUtilities.dp(47));
deleteProgressRect.set(buttonX + AndroidUtilities.dp(3), buttonY + AndroidUtilities.dp(3), buttonX + AndroidUtilities.dp(45), buttonY + AndroidUtilities.dp(45));
}
private void updateSecretTimeText() {
if (currentMessageObject == null || currentMessageObject.isOut()) {
return;
}
String str = currentMessageObject.getSecretTimeString();
if (str == null) {
return;
}
if (currentInfoString == null || !currentInfoString.equals(str)) {
currentInfoString = str;
infoOffset = 0;
infoWidth = (int)Math.ceil(infoPaint.measureText(currentInfoString));
CharSequence str2 = TextUtils.ellipsize(currentInfoString, infoPaint, infoWidth, TextUtils.TruncateAt.END);
infoLayout = new StaticLayout(str2, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
invalidate();
}
}
@Override
@ -766,7 +813,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
canvas.restore();
} else {
photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false);
imageDrawn = photoImage.draw(canvas, photoImage.getImageX(), photoImage.getImageY(), photoWidth, photoHeight);
imageDrawn = photoImage.draw(canvas);
drawTime = photoImage.getVisible();
}
@ -826,6 +873,29 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
currentButtonDrawable.draw(canvas);
}
if (buttonState == -1 && currentMessageObject.isSecretPhoto()) {
int drawable = 5;
if (currentMessageObject.messageOwner.destroyTime != 0) {
if (currentMessageObject.isOut()) {
drawable = 7;
} else {
drawable = 6;
}
}
setDrawableBounds(buttonStatesDrawables[drawable], buttonX, buttonY);
buttonStatesDrawables[drawable].draw(canvas);
if (!currentMessageObject.isOut() && currentMessageObject.messageOwner.destroyTime != 0) {
long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance().getTimeDifference() * 1000;
float progress = Math.max(0, (long)currentMessageObject.messageOwner.destroyTime * 1000 - msTime) / (currentMessageObject.messageOwner.ttl * 1000.0f);
canvas.drawArc(deleteProgressRect, -90, -360 * progress, true, deleteProgressPaint);
if (progress != 0) {
int offset = AndroidUtilities.dp(2);
invalidate((int)deleteProgressRect.left - offset, (int)deleteProgressRect.top - offset, (int)deleteProgressRect.right + offset * 2, (int)deleteProgressRect.bottom + offset * 2);
}
updateSecretTimeText();
}
}
if (progressVisible) {
canvas.drawArc(progressRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint);
}
@ -842,7 +912,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
infoLayout.draw(canvas);
canvas.restore();
}
} else if (infoLayout != null && (buttonState == 1 || buttonState == 0 || buttonState == 3)) {
} else if (infoLayout != null && (buttonState == 1 || buttonState == 0 || buttonState == 3 || currentMessageObject.isSecretPhoto())) {
infoPaint.setColor(0xffffffff);
setDrawableBounds(mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dpf(16.5f));
mediaBackgroundDrawable.draw(canvas);

View File

@ -43,6 +43,7 @@ public class ChatMessageCell extends ChatBaseCell {
y -= textY;
int blockNum = Math.max(0, y / currentMessageObject.blockHeight);
if (blockNum < currentMessageObject.textLayoutBlocks.size()) {
try {
MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
x -= textX - (int)Math.ceil(block.textXOffset);
y -= block.textYOffset;
@ -74,6 +75,10 @@ public class ChatMessageCell extends ChatBaseCell {
} else {
pressedLink = null;
}
} catch (Exception e) {
pressedLink = null;
FileLog.e("tmessages", e);
}
} else {
pressedLink = null;
}

View File

@ -41,7 +41,7 @@ public class ChatOrUserCell extends BaseCell {
private CharSequence currentName;
private ImageReceiver avatarImage;
private String subLabel;
private CharSequence subLabel;
private ChatOrUserCellLayout cellLayout;
private TLRPC.User user = null;
@ -112,7 +112,7 @@ public class ChatOrUserCell extends BaseCell {
}
}
public void setData(TLRPC.User u, TLRPC.Chat c, TLRPC.EncryptedChat ec, CharSequence n, String s) {
public void setData(TLRPC.User u, TLRPC.Chat c, TLRPC.EncryptedChat ec, CharSequence n, CharSequence s) {
currentName = n;
user = u;
chat = c;
@ -236,6 +236,15 @@ public class ChatOrUserCell extends BaseCell {
return;
}
if (useSeparator) {
int h = getMeasuredHeight();
if (!usePadding) {
canvas.drawLine(0, h - 1, getMeasuredWidth(), h - 1, linePaint);
} else {
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h - 1, linePaint);
}
}
if (drawAlpha != 1) {
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int)(255 * drawAlpha), Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
}
@ -263,16 +272,7 @@ public class ChatOrUserCell extends BaseCell {
canvas.restore();
}
avatarImage.draw(canvas, cellLayout.avatarLeft, cellLayout.avatarTop, AndroidUtilities.dp(50), AndroidUtilities.dp(50));
if (useSeparator) {
int h = getMeasuredHeight();
if (!usePadding) {
canvas.drawLine(0, h - 1, getMeasuredWidth(), h, linePaint);
} else {
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h, linePaint);
}
}
avatarImage.draw(canvas);
}
private class ChatOrUserCellLayout {
@ -381,7 +381,7 @@ public class ChatOrUserCell extends BaseCell {
onlineLeft = usePadding ? AndroidUtilities.dp(11) : 0;
}
String onlineString = "";
CharSequence onlineString = "";
TextPaint currentOnlinePaint = offlinePaint;
if (subLabel != null) {

View File

@ -10,6 +10,7 @@ package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.Layout;
@ -48,6 +49,8 @@ public class DialogCell extends BaseCell {
private static Drawable groupDrawable;
private static Drawable broadcastDrawable;
private static Paint linePaint;
private TLRPC.TL_dialog currentDialog;
private ImageReceiver avatarImage;
@ -57,6 +60,8 @@ public class DialogCell extends BaseCell {
private TLRPC.EncryptedChat encryptedChat = null;
private CharSequence lastPrintString = null;
public boolean useSeparator = false;
private void init() {
if (namePaint == null) {
namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
@ -85,6 +90,11 @@ public class DialogCell extends BaseCell {
messagePaint.setColor(0xff808080);
}
if (linePaint == null) {
linePaint = new Paint();
linePaint.setColor(0xffdcdcdc);
}
if (messagePrintingPaint == null) {
messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
messagePrintingPaint.setTextSize(AndroidUtilities.dp(16));
@ -340,7 +350,16 @@ public class DialogCell extends BaseCell {
canvas.restore();
}
avatarImage.draw(canvas, cellLayout.avatarLeft, cellLayout.avatarTop, AndroidUtilities.dp(54), AndroidUtilities.dp(54));
avatarImage.draw(canvas);
if (useSeparator) {
int h = getMeasuredHeight();
if (AndroidUtilities.isTablet()) {
canvas.drawLine(0, h - 1, getMeasuredWidth(), h - 1, linePaint);
} else {
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h - 1, linePaint);
}
}
}
private class DialogCellLayout {

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.AvatarUpdater;
import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.Collections;
@ -476,6 +477,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
args.putBoolean("destroyAfterSelect", true);
args.putBoolean("usersAsSections", true);
args.putBoolean("returnAsResult", true);
//args.putBoolean("allowUsernameSearch", false);
if (chat_id > 0) {
args.putString("selectAlertString", LocaleController.getString("AddToTheGroup", R.string.AddToTheGroup));
}
@ -646,21 +648,19 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
return view;
} else if (type == 1) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
view = new SettingsSectionLayout(mContext);
}
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == settingsSectionRow) {
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
} else if (i == sharedMediaSectionRow) {
textView.setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
((SettingsSectionLayout) view).setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
} else if (i == membersSectionRow) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id);
int count = chat.participants_count;
if (info != null) {
count = info.participants.size();
}
textView.setText(LocaleController.formatPluralString("Members", count).toUpperCase());
((SettingsSectionLayout) view).setText(LocaleController.formatPluralString("Members", count).toUpperCase());
}
} else if (type == 2) {
if (view == null) {

View File

@ -11,6 +11,9 @@ package org.telegram.ui;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@ -18,6 +21,7 @@ import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
@ -26,6 +30,7 @@ import org.telegram.messenger.TLRPC;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
public class ChatProfileChangeNameActivity extends BaseFragment {
private EditText firstNameField;
@ -71,16 +76,27 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
fragmentView = inflater.inflate(R.layout.chat_profile_change_name_layout, container, false);
TLRPC.Chat currentChat = MessagesController.getInstance().getChat(chat_id);
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field);
if (chat_id > 0) {
firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName));
} else {
firstNameField.setHint(LocaleController.getString("EnterListName", R.string.EnterListName));
}
fragmentView = new LinearLayout(inflater.getContext());
fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
SettingsSectionLayout settingsSectionLayout = new SettingsSectionLayout(inflater.getContext());
((LinearLayout) fragmentView).addView(settingsSectionLayout);
firstNameField = new EditText(inflater.getContext());
firstNameField.setText(currentChat.title);
firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
firstNameField.setHintTextColor(0xffa3a3a3);
firstNameField.setTextColor(0xff000000);
firstNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
firstNameField.setMaxLines(3);
firstNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
firstNameField.setImeOptions(EditorInfo.IME_ACTION_DONE);
AndroidUtilities.clearCursorDrawable(firstNameField);
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
@ -91,15 +107,25 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
return false;
}
});
firstNameField.setText(currentChat.title);
firstNameField.setSelection(firstNameField.length());
TextView headerLabel = (TextView)fragmentView.findViewById(R.id.settings_section_text);
if (chat_id > 0) {
headerLabel.setText(LocaleController.getString("EnterGroupNameTitle", R.string.EnterGroupNameTitle));
} else {
headerLabel.setText(LocaleController.getString("EnterListName", R.string.EnterListName).toUpperCase());
if (LocaleController.isRTL) {
firstNameField.setGravity(Gravity.RIGHT);
}
((LinearLayout) fragmentView).addView(firstNameField);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)firstNameField.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(15);
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
firstNameField.setLayoutParams(layoutParams);
if (chat_id > 0) {
settingsSectionLayout.setText(LocaleController.getString("EnterGroupNameTitle", R.string.EnterGroupNameTitle));
firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName));
} else {
settingsSectionLayout.setText(LocaleController.getString("EnterListName", R.string.EnterListName).toUpperCase());
firstNameField.setHint(LocaleController.getString("EnterListName", R.string.EnterListName));
}
firstNameField.setSelection(firstNameField.length());
} else {
ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) {

View File

@ -30,6 +30,7 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.android.MessagesStorage;
import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.ConnectionsManager;
@ -72,6 +73,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
private String inviteText;
private boolean updatingInviteText = false;
private boolean allowUsernameSearch = true;
private ContactsActivityDelegate delegate;
public static interface ContactsActivityDelegate {
@ -91,11 +93,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatCreated);
if (arguments != null) {
onlyUsers = getArguments().getBoolean("onlyUsers", false);
destroyAfterSelect = getArguments().getBoolean("destroyAfterSelect", false);
usersAsSections = getArguments().getBoolean("usersAsSections", false);
returnAsResult = getArguments().getBoolean("returnAsResult", false);
createSecretChat = getArguments().getBoolean("createSecretChat", false);
destroyAfterSelect = arguments.getBoolean("destroyAfterSelect", false);
usersAsSections = arguments.getBoolean("usersAsSections", false);
returnAsResult = arguments.getBoolean("returnAsResult", false);
createSecretChat = arguments.getBoolean("createSecretChat", false);
selectAlertString = arguments.getString("selectAlertString");
allowUsernameSearch = arguments.getBoolean("allowUsernameSearch", true);
}
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
@ -199,7 +202,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
emptyTextView = (TextView)fragmentView.findViewById(R.id.searchEmptyView);
emptyTextView.setText(LocaleController.getString("NoContacts", R.string.NoContacts));
searchListViewAdapter = new ContactsActivitySearchAdapter(getParentActivity(), ignoreUsers);
searchListViewAdapter = new ContactsActivitySearchAdapter(getParentActivity(), ignoreUsers, allowUsernameSearch);
listView = (PinnedHeaderListView)fragmentView.findViewById(R.id.listView);
listView.setEmptyView(emptyTextView);
@ -221,6 +224,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
if (user == null || user.id == UserConfig.getClientUserId()) {
return;
}
if (searchListViewAdapter.isGlobalSearch(i)) {
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(user);
MessagesController.getInstance().putUsers(users, false);
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
}
if (returnAsResult) {
if (ignoreUsers != null && ignoreUsers.containsKey(user.id)) {
return;

View File

@ -31,6 +31,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.io.BufferedReader;
import java.io.InputStream;
@ -484,12 +485,10 @@ public class CountrySelectActivity extends BaseFragment {
@Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView = new SettingsSectionLayout(mContext);
convertView.setBackgroundColor(0xfffafafa);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
textView.setText(sortedCountries.get(section).toUpperCase());
((SettingsSectionLayout) convertView).setText(sortedCountries.get(section).toUpperCase());
return convertView;
}
}

View File

@ -51,6 +51,7 @@ import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.HashMap;
@ -597,15 +598,13 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
@Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView = new SettingsSectionLayout(mContext);
convertView.setBackgroundColor(0xffffffff);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
if (searching && searchWas) {
textView.setText(LocaleController.getString("AllContacts", R.string.AllContacts));
((SettingsSectionLayout) convertView).setText(LocaleController.getString("AllContacts", R.string.AllContacts));
} else {
textView.setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
}
return convertView;
}

View File

@ -38,6 +38,7 @@ import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
@ -81,11 +82,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
if (!usersToLoad.isEmpty()) {
final Semaphore semaphore = new Semaphore(0);
final ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
final boolean[] error = new boolean[1];
MessagesStorage.getInstance().storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad, error));
users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad));
semaphore.release();
}
});
@ -94,7 +94,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
} catch (Exception e) {
FileLog.e("tmessages", e);
}
if (error[0]) {
if (usersToLoad.size() != users.size()) {
return false;
}
if (!users.isEmpty()) {
@ -420,12 +420,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
@Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView = new SettingsSectionLayout(mContext);
convertView.setBackgroundColor(0xffffffff);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
textView.setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
((SettingsSectionLayout) convertView).setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
return convertView;
}
}

View File

@ -661,17 +661,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
actionBarLayout.presentFragment(fragment, false, true, true);
}
Bundle args2 = new Bundle();
args2.putString("videoPath", videoPath);
VideoEditorActivity fragment2 = new VideoEditorActivity(args2);
fragment2.setDelegate(fragment);
presentFragment(fragment2, true, true);
if (!AndroidUtilities.isTablet()) {
actionBarLayout.addFragmentToStack(fragment, actionBarLayout.fragmentsStack.size() - 1);
}
if (!fragment.openVideoEditor(videoPath, true)) {
if (!AndroidUtilities.isTablet()) {
messageFragment.finishFragment(true);
}
}
} else {
actionBarLayout.presentFragment(fragment, true);
fragment.processSendingVideo(videoPath, 0, 0, 0, 0, null);
SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id);
}
} else {
actionBarLayout.presentFragment(fragment, true);
@ -679,10 +680,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
fragment.processSendingText(sendingText);
}
if (photoPathsArray != null) {
fragment.processSendingPhotos(null, photoPathsArray);
SendMessagesHelper.prepareSendingPhotos(null, photoPathsArray, dialog_id);
}
if (documentsPathsArray != null) {
fragment.processSendingDocuments(documentsPathsArray, documentsOriginalPathsArray);
SendMessagesHelper.prepareSendingDocuments(documentsPathsArray, documentsOriginalPathsArray, dialog_id);
}
if (contactsToSend != null && !contactsToSend.isEmpty()) {
for (TLRPC.User user : contactsToSend) {
@ -786,6 +787,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
public void fixLayout() {
if (AndroidUtilities.isTablet()) {
if (actionBarLayout == null) {
return;
}
actionBarLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
@ -836,6 +840,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
@Override
protected void onDestroy() {
PhotoViewer.getInstance().destroyPhotoViewer();
SecretPhotoViewer.getInstance().destroyPhotoViewer();
super.onDestroy();
onFinish();
}
@ -1190,7 +1195,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
buttonLayoutTablet.setVisibility(View.VISIBLE);
backgroundTablet.setVisibility(View.VISIBLE);
}
} else if (layout == layersActionBarLayout && actionBarLayout.fragmentsStack.isEmpty()) {
} else if (layout == layersActionBarLayout && actionBarLayout.fragmentsStack.isEmpty() && layersActionBarLayout.fragmentsStack.size() == 1) {
onFinish();
finish();
return false;

View File

@ -26,7 +26,6 @@ import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.BaseFragment;
@ -55,7 +54,14 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
v.onDestroyActivity();
}
}
Utilities.HideProgressDialog(getParentActivity());
if (progressDialog != null) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
progressDialog = null;
}
}
@Override
@ -255,6 +261,7 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
} catch (Exception e) {
FileLog.e("tmessages", e);
}
progressDialog = null;
}
public void setPage(int page, boolean animated, Bundle params, boolean back) {

View File

@ -94,7 +94,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
@Override
public void onItemClick(int id) {
if (id == -1) {
if (Build.VERSION.SDK_INT < 11) {
if (Build.VERSION.SDK_INT < 11 && listView != null) {
listView.setAdapter(null);
listView = null;
listAdapter = null;

View File

@ -12,6 +12,7 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -35,13 +36,14 @@ import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Adapters.BaseFragmentAdapter;
import org.telegram.ui.Adapters.BaseContactsSearchAdapter;
import org.telegram.ui.Cells.ChatOrUserCell;
import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
import java.util.Timer;
@ -64,10 +66,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
private int activityToken = (int)(Utilities.random.nextDouble() * Integer.MAX_VALUE);
private long selectedDialog;
private Timer searchTimer;
public ArrayList<TLObject> searchResult;
public ArrayList<CharSequence> searchResultNames;
private MessagesActivityDelegate delegate;
private long openedDialogId = 0;
@ -144,7 +142,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override
public void onSearchCollapse() {
searchDialogs(null);
searching = false;
searchWas = false;
if (messagesListView != null) {
@ -152,14 +149,16 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
searchEmptyView.setVisibility(View.GONE);
}
if (messagesListViewAdapter != null) {
messagesListViewAdapter.notifyDataSetChanged();
messagesListViewAdapter.searchDialogs(null);
}
}
@Override
public void onTextChanged(EditText editText) {
String text = editText.getText().toString();
searchDialogs(text);
if (messagesListViewAdapter != null) {
messagesListViewAdapter.searchDialogs(text);
}
if (text.length() != 0) {
searchWas = true;
if (messagesListViewAdapter != null) {
@ -231,10 +230,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view);
messagesListView.setAdapter(messagesListViewAdapter);
if (delegate == null && AndroidUtilities.isTablet()) {
messagesListView.setDivider(inflater.getContext().getResources().getDrawable(R.drawable.messages_list_divider2));
messagesListView.setDividerHeight(1);
}
progressView = fragmentView.findViewById(R.id.progressLayout);
messagesListViewAdapter.notifyDataSetChanged();
@ -277,14 +272,22 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
messagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
long dialog_id = 0;
if (searching && searchWas) {
if (i >= searchResult.size()) {
if (messagesListViewAdapter == null) {
return;
}
TLObject obj = searchResult.get(i);
TLObject obj = messagesListViewAdapter.getItem(i);
if (obj == null) {
return;
}
long dialog_id = 0;
if (obj instanceof TLRPC.User) {
dialog_id = ((TLRPC.User) obj).id;
if (messagesListViewAdapter.isGlobalSearch(i)) {
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add((TLRPC.User)obj);
MessagesController.getInstance().putUsers(users, false);
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
}
} else if (obj instanceof TLRPC.Chat) {
if (((TLRPC.Chat) obj).id > 0) {
dialog_id = -((TLRPC.Chat) obj).id;
@ -293,22 +296,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
}
} else if (obj instanceof TLRPC.EncryptedChat) {
dialog_id = ((long)((TLRPC.EncryptedChat) obj).id) << 32;
} else if (obj instanceof TLRPC.TL_dialog) {
dialog_id = ((TLRPC.TL_dialog) obj).id;
}
} else {
if (serverOnly) {
if (i >= MessagesController.getInstance().dialogsServerOnly.size()) {
return;
}
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogsServerOnly.get(i);
dialog_id = dialog.id;
} else {
if (i >= MessagesController.getInstance().dialogs.size()) {
return;
}
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
dialog_id = dialog.id;
}
}
if (onlySelect) {
didSelectResult(dialog_id, true, false);
} else {
@ -497,7 +488,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
} else if (id == NotificationCenter.reloadSearchResults) {
int token = (Integer)args[0];
if (token == activityToken) {
updateSearchResults((ArrayList<TLObject>)args[1], (ArrayList<CharSequence>)args[2], (ArrayList<TLRPC.User>)args[3]);
messagesListViewAdapter.updateSearchResults((ArrayList<TLObject>) args[1], (ArrayList<CharSequence>) args[2], (ArrayList<TLRPC.User>) args[3]);
}
} else if (id == NotificationCenter.appDidLogout) {
dialogsLoaded = false;
@ -624,6 +615,17 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
}
}
private class MessagesAdapter extends BaseContactsSearchAdapter {
private Context mContext;
private Timer searchTimer;
private ArrayList<TLObject> searchResult = new ArrayList<TLObject>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<CharSequence>();
public MessagesAdapter(Context context) {
mContext = context;
}
public void updateSearchResults(final ArrayList<TLObject> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> encUsers) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
@ -652,10 +654,25 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
});
}
public boolean isGlobalSearch(int i) {
if (searching && searchWas) {
int localCount = searchResult.size();
int globalCount = globalSearch.size();
if (i >= 0 && i < localCount) {
return false;
} else if (i > localCount && i <= globalCount + localCount) {
return true;
}
}
return false;
}
public void searchDialogs(final String query) {
if (query == null) {
searchResult = null;
searchResultNames = null;
searchResult.clear();
searchResultNames.clear();
queryServerSearch(null);
notifyDataSetChanged();
} else {
try {
if (searchTimer != null) {
@ -675,35 +692,36 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
FileLog.e("tmessages", e);
}
MessagesStorage.getInstance().searchDialogs(activityToken, query, !serverOnly);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
queryServerSearch(query);
}
}, 100, 300);
});
}
}, 200, 300);
}
private class MessagesAdapter extends BaseFragmentAdapter {
private Context mContext;
public MessagesAdapter(Context context) {
mContext = context;
}
@Override
public boolean areAllItemsEnabled() {
return true;
return false;
}
@Override
public boolean isEnabled(int i) {
return true;
return !(searching && searchWas) || i != searchResult.size();
}
@Override
public int getCount() {
if (searching && searchWas) {
if (searchResult == null) {
return 0;
int count = searchResult.size();
int globalCount = globalSearch.size();
if (globalCount != 0) {
count += globalCount + 1;
}
return searchResult.size();
return count;
}
int count;
if (serverOnly) {
@ -721,9 +739,29 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
}
@Override
public Object getItem(int i) {
public TLObject getItem(int i) {
if (searching && searchWas) {
int localCount = searchResult.size();
int globalCount = globalSearch.size();
if (i >= 0 && i < localCount) {
return searchResult.get(i);
} else if (i > localCount && i <= globalCount + localCount) {
return globalSearch.get(i - localCount - 1);
}
return null;
}
if (serverOnly) {
if (i < 0 || i >= MessagesController.getInstance().dialogsServerOnly.size()) {
return null;
}
return MessagesController.getInstance().dialogsServerOnly.get(i);
} else {
if (i < 0 || i >= MessagesController.getInstance().dialogs.size()) {
return null;
}
return MessagesController.getInstance().dialogs.get(i);
}
}
@Override
public long getItemId(int i) {
@ -732,22 +770,35 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override
public boolean hasStableIds() {
return false;
return true;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (searching && searchWas) {
int type = getItemViewType(i);
if (type == 3) {
if (view == null) {
view = new SettingsSectionLayout(mContext);
((SettingsSectionLayout) view).setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
view.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), 0);
}
} else if (type == 2) {
if (view == null) {
view = new ChatOrUserCell(mContext);
}
if (searching && searchWas) {
TLRPC.User user = null;
TLRPC.Chat chat = null;
TLRPC.EncryptedChat encryptedChat = null;
TLObject obj = searchResult.get(i);
((ChatOrUserCell) view).useSeparator = (i != getCount() - 1 && i != searchResult.size() - 1);
TLObject obj = getItem(i);
if (obj instanceof TLRPC.User) {
user = MessagesController.getInstance().getUser(((TLRPC.User)obj).id);
user = MessagesController.getInstance().getUser(((TLRPC.User) obj).id);
if (user == null) {
user = (TLRPC.User) obj;
}
} else if (obj instanceof TLRPC.Chat) {
chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id);
} else if (obj instanceof TLRPC.EncryptedChat) {
@ -755,24 +806,39 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
user = MessagesController.getInstance().getUser(encryptedChat.user_id);
}
((ChatOrUserCell)view).setData(user, chat, encryptedChat, searchResultNames.get(i), null);
return view;
CharSequence username = null;
CharSequence name = null;
if (i < searchResult.size()) {
name = searchResultNames.get(i);
if (name != null && user != null && user.username != null && user.username.length() > 0) {
if (name.toString().startsWith("@" + user.username)) {
username = name;
name = null;
}
int type = getItemViewType(i);
if (type == 1) {
}
} else if (i > searchResult.size() && user != null && user.username != null) {
try {
username = Html.fromHtml(String.format("<font color=\"#357aa8\">@%s</font>%s", user.username.substring(0, lastFoundUsername.length()), user.username.substring(lastFoundUsername.length())));
} catch (Exception e) {
username = user.username;
FileLog.e("tmessages", e);
}
}
((ChatOrUserCell) view).setData(user, chat, encryptedChat, name, username);
}
} else if (type == 1) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.loading_more_layout, viewGroup, false);
}
return view;
}
} else if (type == 0) {
if (view == null) {
view = new DialogCell(mContext);
}
((DialogCell) view).useSeparator = (i != getCount() - 1);
if (serverOnly) {
((DialogCell)view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
((DialogCell) view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
} else {
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
if (AndroidUtilities.isTablet()) {
@ -782,7 +848,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
view.setBackgroundColor(0);
}
}
((DialogCell)view).setDialog(dialog);
((DialogCell) view).setDialog(dialog);
}
}
return view;
@ -791,12 +858,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override
public int getItemViewType(int i) {
if (searching && searchWas) {
TLObject obj = searchResult.get(i);
if (obj instanceof TLRPC.User || obj instanceof TLRPC.EncryptedChat) {
return 2;
} else {
if (i == searchResult.size()) {
return 3;
}
return 2;
}
if (serverOnly && i == MessagesController.getInstance().dialogsServerOnly.size() || !serverOnly && i == MessagesController.getInstance().dialogs.size()) {
return 1;
@ -812,7 +877,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override
public boolean isEmpty() {
if (searching && searchWas) {
return searchResult == null || searchResult.size() == 0;
return searchResult.size() == 0 && globalSearch.isEmpty();
}
if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) {
return false;

View File

@ -279,6 +279,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
int count = listView.getChildCount();
for (int a = 0; a < count; a++) {
View view = listView.getChildAt(a);
if (view.getTag() == null) {
continue;
}
int num = (Integer)view.getTag();
if (num < 0 || num >= selectedAlbum.photos.size()) {
continue;
@ -341,7 +344,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
@Override
public void sendButtonPressed(int index) {
if (selectedPhotos.isEmpty()) {
if (index < 0 || index >= selectedAlbum.photos.size()) {
if (selectedAlbum == null || index < 0 || index >= selectedAlbum.photos.size()) {
return;
}
MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index);

View File

@ -101,6 +101,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private View pickerView;
private TextView doneButtonTextView;
private TextView doneButtonBadgeTextView;
private ImageView shareButton;
private boolean canShowBottom = true;
private boolean overlayViewVisible = true;
@ -234,7 +235,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
public int getSelectedCount();
}
private static class FrameLayoutTouchListener extends FrameLayout {
private class FrameLayoutTouchListener extends FrameLayout {
public FrameLayoutTouchListener(Context context) {
super(context);
}
@ -251,7 +252,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
}
private static class FrameLayoutDrawer extends FrameLayout {
private class FrameLayoutDrawer extends FrameLayout {
public FrameLayoutDrawer(Context context) {
super(context);
setWillNotDraw(false);
@ -595,7 +596,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
bottomLayout.setLayoutParams(layoutParams);
bottomLayout.setBackgroundColor(0x7F000000);
ImageView shareButton = new ImageView(containerView.getContext());
shareButton = new ImageView(containerView.getContext());
shareButton.setImageResource(R.drawable.ic_ab_share_white);
shareButton.setScaleType(ImageView.ScaleType.CENTER);
shareButton.setBackgroundResource(R.drawable.bar_selector_white);
@ -611,12 +612,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
return;
}
try {
int size[] = new int[1];
TLRPC.FileLocation fileLocation = getFileLocation(currentIndex, size);
if (fileLocation == null) {
return;
File f = null;
if (currentMessageObject != null) {
f = FileLoader.getPathToMessage(currentMessageObject.messageOwner);
} else if (currentFileLocation != null) {
f = FileLoader.getPathToAttach(currentFileLocation, avatarsUserId != 0);
}
File f = FileLoader.getPathToAttach(fileLocation, avatarsUserId != 0);
if (f.exists()) {
Intent intent = new Intent(Intent.ACTION_SEND);
if (f.toString().endsWith("mp4")) {
@ -654,7 +657,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (obj.isSent()) {
ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(obj.messageOwner.id);
MessagesController.getInstance().deleteMessages(arr, null, null);
ArrayList<Long> random_ids = null;
TLRPC.EncryptedChat encryptedChat = null;
if ((int)obj.getDialogId() == 0 && obj.messageOwner.random_id != 0) {
random_ids = new ArrayList<Long>();
random_ids.add(obj.messageOwner.random_id);
encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(obj.getDialogId() >> 32));
}
MessagesController.getInstance().deleteMessages(arr, random_ids, encryptedChat);
closePhoto(false);
}
} else if (!avatarsArr.isEmpty()) {
@ -1157,6 +1169,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} else {
menuItem.hideSubItem(gallery_menu_showall);
}
if ((int) currentDialogId == 0) {
menuItem.hideSubItem(gallery_menu_save);
shareButton.setVisibility(View.GONE);
} else {
menuItem.showSubItem(gallery_menu_save);
shareButton.setVisibility(View.VISIBLE);
}
setImageIndex(0, true);
} else if (fileLocation != null) {
avatarsUserId = object.user_id;
@ -1164,6 +1183,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
imagesArrLocationsSizes.add(object.size);
avatarsArr.add(new TLRPC.TL_photoEmpty());
bottomLayout.setVisibility(View.GONE);
shareButton.setVisibility(View.VISIBLE);
menuItem.hideSubItem(gallery_menu_showall);
setImageIndex(0, true);
currentUserAvatarLocation = fileLocation;
@ -1192,6 +1212,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
}
}
if ((int) currentDialogId == 0) {
menuItem.hideSubItem(gallery_menu_save);
shareButton.setVisibility(View.GONE);
} else {
menuItem.showSubItem(gallery_menu_save);
shareButton.setVisibility(View.VISIBLE);
}
opennedFromMedia = true;
setImageIndex(index, true);
} else if (photos != null) {
@ -1201,6 +1228,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
setImageIndex(index, true);
pickerView.setVisibility(View.VISIBLE);
bottomLayout.setVisibility(View.GONE);
shareButton.setVisibility(View.VISIBLE);
canShowBottom = false;
updateSelectedCount();
}
@ -2138,7 +2166,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float ai = -1;
if (System.currentTimeMillis() - animationStartTime < animationDuration) {
ai = interpolator.getInterpolation((float)(System.currentTimeMillis() - animationStartTime) / animationDuration);
if (ai >= 0.95) {
if (ai >= 0.95f) {
ai = -1;
}
}
@ -2219,7 +2247,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
int height = (int) (bitmapHeight * scale);
centerImage.setImageCoords(-width / 2, -height / 2, width, height);
centerImage.draw(canvas, -width / 2, -height / 2, width, height);
centerImage.draw(canvas);
}
if (scale >= 1.0f) {
@ -2250,7 +2278,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
int height = (int) (bitmapHeight * scale);
sideImage.setImageCoords(-width / 2, -height / 2, width, height);
sideImage.draw(canvas, -width / 2, -height / 2, width, height);
sideImage.draw(canvas);
}
} else {
changingPage = false;

View File

@ -0,0 +1,372 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ImageLoader;
import org.telegram.android.ImageReceiver;
import org.telegram.android.MessageObject;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import java.io.File;
import java.util.ArrayList;
public class SecretPhotoViewer implements NotificationCenter.NotificationCenterDelegate {
private class FrameLayoutDrawer extends FrameLayout {
public FrameLayoutDrawer(Context context) {
super(context);
setWillNotDraw(false);
}
@Override
protected void onDraw(Canvas canvas) {
getInstance().onDraw(canvas);
}
}
private class FrameLayoutTouchListener extends FrameLayout {
public FrameLayoutTouchListener(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
FileLog.e("tmessages", event.toString());
return super.onTouchEvent(event);
}
}
private class SecretDeleteTimer extends FrameLayout {
private String currentInfoString;
private int infoWidth;
private TextPaint infoPaint = null;
private StaticLayout infoLayout = null;
private Paint deleteProgressPaint;
private RectF deleteProgressRect = new RectF();
private Drawable drawable = null;
public SecretDeleteTimer(Context context) {
super(context);
setWillNotDraw(false);
infoPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
infoPaint.setTextSize(AndroidUtilities.dp(15));
infoPaint.setColor(0xffffffff);
deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
deleteProgressPaint.setColor(0xffe6e6e6);
drawable = getResources().getDrawable(R.drawable.circle1);
}
private void updateSecretTimeText() {
if (currentMessageObject == null) {
return;
}
String str = currentMessageObject.getSecretTimeString();
if (str == null) {
return;
}
if (currentInfoString == null || !currentInfoString.equals(str)) {
currentInfoString = str;
infoWidth = (int)Math.ceil(infoPaint.measureText(currentInfoString));
CharSequence str2 = TextUtils.ellipsize(currentInfoString, infoPaint, infoWidth, TextUtils.TruncateAt.END);
infoLayout = new StaticLayout(str2, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
invalidate();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
deleteProgressRect.set(getMeasuredWidth() - AndroidUtilities.dp(30), AndroidUtilities.dp(2), getMeasuredWidth() - AndroidUtilities.dp(2), AndroidUtilities.dp(30));
}
@Override
protected void onDraw(Canvas canvas) {
if (currentMessageObject == null || currentMessageObject.messageOwner.destroyTime == 0) {
return;
}
if (drawable != null) {
drawable.setBounds(getMeasuredWidth() - AndroidUtilities.dp(32), 0, getMeasuredWidth(), AndroidUtilities.dp(32));
drawable.draw(canvas);
}
long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance().getTimeDifference() * 1000;
float progress = Math.max(0, (long)currentMessageObject.messageOwner.destroyTime * 1000 - msTime) / (currentMessageObject.messageOwner.ttl * 1000.0f);
canvas.drawArc(deleteProgressRect, -90, -360 * progress, true, deleteProgressPaint);
if (progress != 0) {
int offset = AndroidUtilities.dp(2);
invalidate((int)deleteProgressRect.left - offset, (int)deleteProgressRect.top - offset, (int)deleteProgressRect.right + offset * 2, (int)deleteProgressRect.bottom + offset * 2);
}
updateSecretTimeText();
if (infoLayout != null) {
canvas.save();
canvas.translate(getMeasuredWidth() - AndroidUtilities.dp(38) - infoWidth, AndroidUtilities.dp(7));
infoLayout.draw(canvas);
canvas.restore();
}
}
}
private Activity parentActivity;
private WindowManager.LayoutParams windowLayoutParams;
private FrameLayoutTouchListener windowView;
private FrameLayoutDrawer containerView;
private ImageReceiver centerImage = new ImageReceiver();
private SecretDeleteTimer secretDeleteTimer;
private boolean isVisible = false;
private MessageObject currentMessageObject = null;
private static volatile SecretPhotoViewer Instance = null;
public static SecretPhotoViewer getInstance() {
SecretPhotoViewer localInstance = Instance;
if (localInstance == null) {
synchronized (PhotoViewer.class) {
localInstance = Instance;
if (localInstance == null) {
Instance = localInstance = new SecretPhotoViewer();
}
}
}
return localInstance;
}
@SuppressWarnings("unchecked")
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.messagesDeleted) {
if (currentMessageObject == null) {
return;
}
ArrayList<Integer> markAsDeletedMessages = (ArrayList<Integer>)args[0];
if (markAsDeletedMessages.contains(currentMessageObject.messageOwner.id)) {
closePhoto();
}
} else if (id == NotificationCenter.didCreatedNewDeleteTask) {
if (currentMessageObject == null || secretDeleteTimer == null) {
return;
}
SparseArray<ArrayList<Integer>> mids = (SparseArray<ArrayList<Integer>>)args[0];
for(int i = 0; i < mids.size(); i++) {
int key = mids.keyAt(i);
ArrayList<Integer> arr = mids.get(key);
for (Integer mid : arr) {
if (currentMessageObject.messageOwner.id == mid) {
currentMessageObject.messageOwner.destroyTime = key;
secretDeleteTimer.invalidate();
return;
}
}
}
}
}
public void setParentActivity(Activity activity) {
if (parentActivity == activity) {
return;
}
parentActivity = activity;
windowView = new FrameLayoutTouchListener(activity);
windowView.setBackgroundColor(0xff000000);
windowView.setFocusable(true);
windowView.setFocusableInTouchMode(true);
containerView = new FrameLayoutDrawer(activity);
containerView.setFocusable(false);
windowView.addView(containerView);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)containerView.getLayoutParams();
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
containerView.setLayoutParams(layoutParams);
containerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_POINTER_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
closePhoto();
}
return true;
}
});
secretDeleteTimer = new SecretDeleteTimer(activity);
containerView.addView(secretDeleteTimer);
layoutParams = (FrameLayout.LayoutParams)secretDeleteTimer.getLayoutParams();
layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
layoutParams.width = AndroidUtilities.dp(100);
layoutParams.height = AndroidUtilities.dp(32);
layoutParams.rightMargin = AndroidUtilities.dp(19);
layoutParams.topMargin = AndroidUtilities.dp(19);
secretDeleteTimer.setLayoutParams(layoutParams);
windowLayoutParams = new WindowManager.LayoutParams();
windowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
windowLayoutParams.format = PixelFormat.TRANSLUCENT;
windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
windowLayoutParams.gravity = Gravity.TOP;
windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
centerImage.setParentView(containerView);
}
public void openPhoto(MessageObject messageObject) {
if (parentActivity == null || messageObject == null || messageObject.messageOwner.media == null || messageObject.messageOwner.media.photo == null) {
return;
}
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.didCreatedNewDeleteTask);
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(messageObject.messageOwner.media.photo.sizes, AndroidUtilities.getPhotoSize());
int size = sizeFull.size;
if (size == 0) {
size = -1;
}
BitmapDrawable drawable = ImageLoader.getInstance().getImageFromMemory(sizeFull.location, null, null, null);
if (drawable == null) {
File file = FileLoader.getPathToAttach(sizeFull);
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
} catch (Throwable e) {
ImageLoader.getInstance().clearMemory();
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
if (bitmap != null) {
drawable = new BitmapDrawable(bitmap);
ImageLoader.getInstance().putImageToCache(drawable, sizeFull.location.volume_id + "_" + sizeFull.location.local_id);
}
}
if (drawable != null) {
centerImage.setImageBitmap(drawable);
} else {
centerImage.setImage(sizeFull.location, null, null, size, false);
}
currentMessageObject = messageObject;
AndroidUtilities.lockOrientation(parentActivity);
try {
if (windowView.getParent() != null) {
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(windowView);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.addView(windowView, windowLayoutParams);
secretDeleteTimer.invalidate();
isVisible = true;
}
public boolean isVisible() {
return isVisible;
}
public void closePhoto() {
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask);
if (parentActivity == null) {
return;
}
currentMessageObject = null;
isVisible = false;
AndroidUtilities.unlockOrientation(parentActivity);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
centerImage.setImageBitmap((Bitmap)null);
}
});
try {
if (windowView.getParent() != null) {
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(windowView);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void destroyPhotoViewer() {
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask);
isVisible = false;
currentMessageObject = null;
if (parentActivity == null || windowView == null) {
return;
}
try {
if (windowView.getParent() != null) {
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.removeViewImmediate(windowView);
}
windowView = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
Instance = null;
}
private void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(containerView.getWidth() / 2, containerView.getHeight() / 2);
Bitmap bitmap = centerImage.getBitmap();
if (bitmap != null) {
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();
float scaleX = (float) containerView.getWidth() / (float) bitmapWidth;
float scaleY = (float) containerView.getHeight() / (float) bitmapHeight;
float scale = scaleX > scaleY ? scaleY : scaleX;
int width = (int) (bitmapWidth * scale);
int height = (int) (bitmapHeight * scale);
centerImage.setImageCoords(-width / 2, -height / 2, width, height);
centerImage.draw(canvas);
}
canvas.restore();
}
}

View File

@ -59,6 +59,8 @@ import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.AvatarUpdater;
import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.NumberPicker;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.io.File;
import java.util.ArrayList;
@ -72,6 +74,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
private int profileRow;
private int numberSectionRow;
private int numberRow;
private int usernameRow;
private int settingsSectionRow;
private int textSizeRow;
private int enableAnimationsRow;
@ -178,6 +181,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
profileRow = rowCount++;
numberSectionRow = rowCount++;
numberRow = rowCount++;
usernameRow = rowCount++;
settingsSectionRow = rowCount++;
enableAnimationsRow = rowCount++;
languageRow = rowCount++;
@ -207,12 +211,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
logoutRow = rowCount++;
versionRow = rowCount++;
MessagesController.getInstance().loadFullUser(UserConfig.getCurrentUser(), classGuid);
return true;
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
MessagesController.getInstance().cancelLoadFullUser(UserConfig.getClientUserId());
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces);
avatarUpdater.clear();
}
@ -245,39 +252,24 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("TextSize", R.string.TextSize));
builder.setItems(new CharSequence[] {
String.format("%d", 12),
String.format("%d", 13),
String.format("%d", 14),
String.format("%d", 15),
String.format("%d", 16),
String.format("%d", 17),
String.format("%d", 18),
String.format("%d", 19),
String.format("%d", 20),
String.format("%d", 21),
String.format("%d", 22),
String.format("%d", 23),
String.format("%d", 24),
String.format("%d", 25),
String.format("%d", 26),
String.format("%d", 27),
String.format("%d", 28),
String.format("%d", 29),
String.format("%d", 30)}, new DialogInterface.OnClickListener() {
final NumberPicker numberPicker = new NumberPicker(getParentActivity());
numberPicker.setMinValue(12);
numberPicker.setMaxValue(30);
numberPicker.setValue(MessagesController.getInstance().fontSize);
builder.setView(numberPicker);
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("fons_size", 12 + which);
MessagesController.getInstance().fontSize = 12 + which;
editor.putInt("fons_size", numberPicker.getValue());
MessagesController.getInstance().fontSize = numberPicker.getValue();
editor.commit();
if (listView != null) {
listView.invalidateViews();
}
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showAlertDialog(builder);
} else if (i == enableAnimationsRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
@ -491,6 +483,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
});
builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null);
showAlertDialog(builder);
} else if (i == usernameRow) {
presentFragment(new SettingsChangeUsernameActivity());
}
}
});
@ -723,7 +717,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
public boolean isEnabled(int i) {
return i == textSizeRow || i == enableAnimationsRow || i == blockedRow || i == notificationRow || i == backgroundRow ||
i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == terminateSessionsRow || i == wifiDownloadRow ||
i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow ||
i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow || i == usernameRow ||
i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow;
}
@ -838,22 +832,20 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
return view;
} else if (type == 1) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
view = new SettingsSectionLayout(mContext);
}
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == numberSectionRow) {
textView.setText(LocaleController.getString("YourPhoneNumber", R.string.YourPhoneNumber));
((SettingsSectionLayout) view).setText(LocaleController.getString("Info", R.string.Info));
} else if (i == settingsSectionRow) {
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
} else if (i == supportSectionRow) {
textView.setText(LocaleController.getString("Support", R.string.Support));
((SettingsSectionLayout) view).setText(LocaleController.getString("Support", R.string.Support));
} else if (i == messagesSectionRow) {
textView.setText(LocaleController.getString("MessagesSettings", R.string.MessagesSettings));
((SettingsSectionLayout) view).setText(LocaleController.getString("MessagesSettings", R.string.MessagesSettings));
} else if (i == mediaDownloadSection) {
textView.setText(LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload));
((SettingsSectionLayout) view).setText(LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload));
} else if (i == contactsSectionRow) {
textView.setText(LocaleController.getString("Contacts", R.string.Contacts).toUpperCase());
((SettingsSectionLayout) view).setText(LocaleController.getString("Contacts", R.string.Contacts).toUpperCase());
}
} else if (type == 2) {
if (view == null) {
@ -862,15 +854,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
}
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
View divider = view.findViewById(R.id.settings_row_divider);
if (i == numberRow) {
TLRPC.User user = UserConfig.getCurrentUser();
if (user != null && user.phone != null && user.phone.length() != 0) {
textView.setText(PhoneFormat.getInstance().format("+" + user.phone));
} else {
textView.setText("Unknown");
}
divider.setVisibility(View.INVISIBLE);
} else if (i == notificationRow) {
if (i == notificationRow) {
textView.setText(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds));
divider.setVisibility(View.VISIBLE);
} else if (i == blockedRow) {
@ -980,7 +964,16 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail);
View divider = view.findViewById(R.id.settings_row_divider);
if (i == textSizeRow) {
if (i == numberRow) {
TLRPC.User user = UserConfig.getCurrentUser();
textView.setText(LocaleController.getString("Phone", R.string.Phone));
if (user != null && user.phone != null && user.phone.length() != 0) {
detailTextView.setText(PhoneFormat.getInstance().format("+" + user.phone));
} else {
detailTextView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
}
divider.setVisibility(View.VISIBLE);
} else if (i == textSizeRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
detailTextView.setText(String.format("%d", size));
@ -1002,6 +995,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
} else if (sort == 2) {
detailTextView.setText(LocaleController.getString("LastName", R.string.SortLastName));
}
} else if (i == usernameRow) {
TLRPC.User user = UserConfig.getCurrentUser();
textView.setText(LocaleController.getString("Username", R.string.Username));
if (user != null && user.username != null && user.username.length() != 0) {
detailTextView.setText("@" + user.username);
} else {
detailTextView.setText(LocaleController.getString("UsernameEmpty", R.string.UsernameEmpty));
}
divider.setVisibility(View.INVISIBLE);
}
} else if (type == 6) {
if (view == null) {
@ -1075,11 +1077,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
return 0;
} else if (i == numberSectionRow || i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) {
return 1;
} else if (i == textSizeRow || i == languageRow || i == contactsSortRow) {
} else if (i == textSizeRow || i == languageRow || i == contactsSortRow || i == numberRow || i == usernameRow) {
return 5;
} else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow) {
return 3;
} else if (i == numberRow || i == notificationRow || i == blockedRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == terminateSessionsRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow) {
} else if (i == notificationRow || i == blockedRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == terminateSessionsRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow) {
return 2;
} else if (i == logoutRow) {
return 4;

View File

@ -249,7 +249,7 @@ public class SettingsBlockedUsersActivity extends BaseFragment implements Notifi
((ChatOrUserCell)view).useSeparator = true;
}
TLRPC.User user = MessagesController.getInstance().getUser(MessagesController.getInstance().blockedUsers.get(i));
((ChatOrUserCell)view).setData(user, null, null, null, user.phone != null && user.phone.length() != 0 ? PhoneFormat.getInstance().format("+" + user.phone) : "Unknown");
((ChatOrUserCell)view).setData(user, null, null, null, user.phone != null && user.phone.length() != 0 ? PhoneFormat.getInstance().format("+" + user.phone) : LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
} else if (type == 1) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View File

@ -10,6 +10,9 @@ package org.telegram.ui;
import android.app.Activity;
import android.content.SharedPreferences;
import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@ -17,6 +20,7 @@ import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
@ -30,6 +34,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
public class SettingsChangeNameActivity extends BaseFragment {
private EditText firstNameField;
@ -63,14 +68,31 @@ public class SettingsChangeNameActivity extends BaseFragment {
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
fragmentView = inflater.inflate(R.layout.settings_change_name_layout, container, false);
TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
if (user == null) {
user = UserConfig.getCurrentUser();
}
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field);
fragmentView = new LinearLayout(inflater.getContext());
fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
SettingsSectionLayout settingsSectionLayout = new SettingsSectionLayout(inflater.getContext());
((LinearLayout) fragmentView).addView(settingsSectionLayout);
settingsSectionLayout.setText(LocaleController.getString("YourFirstNameAndLastName", R.string.YourFirstNameAndLastName).toUpperCase());
firstNameField = new EditText(inflater.getContext());
firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
firstNameField.setHintTextColor(0xffa3a3a3);
firstNameField.setTextColor(0xff000000);
firstNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
firstNameField.setMaxLines(1);
firstNameField.setLines(1);
firstNameField.setSingleLine(true);
firstNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT);
firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName));
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
@ -83,7 +105,25 @@ public class SettingsChangeNameActivity extends BaseFragment {
return false;
}
});
lastNameField = (EditText)fragmentView.findViewById(R.id.last_name_field);
AndroidUtilities.clearCursorDrawable(firstNameField);
((LinearLayout) fragmentView).addView(firstNameField);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)firstNameField.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(15);
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
firstNameField.setLayoutParams(layoutParams);
lastNameField = new EditText(inflater.getContext());
lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
lastNameField.setHintTextColor(0xffa3a3a3);
lastNameField.setTextColor(0xff000000);
lastNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
lastNameField.setMaxLines(1);
lastNameField.setLines(1);
lastNameField.setSingleLine(true);
lastNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
lastNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
lastNameField.setImeOptions(EditorInfo.IME_ACTION_DONE);
lastNameField.setHint(LocaleController.getString("LastName", R.string.LastName));
lastNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
@ -95,15 +135,19 @@ public class SettingsChangeNameActivity extends BaseFragment {
return false;
}
});
AndroidUtilities.clearCursorDrawable(lastNameField);
((LinearLayout) fragmentView).addView(lastNameField);
layoutParams = (LinearLayout.LayoutParams)lastNameField.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(10);
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
lastNameField.setLayoutParams(layoutParams);
if (user != null) {
firstNameField.setText(user.first_name);
firstNameField.setSelection(firstNameField.length());
lastNameField.setText(user.last_name);
}
TextView headerLabel = (TextView)fragmentView.findViewById(R.id.settings_section_text);
headerLabel.setText(LocaleController.getString("YourFirstNameAndLastName", R.string.YourFirstNameAndLastName));
} else {
ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) {
@ -125,12 +169,18 @@ public class SettingsChangeNameActivity extends BaseFragment {
}
private void saveName() {
TLRPC.TL_account_updateProfile req = new TLRPC.TL_account_updateProfile();
if (UserConfig.getCurrentUser() == null || lastNameField.getText() == null || firstNameField.getText() == null) {
TLRPC.User currentUser = UserConfig.getCurrentUser();
if (currentUser == null || lastNameField.getText() == null || firstNameField.getText() == null) {
return;
}
UserConfig.getCurrentUser().first_name = req.first_name = firstNameField.getText().toString();
UserConfig.getCurrentUser().last_name = req.last_name = lastNameField.getText().toString();
String newFirst = firstNameField.getText().toString();
String newLast = lastNameField.getText().toString();
if (currentUser.first_name != null && currentUser.first_name.equals(newFirst) && currentUser.last_name != null && currentUser.last_name.equals(newLast)) {
return;
}
TLRPC.TL_account_updateProfile req = new TLRPC.TL_account_updateProfile();
currentUser.first_name = req.first_name = newFirst;
currentUser.last_name = req.last_name = newLast;
TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
if (user != null) {
user.first_name = req.first_name;

View File

@ -0,0 +1,407 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.text.Editable;
import android.text.Html;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.android.MessagesController;
import org.telegram.android.MessagesStorage;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
public class SettingsChangeUsernameActivity extends BaseFragment {
private EditText firstNameField;
private View doneButton;
private TextView checkTextView;
private long checkReqId = 0;
private String lastCheckName = null;
private Runnable checkRunnable = null;
private boolean lastNameAvailable = false;
@Override
public View createView(LayoutInflater inflater, ViewGroup container) {
if (fragmentView == null) {
actionBarLayer.setCustomView(R.layout.settings_do_action_layout);
Button cancelButton = (Button)actionBarLayer.findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finishFragment();
}
});
doneButton = actionBarLayer.findViewById(R.id.done_button);
doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveName();
}
});
cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
if (user == null) {
user = UserConfig.getCurrentUser();
}
fragmentView = new LinearLayout(inflater.getContext());
fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
SettingsSectionLayout settingsSectionLayout = new SettingsSectionLayout(inflater.getContext());
((LinearLayout) fragmentView).addView(settingsSectionLayout);
settingsSectionLayout.setText(LocaleController.getString("Username", R.string.Username).toUpperCase());
firstNameField = new EditText(inflater.getContext());
firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
firstNameField.setHintTextColor(0xffa3a3a3);
firstNameField.setTextColor(0xff000000);
firstNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
firstNameField.setMaxLines(1);
firstNameField.setLines(1);
firstNameField.setSingleLine(true);
firstNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
firstNameField.setImeOptions(EditorInfo.IME_ACTION_DONE);
firstNameField.setHint(LocaleController.getString("UsernamePlaceholder", R.string.UsernamePlaceholder));
AndroidUtilities.clearCursorDrawable(firstNameField);
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_DONE && doneButton != null) {
doneButton.performClick();
return true;
}
return false;
}
});
((LinearLayout) fragmentView).addView(firstNameField);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)firstNameField.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(15);
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
firstNameField.setLayoutParams(layoutParams);
if (user != null && user.username != null && user.username.length() > 0) {
firstNameField.setText(user.username);
firstNameField.setSelection(firstNameField.length());
}
checkTextView = new TextView(inflater.getContext());
checkTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
checkTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0);
checkTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
((LinearLayout) fragmentView).addView(checkTextView);
layoutParams = (LinearLayout.LayoutParams)checkTextView.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(12);
layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT;
checkTextView.setLayoutParams(layoutParams);
TextView helpTextView = new TextView(inflater.getContext());
helpTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
helpTextView.setTextColor(0xff6d6d72);
helpTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0);
helpTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
helpTextView.setText(Html.fromHtml(LocaleController.getString("UsernameHelp", R.string.UsernameHelp)));
((LinearLayout) fragmentView).addView(helpTextView);
layoutParams = (LinearLayout.LayoutParams)helpTextView.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(10);
layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
layoutParams.gravity = LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT;
helpTextView.setLayoutParams(layoutParams);
firstNameField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
checkUserName(firstNameField.getText().toString(), false);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
checkTextView.setVisibility(View.GONE);
} else {
ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) {
parent.removeView(fragmentView);
}
}
return fragmentView;
}
@Override
public void onResume() {
super.onResume();
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
boolean animations = preferences.getBoolean("view_animations", true);
if (!animations) {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
}
}
private void showErrorAlert(String error) {
if (getParentActivity() == null) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
if (error.equals("USERNAME_INVALID")) {
builder.setMessage(LocaleController.getString("UsernameInvalid", R.string.UsernameInvalid));
} else if (error.equals("USERNAME_OCCUPIED")) {
builder.setMessage(LocaleController.getString("UsernameInUse", R.string.UsernameInUse));
} else if (error.equals("USERNAMES_UNAVAILABLE")) {
builder.setMessage(LocaleController.getString("FeatureUnavailable", R.string.FeatureUnavailable));
} else {
builder.setMessage(LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred));
}
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
showAlertDialog(builder);
}
private boolean checkUserName(final String name, boolean alert) {
if (name != null && name.length() > 0) {
checkTextView.setVisibility(View.VISIBLE);
} else {
checkTextView.setVisibility(View.GONE);
}
if (alert && name.length() == 0) {
return true;
}
if (checkRunnable != null) {
AndroidUtilities.CancelRunOnUIThread(checkRunnable);
checkRunnable = null;
lastCheckName = null;
if (checkReqId != 0) {
ConnectionsManager.getInstance().cancelRpc(checkReqId, true);
}
}
lastNameAvailable = false;
if (name != null) {
for (int a = 0; a < name.length(); a++) {
char ch = name.charAt(a);
if (a == 0 && ch >= '0' && ch <= '9') {
if (alert) {
showErrorAlert(LocaleController.getString("UsernameInvalidStartNumber", R.string.UsernameInvalidStartNumber));
} else {
checkTextView.setText(LocaleController.getString("UsernameInvalidStartNumber", R.string.UsernameInvalidStartNumber));
checkTextView.setTextColor(0xffcf3030);
}
return false;
}
if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_')) {
if (alert) {
showErrorAlert(LocaleController.getString("UsernameInvalid", R.string.UsernameInvalid));
} else {
checkTextView.setText(LocaleController.getString("UsernameInvalid", R.string.UsernameInvalid));
checkTextView.setTextColor(0xffcf3030);
}
return false;
}
}
}
if (name == null || name.length() < 5) {
if (alert) {
showErrorAlert(LocaleController.getString("UsernameInvalidShort", R.string.UsernameInvalidShort));
} else {
checkTextView.setText(LocaleController.getString("UsernameInvalidShort", R.string.UsernameInvalidShort));
checkTextView.setTextColor(0xffcf3030);
}
return false;
}
if (name.length() > 32) {
if (alert) {
showErrorAlert(LocaleController.getString("UsernameInvalidLong", R.string.UsernameInvalidLong));
} else {
checkTextView.setText(LocaleController.getString("UsernameInvalidLong", R.string.UsernameInvalidLong));
checkTextView.setTextColor(0xffcf3030);
}
return false;
}
if (!alert) {
String currentName = UserConfig.getCurrentUser().username;
if (currentName == null) {
currentName = "";
}
if (name.equals(currentName)) {
checkTextView.setText(LocaleController.formatString("UsernameAvailable", R.string.UsernameAvailable, name));
checkTextView.setTextColor(0xff26972c);
return true;
}
checkTextView.setText(LocaleController.getString("UsernameChecking", R.string.UsernameChecking));
checkTextView.setTextColor(0xff6d6d72);
lastCheckName = name;
checkRunnable = new Runnable() {
@Override
public void run() {
TLRPC.TL_account_checkUsername req = new TLRPC.TL_account_checkUsername();
req.username = name;
checkReqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
checkReqId = 0;
if (lastCheckName != null && lastCheckName.equals(name)) {
if (error == null && response instanceof TLRPC.TL_boolTrue) {
checkTextView.setText(LocaleController.formatString("UsernameAvailable", R.string.UsernameAvailable, name));
checkTextView.setTextColor(0xff26972c);
lastNameAvailable = true;
} else {
checkTextView.setText(LocaleController.getString("UsernameInUse", R.string.UsernameInUse));
checkTextView.setTextColor(0xffcf3030);
lastNameAvailable = false;
}
}
}
});
}
}, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
};
AndroidUtilities.RunOnUIThread(checkRunnable, 300);
}
return true;
}
private void saveName() {
if (!checkUserName(firstNameField.getText().toString(), true)) {
return;
}
TLRPC.User user = UserConfig.getCurrentUser();
if (getParentActivity() == null || user == null) {
return;
}
String currentName = user.username;
if (currentName == null) {
currentName = "";
}
String newName = firstNameField.getText().toString();
if (currentName.equals(newName)) {
finishFragment();
return;
}
final ProgressDialog progressDialog = new ProgressDialog(getParentActivity());
progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
TLRPC.TL_account_updateUsername req = new TLRPC.TL_account_updateUsername();
req.username = newName;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_NAME);
final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, final TLRPC.TL_error error) {
if (error == null) {
final TLRPC.User user = (TLRPC.User)response;
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(user);
MessagesController.getInstance().putUsers(users, false);
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
UserConfig.saveConfig(true);
finishFragment();
}
});
} else {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
showErrorAlert(error.text);
}
});
}
}
}, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ConnectionsManager.getInstance().cancelRpc(reqId, true);
try {
dialog.dismiss();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
});
progressDialog.show();
}
@Override
public void onOpenAnimationEnd() {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
}
}

View File

@ -42,6 +42,7 @@ import org.telegram.ui.Adapters.BaseFragmentAdapter;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.ColorPickerView;
import org.telegram.ui.Views.SettingsSectionLayout;
public class SettingsNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private ListView listView;
@ -541,22 +542,20 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
int type = getItemViewType(i);
if (type == 0) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
view = new SettingsSectionLayout(mContext);
}
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == messageSectionRow) {
textView.setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications));
((SettingsSectionLayout) view).setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications));
} else if (i == groupSectionRow) {
textView.setText(LocaleController.getString("GroupNotifications", R.string.GroupNotifications));
((SettingsSectionLayout) view).setText(LocaleController.getString("GroupNotifications", R.string.GroupNotifications));
} else if (i == inappSectionRow) {
textView.setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications));
((SettingsSectionLayout) view).setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications));
} else if (i == eventsSectionRow) {
textView.setText(LocaleController.getString("Events", R.string.Events));
((SettingsSectionLayout) view).setText(LocaleController.getString("Events", R.string.Events));
} else if (i == otherSectionRow) {
textView.setText(LocaleController.getString("PhoneOther", R.string.PhoneOther));
((SettingsSectionLayout) view).setText(LocaleController.getString("PhoneOther", R.string.PhoneOther));
} else if (i == resetSectionRow) {
textView.setText(LocaleController.getString("Reset", R.string.Reset));
((SettingsSectionLayout) view).setText(LocaleController.getString("Reset", R.string.Reset));
}
} if (type == 1) {
if (view == null) {

View File

@ -31,7 +31,6 @@ import org.telegram.messenger.TLRPC;
import org.telegram.android.ContactsController;
import org.telegram.messenger.FileLog;
import org.telegram.android.MessagesController;
import org.telegram.android.MessagesStorage;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.android.MessageObject;
@ -42,6 +41,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.IdenticonView;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList;
@ -64,6 +64,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
private int avatarRow;
private int phoneSectionRow;
private int phoneRow;
private int usernameRow;
private int settingsSectionRow;
private int settingsTimerRow;
private int settingsKeyRow;
@ -94,6 +95,9 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded);
userBlocked = MessagesController.getInstance().blockedUsers.contains(user_id);
MessagesController.getInstance().loadFullUser(MessagesController.getInstance().getUser(user_id), classGuid);
return true;
}
@ -106,6 +110,8 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatCreated);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatUpdated);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.blockedUsersDidLoaded);
MessagesController.getInstance().cancelLoadFullUser(user_id);
}
private void updateRowsIds() {
@ -113,6 +119,12 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
avatarRow = rowCount++;
phoneSectionRow = rowCount++;
phoneRow = rowCount++;
TLRPC.User user = MessagesController.getInstance().getUser(user_id);
if (user != null && user.username != null && user.username.length() > 0) {
usernameRow = rowCount++;
} else {
usernameRow = -1;
}
settingsSectionRow = rowCount++;
if (currentEncryptedChat instanceof TLRPC.TL_encryptedChat) {
settingsTimerRow = rowCount++;
@ -256,47 +268,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
if (getParentActivity() == null) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
builder.setItems(new CharSequence[]{
LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever),
LocaleController.getString("ShortMessageLifetime2s", R.string.ShortMessageLifetime2s),
LocaleController.getString("ShortMessageLifetime5s", R.string.ShortMessageLifetime5s),
LocaleController.getString("ShortMessageLifetime1m", R.string.ShortMessageLifetime1m),
LocaleController.getString("ShortMessageLifetime1h", R.string.ShortMessageLifetime1h),
LocaleController.getString("ShortMessageLifetime1d", R.string.ShortMessageLifetime1d),
LocaleController.getString("ShortMessageLifetime1w", R.string.ShortMessageLifetime1w)
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int oldValue = currentEncryptedChat.ttl;
if (which == 0) {
currentEncryptedChat.ttl = 0;
} else if (which == 1) {
currentEncryptedChat.ttl = 2;
} else if (which == 2) {
currentEncryptedChat.ttl = 5;
} else if (which == 3) {
currentEncryptedChat.ttl = 60;
} else if (which == 4) {
currentEncryptedChat.ttl = 60 * 60;
} else if (which == 5) {
currentEncryptedChat.ttl = 60 * 60 * 24;
} else if (which == 6) {
currentEncryptedChat.ttl = 60 * 60 * 24 * 7;
}
if (oldValue != currentEncryptedChat.ttl) {
if (listView != null) {
listView.invalidateViews();
}
SendMessagesHelper.getInstance().sendTTLMessage(currentEncryptedChat);
MessagesStorage.getInstance().updateEncryptedChat(currentEncryptedChat);
}
}
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showAlertDialog(builder);
showAlertDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat));
} else if (i == settingsNotificationsRow) {
Bundle args = new Bundle();
args.putLong("dialog_id", dialog_id == 0 ? user_id : dialog_id);
@ -318,10 +290,11 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
return fragmentView;
}
public void didReceivedNotification(int id, Object... args) {
public void didReceivedNotification(int id, final Object... args) {
if (id == NotificationCenter.updateInterfaces) {
int mask = (Integer)args[0];
if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_NAME) != 0) {
updateRowsIds();
if (listView != null) {
listView.invalidateViews();
}
@ -338,12 +311,17 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
}
} else if (id == NotificationCenter.encryptedChatCreated) {
if (creatingChat) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
TLRPC.EncryptedChat encryptedChat = (TLRPC.EncryptedChat)args[0];
Bundle args2 = new Bundle();
args2.putInt("enc_id", encryptedChat.id);
presentFragment(new ChatActivity(args2), true);
}
});
}
} else if (id == NotificationCenter.encryptedChatUpdated) {
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat)args[0];
if (currentEncryptedChat != null && chat.id == currentEncryptedChat.id) {
@ -449,6 +427,13 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
}
}
@Override
protected void onDialogDismiss() {
if (listView != null) {
listView.invalidateViews();
}
}
@Override
public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) {
if (dialog_id != 0) {
@ -555,16 +540,14 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
return view;
} else if (type == 1) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
view = new SettingsSectionLayout(mContext);
}
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == phoneSectionRow) {
textView.setText(LocaleController.getString("PHONE", R.string.PHONE));
((SettingsSectionLayout) view).setText(LocaleController.getString("Info", R.string.Info));
} else if (i == settingsSectionRow) {
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
} else if (i == sharedMediaSectionRow) {
textView.setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
((SettingsSectionLayout) view).setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
}
} else if (type == 2) {
final TLRPC.User user = MessagesController.getInstance().getUser(user_id);
@ -637,9 +620,9 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
if (user.phone != null && user.phone.length() != 0) {
textView.setText(PhoneFormat.getInstance().format("+" + user.phone));
} else {
textView.setText("Unknown");
textView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
}
divider.setVisibility(View.INVISIBLE);
divider.setVisibility(usernameRow != -1 ? View.VISIBLE : View.INVISIBLE);
detailTextView.setText(LocaleController.getString("PhoneMobile", R.string.PhoneMobile));
}
} else if (type == 3) {
@ -665,21 +648,18 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
divider.setVisibility(View.VISIBLE);
if (encryptedChat.ttl == 0) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever));
} else if (encryptedChat.ttl == 2) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime2s", R.string.ShortMessageLifetime2s));
} else if (encryptedChat.ttl == 5) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime5s", R.string.ShortMessageLifetime5s));
} else if (encryptedChat.ttl == 60) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1m", R.string.ShortMessageLifetime1m));
} else if (encryptedChat.ttl == 60 * 60) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1h", R.string.ShortMessageLifetime1h));
} else if (encryptedChat.ttl == 60 * 60 * 24) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1d", R.string.ShortMessageLifetime1d));
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1w", R.string.ShortMessageLifetime1w));
} else {
detailTextView.setText(String.format("%d", encryptedChat.ttl));
detailTextView.setText(AndroidUtilities.formatTTLString(encryptedChat.ttl));
}
} else if (i == usernameRow) {
TLRPC.User user = MessagesController.getInstance().getUser(user_id);
textView.setText(LocaleController.getString("Username", R.string.Username));
if (user != null && user.username != null && user.username.length() != 0) {
detailTextView.setText("@" + user.username);
} else {
detailTextView.setText("-");
}
divider.setVisibility(View.INVISIBLE);
}
} else if (type == 4) {
if (view == null) {
@ -716,7 +696,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
return 1;
} else if (i == phoneRow) {
return 2;
} else if (i == sharedMediaRow || i == settingsTimerRow) {
} else if (i == sharedMediaRow || i == settingsTimerRow || i == usernameRow) {
return 3;
} else if (i == settingsKeyRow) {
return 4;

View File

@ -58,6 +58,7 @@ import java.util.List;
@TargetApi(16)
public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener {
private boolean created = false;
private MediaPlayer videoPlayer = null;
private VideoTimelineView videoTimelineView = null;
private View videoContainerView = null;
@ -161,6 +162,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
@Override
public boolean onFragmentCreate() {
if (created) {
return true;
}
if (videoPath == null || !processOpenVideo()) {
return false;
}
@ -191,6 +195,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
return false;
}
created = true;
return super.onFragmentCreate();
}
@ -276,6 +282,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
});
if (Build.VERSION.SDK_INT < 18) {
try {
MediaCodecInfo codecInfo = MediaController.selectCodec(MediaController.MIME_TYPE);
if (codecInfo == null) {
compressVideo.setVisibility(View.GONE);
@ -293,6 +300,10 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
}
}
}
} catch (Exception e) {
compressVideo.setVisibility(View.GONE);
FileLog.e("tmessages", e);
}
}
TextView titleTextView = (TextView) fragmentView.findViewById(R.id.original_title);
@ -446,12 +457,18 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
}
private void onPlayComplete() {
if (playButton != null) {
playButton.setImageResource(R.drawable.video_play);
}
if (videoSeekBarView != null && videoTimelineView != null) {
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
}
try {
if (videoPlayer != null) {
if (videoTimelineView != null) {
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}

View File

@ -171,9 +171,9 @@ public class ActionBarLayer extends FrameLayout {
x = AndroidUtilities.dp(16 + leftMargin);
} else {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
x = AndroidUtilities.dp(22 + leftMargin) + (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f);
x = AndroidUtilities.dp(22 + leftMargin) + (logoImageView.getDrawable() != null ? (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f) : 0);
} else {
x = AndroidUtilities.dp(22 + leftMargin) + logoImageView.getDrawable().getIntrinsicWidth();
x = AndroidUtilities.dp(22 + leftMargin) + (logoImageView.getDrawable() != null ? logoImageView.getDrawable().getIntrinsicWidth() : 0);
}
}

View File

@ -54,7 +54,11 @@ public class BaseFragment {
if (fragmentView != null) {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
try {
parent.removeView(fragmentView);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
fragmentView = null;
}

View File

@ -91,6 +91,6 @@ public class BackupImageView extends View {
@Override
protected void onDraw(Canvas canvas) {
imageReceiver.setImageCoords(0, 0, getWidth(), getHeight());
imageReceiver.draw(canvas, 0, 0, getWidth(), getHeight());
imageReceiver.draw(canvas);
}
}

View File

@ -597,24 +597,22 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
messsageEditText.dispatchKeyEvent(new KeyEvent(0, 67));
}
public void onEmojiSelected(String paramAnonymousString) {
public void onEmojiSelected(String symbol) {
int i = messsageEditText.getSelectionEnd();
CharSequence localCharSequence = Emoji.replaceEmoji(paramAnonymousString, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
if (i < 0) {
i = 0;
}
try {
CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence));
int j = i + localCharSequence.length();
messsageEditText.setSelection(j, j);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
});
emojiPopup = new PopupWindow(emojiView);
/*try {
Method method = emojiPopup.getClass().getMethod("setWindowLayoutType", int.class);
if (method != null) {
method.invoke(emojiPopup, WindowManager.LayoutParams.LAST_SUB_WINDOW);
}
} catch (Exception e) {
//don't promt
}*/
}
public void setDelegate(ChatActivityEnterViewDelegate delegate) {

View File

@ -23,8 +23,6 @@ import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.Scroller;
import org.telegram.messenger.R;
public class HorizontalListView extends AdapterView<ListAdapter> {
public boolean mAlwaysOverrideTouch = true;
@ -209,7 +207,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
v = list.poll();
}
View child = mAdapter.getView(mRightViewIndex, v, this);
child.setTag(R.string.CacheTag, type);
child.setTag(type);
addAndMeasureChild(child, -1);
rightEdge += child.getMeasuredWidth();
@ -236,7 +234,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
v = list.poll();
}
View child = mAdapter.getView(mLeftViewIndex, v, this);
child.setTag(R.string.CacheTag, type);
child.setTag(type);
addAndMeasureChild(child, 0);
leftEdge -= child.getMeasuredWidth();
@ -250,7 +248,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
while (child != null && child.getRight() + dx <= 0) {
mDisplayOffset += child.getMeasuredWidth();
int type = (Integer) child.getTag(R.string.CacheTag);
int type = (Integer) child.getTag();
LinkedList<View> list = mRemovedViewQueue.get(type);
if (list == null) {
list = new LinkedList<View>();
@ -265,7 +263,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
child = getChildAt(getChildCount() - 1);
while (child != null && child.getLeft() + dx >= getWidth()) {
int type = (Integer) child.getTag(R.string.CacheTag);
int type = (Integer) child.getTag();
LinkedList<View> list = mRemovedViewQueue.get(type);
if (list == null) {
list = new LinkedList<View>();

View File

@ -10,11 +10,17 @@ package org.telegram.ui.Views;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
public class LayoutListView extends ListView {
public static interface OnInterceptTouchEventListener {
public abstract boolean onInterceptTouchEvent(MotionEvent event);
}
private OnInterceptTouchEventListener onInterceptTouchEventListener;
private int height = -1;
public LayoutListView(Context context) {
@ -29,6 +35,18 @@ public class LayoutListView extends ListView {
super(context, attrs, defStyle);
}
public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener listener) {
onInterceptTouchEventListener = listener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (onInterceptTouchEventListener != null) {
return onInterceptTouchEventListener.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
}
return super.onInterceptTouchEvent(ev);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
View v = getChildAt(getChildCount() - 1);

View File

@ -1,42 +0,0 @@
/*
* This is the source code of Telegram for Android v. 1.3.2.
* 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.
*/
package org.telegram.ui.Views;
import android.widget.FrameLayout;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.R;
public class MessageActionLayout extends FrameLayout {
public TightTextView messageTextView;
public MessageActionLayout(android.content.Context context) {
super(context);
}
public MessageActionLayout(android.content.Context context, android.util.AttributeSet attrs) {
super(context, attrs);
}
public MessageActionLayout(android.content.Context context, android.util.AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(messageTextView.linesMaxWidth + AndroidUtilities.dp(14), getMeasuredHeight());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
messageTextView = (TightTextView)findViewById(R.id.chat_message_text);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,502 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.telegram.ui.Views;
import android.content.Context;
import android.hardware.SensorManager;
import android.util.FloatMath;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
/**
* This class encapsulates scrolling. The duration of the scroll
* can be passed in the constructor and specifies the maximum time that
* the scrolling animation should take. Past this time, the scrolling is
* automatically moved to its final stage and computeScrollOffset()
* will always return false to indicate that scrolling is over.
*/
public class Scroller {
private int mMode;
private int mStartX;
private int mStartY;
private int mFinalX;
private int mFinalY;
private int mMinX;
private int mMaxX;
private int mMinY;
private int mMaxY;
private int mCurrX;
private int mCurrY;
private long mStartTime;
private int mDuration;
private float mDurationReciprocal;
private float mDeltaX;
private float mDeltaY;
private boolean mFinished;
private Interpolator mInterpolator;
private boolean mFlywheel;
private float mVelocity;
private static final int DEFAULT_DURATION = 250;
private static final int SCROLL_MODE = 0;
private static final int FLING_MODE = 1;
private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance)
private static float END_TENSION = 1.0f - START_TENSION;
private static final int NB_SAMPLES = 100;
private static final float[] SPLINE = new float[NB_SAMPLES + 1];
private float mDeceleration;
private final float mPpi;
static {
float x_min = 0.0f;
for (int i = 0; i <= NB_SAMPLES; i++) {
final float t = (float) i / NB_SAMPLES;
float x_max = 1.0f;
float x, tx, coef;
while (true) {
x = x_min + (x_max - x_min) / 2.0f;
coef = 3.0f * x * (1.0f - x);
tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x;
if (Math.abs(tx - t) < 1E-5) break;
if (tx > t) x_max = x;
else x_min = x;
}
final float d = coef + x * x * x;
SPLINE[i] = d;
}
SPLINE[NB_SAMPLES] = 1.0f;
// This controls the viscous fluid effect (how much of it)
sViscousFluidScale = 8.0f;
// must be set to 1.0 (used in viscousFluid())
sViscousFluidNormalize = 1.0f;
sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
}
private static float sViscousFluidScale;
private static float sViscousFluidNormalize;
/**
* Create a Scroller with the default duration and interpolator.
*/
public Scroller(Context context) {
this(context, null);
}
/**
* Create a Scroller with the specified interpolator. If the interpolator is
* null, the default (viscous) interpolator will be used. "Flywheel" behavior will
* be in effect for apps targeting Honeycomb or newer.
*/
public Scroller(Context context, Interpolator interpolator) {
this(context, interpolator, true);
}
/**
* Create a Scroller with the specified interpolator. If the interpolator is
* null, the default (viscous) interpolator will be used. Specify whether or
* not to support progressive "flywheel" behavior in flinging.
*/
public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
mFinished = true;
mInterpolator = interpolator;
mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
mFlywheel = flywheel;
}
/**
* The amount of friction applied to flings. The default value
* is {@link android.view.ViewConfiguration#getScrollFriction}.
*
* @param friction A scalar dimension-less value representing the coefficient of
* friction.
*/
public final void setFriction(float friction) {
mDeceleration = computeDeceleration(friction);
}
private float computeDeceleration(float friction) {
return SensorManager.GRAVITY_EARTH // g (m/s^2)
* 39.37f // inch/meter
* mPpi // pixels per inch
* friction;
}
/**
*
* Returns whether the scroller has finished scrolling.
*
* @return True if the scroller has finished scrolling, false otherwise.
*/
public final boolean isFinished() {
return mFinished;
}
/**
* Force the finished field to a particular value.
*
* @param finished The new finished value.
*/
public final void forceFinished(boolean finished) {
mFinished = finished;
}
/**
* Returns how long the scroll event will take, in milliseconds.
*
* @return The duration of the scroll in milliseconds.
*/
public final int getDuration() {
return mDuration;
}
/**
* Returns the current X offset in the scroll.
*
* @return The new X offset as an absolute distance from the origin.
*/
public final int getCurrX() {
return mCurrX;
}
/**
* Returns the current Y offset in the scroll.
*
* @return The new Y offset as an absolute distance from the origin.
*/
public final int getCurrY() {
return mCurrY;
}
/**
* Returns the current velocity.
*
* @return The original velocity less the deceleration. Result may be
* negative.
*/
public float getCurrVelocity() {
return mVelocity - mDeceleration * timePassed() / 2000.0f;
}
/**
* Returns the start X offset in the scroll.
*
* @return The start X offset as an absolute distance from the origin.
*/
public final int getStartX() {
return mStartX;
}
/**
* Returns the start Y offset in the scroll.
*
* @return The start Y offset as an absolute distance from the origin.
*/
public final int getStartY() {
return mStartY;
}
/**
* Returns where the scroll will end. Valid only for "fling" scrolls.
*
* @return The final X offset as an absolute distance from the origin.
*/
public final int getFinalX() {
return mFinalX;
}
/**
* Returns where the scroll will end. Valid only for "fling" scrolls.
*
* @return The final Y offset as an absolute distance from the origin.
*/
public final int getFinalY() {
return mFinalY;
}
/**
* Call this when you want to know the new location. If it returns true,
* the animation is not yet finished. loc will be altered to provide the
* new location.
*/
public boolean computeScrollOffset() {
if (mFinished) {
return false;
}
int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
if (timePassed < mDuration) {
switch (mMode) {
case SCROLL_MODE:
float x = timePassed * mDurationReciprocal;
if (mInterpolator == null)
x = viscousFluid(x);
else
x = mInterpolator.getInterpolation(x);
mCurrX = mStartX + Math.round(x * mDeltaX);
mCurrY = mStartY + Math.round(x * mDeltaY);
break;
case FLING_MODE:
final float t = (float) timePassed / mDuration;
final int index = (int) (NB_SAMPLES * t);
final float t_inf = (float) index / NB_SAMPLES;
final float t_sup = (float) (index + 1) / NB_SAMPLES;
final float d_inf = SPLINE[index];
final float d_sup = SPLINE[index + 1];
final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf);
mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
// Pin to mMinX <= mCurrX <= mMaxX
mCurrX = Math.min(mCurrX, mMaxX);
mCurrX = Math.max(mCurrX, mMinX);
mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
// Pin to mMinY <= mCurrY <= mMaxY
mCurrY = Math.min(mCurrY, mMaxY);
mCurrY = Math.max(mCurrY, mMinY);
if (mCurrX == mFinalX && mCurrY == mFinalY) {
mFinished = true;
}
break;
}
}
else {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
return true;
}
/**
* Start scrolling by providing a starting point and the distance to travel.
* The scroll will use the default value of 250 milliseconds for the
* duration.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
* @param startY Starting vertical scroll offset in pixels. Positive numbers
* will scroll the content up.
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
*/
public void startScroll(int startX, int startY, int dx, int dy) {
startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}
/**
* Start scrolling by providing a starting point and the distance to travel.
*
* @param startX Starting horizontal scroll offset in pixels. Positive
* numbers will scroll the content to the left.
* @param startY Starting vertical scroll offset in pixels. Positive numbers
* will scroll the content up.
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
* @param duration Duration of the scroll in milliseconds.
*/
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
}
/**
* Start scrolling based on a fling gesture. The distance travelled will
* depend on the initial velocity of the fling.
*
* @param startX Starting point of the scroll (X)
* @param startY Starting point of the scroll (Y)
* @param velocityX Initial velocity of the fling (X) measured in pixels per
* second.
* @param velocityY Initial velocity of the fling (Y) measured in pixels per
* second
* @param minX Minimum X value. The scroller will not scroll past this
* point.
* @param maxX Maximum X value. The scroller will not scroll past this
* point.
* @param minY Minimum Y value. The scroller will not scroll past this
* point.
* @param maxY Maximum Y value. The scroller will not scroll past this
* point.
*/
public void fling(int startX, int startY, int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) {
// Continue a scroll or fling in progress
if (mFlywheel && !mFinished) {
float oldVel = getCurrVelocity();
float dx = (float) (mFinalX - mStartX);
float dy = (float) (mFinalY - mStartY);
float hyp = FloatMath.sqrt(dx * dx + dy * dy);
float ndx = dx / hyp;
float ndy = dy / hyp;
float oldVelocityX = ndx * oldVel;
float oldVelocityY = ndy * oldVel;
if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
Math.signum(velocityY) == Math.signum(oldVelocityY)) {
velocityX += oldVelocityX;
velocityY += oldVelocityY;
}
}
mMode = FLING_MODE;
mFinished = false;
float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
mVelocity = velocity;
float ALPHA = 800;
final double l = Math.log(START_TENSION * velocity / ALPHA);
mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0)));
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
int totalDistance =
(int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l));
mMinX = minX;
mMaxX = maxX;
mMinY = minY;
mMaxY = maxY;
mFinalX = startX + Math.round(totalDistance * coeffX);
// Pin to mMinX <= mFinalX <= mMaxX
mFinalX = Math.min(mFinalX, mMaxX);
mFinalX = Math.max(mFinalX, mMinX);
mFinalY = startY + Math.round(totalDistance * coeffY);
// Pin to mMinY <= mFinalY <= mMaxY
mFinalY = Math.min(mFinalY, mMaxY);
mFinalY = Math.max(mFinalY, mMinY);
}
static float viscousFluid(float x)
{
x *= sViscousFluidScale;
if (x < 1.0f) {
x -= (1.0f - (float)Math.exp(-x));
} else {
float start = 0.36787944117f; // 1/e == exp(-1)
x = 1.0f - (float)Math.exp(1.0f - x);
x = start + x * (1.0f - start);
}
x *= sViscousFluidNormalize;
return x;
}
/**
* Stops the animation. Contrary to {@link #forceFinished(boolean)},
* aborting the animating cause the scroller to move to the final x and y
* position
*
* @see #forceFinished(boolean)
*/
public void abortAnimation() {
mCurrX = mFinalX;
mCurrY = mFinalY;
mFinished = true;
}
/**
* Extend the scroll animation. This allows a running animation to scroll
* further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
*
* @param extend Additional time to scroll in milliseconds.
* @see #setFinalX(int)
* @see #setFinalY(int)
*/
public void extendDuration(int extend) {
int passed = timePassed();
mDuration = passed + extend;
mDurationReciprocal = 1.0f / mDuration;
mFinished = false;
}
/**
* Returns the time elapsed since the beginning of the scrolling.
*
* @return The elapsed time in milliseconds.
*/
public int timePassed() {
return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
}
/**
* Sets the final position (X) for this scroller.
*
* @param newX The new X offset as an absolute distance from the origin.
* @see #extendDuration(int)
* @see #setFinalY(int)
*/
public void setFinalX(int newX) {
mFinalX = newX;
mDeltaX = mFinalX - mStartX;
mFinished = false;
}
/**
* Sets the final position (Y) for this scroller.
*
* @param newY The new Y offset as an absolute distance from the origin.
* @see #extendDuration(int)
* @see #setFinalX(int)
*/
public void setFinalY(int newY) {
mFinalY = newY;
mDeltaY = mFinalY - mStartY;
mFinished = false;
}
public boolean isScrollingInDirection(float xvel, float yvel) {
return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
Math.signum(yvel) == Math.signum(mFinalY - mStartY);
}
}

View File

@ -0,0 +1,85 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui.Views;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
public class SettingsSectionLayout extends LinearLayout {
private TextView textView;
private void init() {
setOrientation(LinearLayout.VERTICAL);
textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
textView.setTextColor(0xff3b84c0);
addView(textView);
LayoutParams layoutParams = (LayoutParams)textView.getLayoutParams();
layoutParams.width = LayoutParams.WRAP_CONTENT;
layoutParams.height = LayoutParams.WRAP_CONTENT;
layoutParams.leftMargin = AndroidUtilities.dp(8);
layoutParams.rightMargin = AndroidUtilities.dp(8);
layoutParams.topMargin = AndroidUtilities.dp(6);
layoutParams.bottomMargin = AndroidUtilities.dp(4);
if (LocaleController.isRTL) {
textView.setGravity(Gravity.RIGHT);
layoutParams.gravity = Gravity.RIGHT;
}
textView.setLayoutParams(layoutParams);
View view = new View(getContext());
view.setBackgroundColor(0xff6caae4);
addView(view);
layoutParams = (LayoutParams)view.getLayoutParams();
layoutParams.weight = LayoutParams.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(1);
view.setLayoutParams(layoutParams);
}
public SettingsSectionLayout(Context context) {
super(context);
init();
}
public SettingsSectionLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SettingsSectionLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public SettingsSectionLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
}
public void setText(String text) {
textView.setText(text);
}
}

View File

@ -1,118 +0,0 @@
/*
* This is the source code of Telegram for Android v. 1.3.2.
* 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.
*/
package org.telegram.ui.Views;
import android.content.Context;
import android.text.Layout;
import android.util.AttributeSet;
import android.widget.TextView;
import org.telegram.messenger.FileLog;
public class TightTextView extends TextView {
private boolean hasMaxWidth;
public int maxWidth;
public int lastLineWidth = 0;
public int linesMaxWidth = 0;
public int lines = 0;
public TightTextView(Context context) {
this(context, null, 0);
}
public TightTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TightTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredWidth = getMeasuredWidth();
Layout layout = getLayout();
lines = layout.getLineCount();
float lastLeft = layout.getLineLeft(lines - 1);
float lastLine = layout.getLineWidth(lines - 1);
int lastLineWidthWithLeft;
int linesMaxWidthWithLeft;
boolean hasNonRTL = false;
linesMaxWidth = lastLineWidth = (int)Math.ceil(lastLine);
linesMaxWidthWithLeft = lastLineWidthWithLeft = (int)Math.ceil(lastLine + lastLeft);
if (lastLeft == 0) {
hasNonRTL = true;
}
if (hasMaxWidth) {
int specModeW = MeasureSpec.getMode(widthMeasureSpec);
if (specModeW != MeasureSpec.EXACTLY) {
if (lines > 1) {
float textRealMaxWidth = 0, textRealMaxWidthWithLeft = 0;
for (int n = 0; n < lines; ++n) {
float lineWidth;
float lineLeft;
try {
lineWidth = layout.getLineWidth(n);
lineLeft = layout.getLineLeft(n);
} catch (Exception e) {
FileLog.e("tmessages", e);
return;
}
if (lineLeft == 0) {
hasNonRTL = true;
}
textRealMaxWidth = Math.max(textRealMaxWidth, lineWidth);
textRealMaxWidthWithLeft = Math.max(textRealMaxWidthWithLeft, lineWidth + lineLeft);
linesMaxWidth = Math.max(linesMaxWidth, (int)Math.ceil(lineWidth));
linesMaxWidthWithLeft = Math.max(linesMaxWidthWithLeft, (int)Math.ceil(lineWidth + lineLeft));
}
if (hasNonRTL) {
textRealMaxWidth = textRealMaxWidthWithLeft;
lastLineWidth = lastLineWidthWithLeft;
linesMaxWidth = linesMaxWidthWithLeft;
} else {
lastLineWidth = linesMaxWidth;
}
int w = (int)Math.ceil(textRealMaxWidth);
if (w < getMeasuredWidth()) {
super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), heightMeasureSpec);
}
} else {
super.onMeasure(MeasureSpec.makeMeasureSpec(Math.min(maxWidth, linesMaxWidth), MeasureSpec.AT_MOST), heightMeasureSpec);
}
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
try {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} catch (Exception e2) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
FileLog.e("tmessages", e2);
}
}
}
@Override
public void setMaxWidth(int maxpixels) {
super.setMaxWidth(maxpixels);
hasMaxWidth = true;
maxWidth = maxpixels;
}
@Override
public void setMaxEms(int maxems) {
super.setMaxEms(maxems);
hasMaxWidth = true;
}
}

View File

@ -65,21 +65,34 @@ public class TimerButton extends View {
time = value;
String timeString = null;
if (time == 2) {
timeString = "2s";
} else if (time == 5) {
timeString = "5s";
} else if (time == 60) {
timeString = "1m";
} else if (time == 60 * 60) {
timeString = "1h";
} else if (time == 60 * 60 * 24) {
timeString = "1d";
} else if (time == 60 * 60 * 24 * 7) {
timeString = "1w";
if (time >= 1 && time < 60) {
timeString = "" + value;
if (timeString.length() < 2) {
timeString += "s";
}
} else if (time >= 60 && time < 60 * 60) {
timeString = "" + value / 60;
if (timeString.length() < 2) {
timeString += "m";
}
} else if (time >= 60 * 60 && time < 60 * 60 * 24) {
timeString = "" + value / 60 / 60;
if (timeString.length() < 2) {
timeString += "h";
}
} else if (time >= 60 * 60 * 24 && time < 60 * 60 * 24 * 7) {
timeString = "" + value / 60 / 60 / 24;
if (timeString.length() < 2) {
timeString += "d";
}
} else {
timeString = "" + value / 60 / 60 / 24 / 7;
if (timeString.length() < 2) {
timeString += "w";
} else if (timeString.length() > 2) {
timeString = "c";
}
}
timeWidth = timePaint.measureText(timeString);
try {
@ -110,7 +123,7 @@ public class TimerButton extends View {
drawable.draw(canvas);
if (time != 0 && timeLayout != null) {
canvas.translate((width - timeWidth) / 2, (height - timeHeight) / 2 + AndroidUtilities.dp(1));
canvas.translate((int)(width / 2 - Math.ceil(timeWidth / 2)), (height - timeHeight) / 2 + AndroidUtilities.dpf2(1.5f));
timeLayout.draw(canvas);
}
}

View File

@ -0,0 +1,24 @@
/*
* This is the source code of Telegram for Android v. 1.7.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-2014.
*/
package org.telegram.ui.Views;
import android.text.TextPaint;
import android.text.style.URLSpan;
public class URLSpanNoUnderline extends URLSpan {
public URLSpanNoUnderline(String url) {
super(url);
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}

View File

@ -153,9 +153,13 @@ public class VideoTimelineView extends View {
public void setVideoPath(String path) {
mediaMetadataRetriever = new MediaMetadataRetriever();
try {
mediaMetadataRetriever.setDataSource(path);
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
videoLength = Long.parseLong(duration);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void setDelegate(VideoTimelineViewDelegate delegate) {

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:factor="1.5" />

View File

@ -1,15 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="0.9"
android:fromYScale="0.9"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
<!--<scale-->
<!--android:fromXScale="0.9"-->
<!--android:fromYScale="0.9"-->
<!--android:toXScale="1.0"-->
<!--android:toYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220"/>-->
<!--<alpha android:fromAlpha="0.0"-->
<!--android:toAlpha="1.0"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="@android:integer/config_mediumAnimTime" />-->
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:interpolator="@anim/decelerate_cubic"
android:duration="150"/>
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="150" />
<scale
android:fromXScale=".8" android:toXScale="1.0"
android:fromYScale=".8" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@anim/decelerate_cubic"
android:duration="150"/>
</set>

View File

@ -1,16 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="0.9"
android:toYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
<!--<scale-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:toXScale="0.9"-->
<!--android:toYScale="0.9"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220"/>-->
<!--<alpha-->
<!--android:fromAlpha="1.0"-->
<!--android:toAlpha="0.0"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220" />-->
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:interpolator="@anim/decelerate_cubic"
android:duration="150"/>
<alpha android:fromAlpha="1.0"
android:toAlpha="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:duration="150" />
<scale
android:fromXScale="1.0"
android:toXScale=".8"
android:fromYScale="1.0"
android:toYScale=".8"
android:pivotX="50%p"
android:pivotY="50%p"
android:interpolator="@anim/decelerate_cubic"
android:duration="150"/>
</set>

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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