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 messenger for Android
[Telegram](http://telegram.org) is a messaging app with a focus on speed and security. Its superfast, simple and free. [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 ### 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 ### Usage
**Beware of using dev branch and uploading it to any markets, in most cases it will work as you expecting** **Beware of using the dev branch and uploading it to any markets, in many cases it not will work as expected**.
First of all your should take a look to **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
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. Import the root folder into your IDE (tested on Android Studio), then run project.
### Localization ### Localization

View File

@ -19,13 +19,13 @@ tasks.withType(JavaCompile) {
dependencies { dependencies {
compile 'com.android.support:support-v4:20.0.+' compile 'com.android.support:support-v4:20.0.+'
compile 'com.google.android.gms:play-services:3.2.+' 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.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+'
} }
android { android {
compileSdkVersion 19 compileSdkVersion 21
buildToolsVersion '20.0.0' buildToolsVersion '21.0.2'
signingConfigs { signingConfigs {
debug { debug {
@ -80,7 +80,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 8 minSdkVersion 8
targetSdkVersion 19 targetSdkVersion 19
versionCode 355 versionCode 374
versionName "1.9.4" 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); 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; uint8_t *pix = (uint8_t *)pixels;
const int w = imageWidth; const int w = imageWidth;
const int h = imageHeight; const int h = imageHeight;
const int stride = imageStride; const int stride = imageStride;
const int radius = 3;
const int r1 = radius + 1; const int r1 = radius + 1;
const int div = radius * 2 + 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)); 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; int x, y, i;
@ -111,7 +202,7 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
longjmp(myerr->setjmp_buffer, 1); 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) { if (!bitmap) {
return; return;
} }
@ -130,7 +221,11 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl
if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) { if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
return; 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); 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()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()]. ** [sqlite_version()] and [sqlite_source_id()].
*/ */
#define SQLITE_VERSION "3.8.4.1" #define SQLITE_VERSION "3.8.6"
#define SQLITE_VERSION_NUMBER 3008004 #define SQLITE_VERSION_NUMBER 3008006
#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0" #define SQLITE_SOURCE_ID "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
/* /*
** CAPI3REF: Run-Time Library Version Numbers ** 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 ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object. ** 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 ** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated. ** resources are deallocated.
** **
@ -277,7 +277,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** statements or unfinished sqlite3_backup objects then sqlite3_close() ** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY]. ** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements ** ^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 ** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is ** last prepared statement is finalized or the last sqlite3_backup is
** finished. The sqlite3_close_v2() interface is intended for use with ** 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 ** with the [sqlite3] object prior to attempting to close the object. ^If
** sqlite3_close_v2() is called on a [database connection] that still has ** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or ** 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], ** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed. ** and [sqlite3_backup] objects are also destroyed.
** **
@ -386,16 +386,14 @@ SQLITE_API int sqlite3_exec(
/* /*
** CAPI3REF: Result Codes ** CAPI3REF: Result Codes
** KEYWORDS: SQLITE_OK {error code} {error codes} ** KEYWORDS: {result code definitions}
** KEYWORDS: {result code} {result codes}
** **
** Many SQLite functions return an integer result code from the set shown ** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure. ** here in order to indicate success or failure.
** **
** New error codes may be added in future versions of SQLite. ** New error codes may be added in future versions of SQLite.
** **
** See also: [SQLITE_IOERR_READ | extended result codes], ** See also: [extended result code definitions]
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
*/ */
#define SQLITE_OK 0 /* Successful result */ #define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */ /* beginning-of-error-codes */
@ -433,26 +431,19 @@ SQLITE_API int sqlite3_exec(
/* /*
** CAPI3REF: Extended Result Codes ** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes} ** KEYWORDS: {extended result code definitions}
** KEYWORDS: {extended result code} {extended result codes}
** **
** In its default configuration, SQLite API routines return one of 26 integer ** In its default configuration, SQLite API routines return one of 30 integer
** [SQLITE_OK | result codes]. However, experience has shown that many of ** [result codes]. However, experience has shown that many of
** these result codes are too coarse-grained. They do not provide as ** these result codes are too coarse-grained. They do not provide as
** much information about problems as programmers might like. In an effort to ** 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 ** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information ** 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 ** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API. ** [sqlite3_extended_result_codes()] API. Or, the extended code for
** ** the most recent error can be obtained using
** Some of the available extended result codes are listed here. ** [sqlite3_extended_errcode()].
** 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.
*/ */
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<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 ** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are ** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ** 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_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC512 0x00000002
@ -575,6 +569,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
/* /*
** CAPI3REF: File Locking Levels ** CAPI3REF: File Locking Levels
@ -681,7 +676,7 @@ struct sqlite3_file {
** locking strategy (for example to use dot-file locks), to inquire ** locking strategy (for example to use dot-file locks), to inquire
** about the status of a lock, or to break stale locks. The SQLite ** about the status of a lock, or to break stale locks. The SQLite
** core reserves all opcodes less than 100 for its own use. ** 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 ** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts. VFS implementations should ** greater than 100 to avoid conflicts. VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not ** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@ -754,6 +749,7 @@ struct sqlite3_io_methods {
/* /*
** CAPI3REF: Standard File Control Opcodes ** CAPI3REF: Standard File Control Opcodes
** KEYWORDS: {file control opcodes} {file control opcode}
** **
** These integer constants are opcodes for the xFileControl method ** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** 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 ** on whether or not the file has been renamed, moved, or deleted since it
** was first opened. ** 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> ** </ul>
*/ */
#define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_LOCKSTATE 1
@ -966,6 +968,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_HAS_MOVED 20 #define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
/* /*
** CAPI3REF: Mutex Handle ** CAPI3REF: Mutex Handle
@ -2026,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
/* /*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** **
** ^This routine sets a callback function that might be invoked whenever ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** an attempt is made to open a database table that another thread ** that might be invoked with argument P whenever
** or process has locked. ** 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 returned immediately upon encountering the lock. ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments. ** 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 ** ^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 ** 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 ** 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 ** 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 ** ^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 ** 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 ** 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] ** 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 ** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and ** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying ** 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 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 ** ^(There can only be a single busy handler defined for each
** [database connection]. Setting a new busy handler clears any ** [database connection]. Setting a new busy handler clears any
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] ** 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 ** 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. ** result in undefined behavior.
** **
** A busy handler must not close the database connection ** 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 ** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated. ^After 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 ** 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 ** ^Calling this routine with an argument less than or equal to zero
** turns off all busy handlers. ** 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 ** [database connection] any any given moment. If another busy handler
** was defined (using [sqlite3_busy_handler()]) prior to calling ** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^ ** this routine, that other busy handler is cleared.)^
**
** See also: [PRAGMA busy_timeout]
*/ */
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); 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 ** [sqlite3_set_authorizer | authorizer documentation] for additional
** information. ** information.
** **
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] ** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
** from the [sqlite3_vtab_on_conflict()] interface. ** returned from the [sqlite3_vtab_on_conflict()] interface.
*/ */
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ #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 */ #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 ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting ** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** 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> ** </ul>
** **
** ^Specifying an unknown parameter in the query component of a URI is not an ** ^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. ** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by ** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache. ** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td> ** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". ** 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> ** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter. ** An error. "readonly" is not a valid option for the "mode" parameter.
** </table> ** </table>
@ -4670,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
** is a NULL pointer, then SQLite performs a search for an appropriate ** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory. ** 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 ** 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 ** 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 ** 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 ** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc] ** 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. ** 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 ** <b>Note to Windows Runtime users:</b> The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various ** 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_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER ** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MEM ** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2 ** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG ** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU ** <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>)^ ** </ul>)^
** **
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) ** ^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_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ #define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ #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 ** 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_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #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 ** 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 ** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL. ** from SQL.
** **
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint ** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages. The use of this interface ** 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 ** empty string, then a checkpoint is run on all databases of
** connection D. ^If the database connection D is not in ** connection D. ^If the database connection D is not in
** [WAL | write-ahead log mode] then this interface is a harmless no-op. ** [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 ** ^The [wal_checkpoint pragma] can be used to invoke this interface
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the ** 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 ** 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 ** readers or writers to finish. Sync the db file if all frames in the log
** are checkpointed. This mode is the same as calling ** 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> ** <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 ** 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 ** snapshot. It then checkpoints all frames in the log file and syncs the
** database file. This call blocks database writers while it is running, ** 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> ** <dt>SQLITE_CHECKPOINT_RESTART<dd>
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after ** 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 ** 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 ** 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, ** 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 ** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
** **
** These constants are returned by [sqlite3_vtab_on_conflict()] to ** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode ** inform a [virtual table] implementation what the [ON CONFLICT] mode
@ -7346,6 +7399,16 @@ extern "C" {
#endif #endif
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; 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 ** 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( SQLITE_API int sqlite3_rtree_geometry_callback(
sqlite3 *db, sqlite3 *db,
const char *zGeom, const char *zGeom,
#ifdef SQLITE_RTREE_INT_ONLY int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
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
void *pContext void *pContext
); );
@ -7372,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
struct sqlite3_rtree_geometry { struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */ void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */ 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 *pUser; /* Callback implementation user data */
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ 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 #ifdef __cplusplus
} /* end of the 'extern "C"' block */ } /* end of the 'extern "C"' block */

View File

@ -9,7 +9,9 @@
package org.telegram.android; package org.telegram.android;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Point; import android.graphics.Point;
@ -21,17 +23,23 @@ import android.view.Surface;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.ui.ApplicationLoader; import org.telegram.ui.ApplicationLoader;
import org.telegram.ui.Views.NumberPicker;
import java.io.File; import java.io.File;
import java.lang.reflect.Field;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Locale; import java.util.Locale;
public class AndroidUtilities { public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<String, Typeface>(); private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<String, Typeface>();
private static int prevOrientation = -10; private static int prevOrientation = -10;
private static boolean waitingForSms = false; private static boolean waitingForSms = false;
@ -210,7 +218,7 @@ public class AndroidUtilities {
} }
public static File getCacheDir() { public static File getCacheDir() {
if (Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) { if (Environment.getExternalStorageState() == null || Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
try { try {
File file = ApplicationLoader.applicationContext.getExternalCacheDir(); File file = ApplicationLoader.applicationContext.getExternalCacheDir();
if (file != null) { if (file != null) {
@ -239,6 +247,10 @@ public class AndroidUtilities {
return (int)Math.ceil(density * value); return (int)Math.ceil(density * value);
} }
public static float dpf2(float value) {
return density * value;
}
public static void checkDisplaySize() { public static void checkDisplaySize() {
try { try {
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
@ -262,6 +274,22 @@ public class AndroidUtilities {
return 0x0000000100000000L | ((long)id & 0x00000000FFFFFFFFL); 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) { public static void RunOnUIThread(Runnable runnable) {
RunOnUIThread(runnable, 0); RunOnUIThread(runnable, 0);
} }
@ -274,6 +302,10 @@ public class AndroidUtilities {
} }
} }
public static void CancelRunOnUIThread(Runnable runnable) {
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
}
public static boolean isTablet() { public static boolean isTablet() {
if (isTablet == null) { if (isTablet == null) {
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet); isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
@ -367,4 +399,106 @@ public class AndroidUtilities {
} }
return photoSize; 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(); ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
HashMap<String, Contact> shortContacts = new HashMap<String, Contact>(); 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); Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
if (pCur != null) { if (pCur != null) {
if (pCur.getCount() > 0) { if (pCur.getCount() > 0) {
@ -262,9 +262,9 @@ public class ContactsController {
Integer id = pCur.getInt(0); Integer id = pCur.getInt(0);
if (ids.length() != 0) { if (ids.length() != 0) {
ids += ","; ids.append(",");
} }
ids += id; ids.append(id);
int type = pCur.getInt(2); int type = pCur.getInt(2);
Contact contact = contactsMap.get(id); Contact contact = contactsMap.get(id);
@ -299,7 +299,7 @@ public class ContactsController {
pCur.close(); 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) { if (pCur != null && pCur.getCount() > 0) {
while (pCur.moveToNext()) { while (pCur.moveToNext()) {
int id = pCur.getInt(0); int id = pCur.getInt(0);
@ -844,14 +844,14 @@ public class ContactsController {
return 0; return 0;
} }
}); });
String ids = ""; StringBuilder ids = new StringBuilder();
for (TLRPC.TL_contact aContactsArr : contactsArr) { for (TLRPC.TL_contact aContactsArr : contactsArr) {
if (ids.length() != 0) { 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); 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 HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>(); final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
@ -1114,11 +1114,11 @@ public class ContactsController {
} }
arr.add(value); arr.add(value);
if (ids.length() != 0) { 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); UserConfig.saveConfig(false);
Collections.sort(sortedSectionsArray, new Comparator<String>() { 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()); FileLog.e("tmessages", "process update - contacts add = " + newC.size() + " delete = " + contactsTD.size());
String toAdd = ""; StringBuilder toAdd = new StringBuilder();
String toDelete = ""; StringBuilder toDelete = new StringBuilder();
boolean reloadContacts = false; boolean reloadContacts = false;
for (TLRPC.TL_contact newContact : newC) { for (TLRPC.TL_contact newContact : newC) {
@ -1216,9 +1216,9 @@ public class ContactsController {
} }
} }
if (toAdd.length() != 0) { if (toAdd.length() != 0) {
toAdd += ","; toAdd.append(",");
} }
toAdd += user.phone; toAdd.append(user.phone);
} }
for (final Integer uid : contactsTD) { for (final Integer uid : contactsTD) {
@ -1252,14 +1252,14 @@ public class ContactsController {
} }
} }
if (toDelete.length() != 0) { if (toDelete.length() != 0) {
toDelete += ","; toDelete.append(",");
} }
toDelete += user.phone; toDelete.append(user.phone);
} }
} }
if (toAdd.length() != 0 || toDelete.length() != 0) { if (toAdd.length() != 0 || toDelete.length() != 0) {
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd, toDelete); MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd.toString(), toDelete.toString());
} }
if (reloadContacts) { if (reloadContacts) {

View File

@ -28,7 +28,6 @@ import android.provider.MediaStore;
import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
@ -293,7 +292,7 @@ public class ImageLoader {
} }
} }
if (image != null && blur && bitmapH < 100 && bitmapW < 100) { if (image != null && blur && bitmapH < 100 && bitmapW < 100) {
Utilities.blurBitmap(image); Utilities.blurBitmap(image, 3);
} }
} }
if (runtimeHack != null) { 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) { 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))) { if ((fileLocation == null && httpUrl == null) || imageView == null || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation))) {
return; return;

View File

@ -9,8 +9,13 @@
package org.telegram.android; package org.telegram.android;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.View; import android.view.View;
@ -35,6 +40,13 @@ public class ImageReceiver {
private boolean isVisible = true; private boolean isVisible = true;
private boolean isAspectFit = false; private boolean isAspectFit = false;
private boolean lastCacheOnly = 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() { public ImageReceiver() {
@ -65,6 +77,7 @@ public class ImageReceiver {
last_httpUrl = null; last_httpUrl = null;
last_filter = null; last_filter = null;
lastCacheOnly = false; lastCacheOnly = false;
bitmapShader = null;
last_placeholder = placeholder; last_placeholder = placeholder;
last_size = 0; last_size = 0;
currentImage = null; currentImage = null;
@ -104,9 +117,13 @@ public class ImageReceiver {
last_placeholder = placeholder; last_placeholder = placeholder;
last_size = size; last_size = size;
lastCacheOnly = cacheOnly; lastCacheOnly = cacheOnly;
bitmapShader = null;
if (img == null) { if (img == null) {
isPlaceholder = true; isPlaceholder = true;
ImageLoader.getInstance().loadImage(fileLocation, httpUrl, this, size, cacheOnly); ImageLoader.getInstance().loadImage(fileLocation, httpUrl, this, size, cacheOnly);
if (parentView != null) {
parentView.invalidate();
}
} else { } else {
setImageBitmap(img, currentPath); setImageBitmap(img, currentPath);
} }
@ -119,6 +136,11 @@ public class ImageReceiver {
isPlaceholder = false; isPlaceholder = false;
ImageLoader.getInstance().incrementUseCount(currentPath); ImageLoader.getInstance().incrementUseCount(currentPath);
currentImage = bitmap; 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) { if (parentView != null) {
parentView.invalidate(); parentView.invalidate();
} }
@ -138,6 +160,7 @@ public class ImageReceiver {
last_httpUrl = null; last_httpUrl = null;
last_filter = null; last_filter = null;
currentImage = null; currentImage = null;
bitmapShader = null;
last_size = 0; last_size = 0;
lastCacheOnly = false; lastCacheOnly = false;
if (parentView != null) { if (parentView != null) {
@ -155,6 +178,7 @@ public class ImageReceiver {
last_path = null; last_path = null;
last_httpUrl = null; last_httpUrl = null;
last_filter = null; last_filter = null;
bitmapShader = null;
last_size = 0; last_size = 0;
lastCacheOnly = false; lastCacheOnly = false;
if (parentView != null) { if (parentView != null) {
@ -192,83 +216,92 @@ public class ImageReceiver {
} }
} }
public boolean draw(Canvas canvas, int x, int y, int w, int h) { public boolean draw(Canvas canvas) {
try { try {
Drawable bitmapDrawable = currentImage; 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; bitmapDrawable = last_placeholder;
} }
if (bitmapDrawable != null) { if (bitmapDrawable != null) {
int bitmapW = bitmapDrawable.getIntrinsicWidth(); if (bitmapShader != null) {
int bitmapH = bitmapDrawable.getIntrinsicHeight(); drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
float scaleW = bitmapW / (float)w; roundRect.set(imageX, imageY, imageX + imageW, imageY + imageH);
float scaleH = bitmapH / (float)h; shaderMatrix.reset();
shaderMatrix.setScale(1.5f, 1.5f);
if (isAspectFit) { bitmapShader.setLocalMatrix(shaderMatrix);
float scale = Math.max(scaleW, scaleH); canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint);
canvas.save();
bitmapW /= scale;
bitmapH /= scale;
drawRegion.set(x + (w - bitmapW) / 2, y + (h - bitmapH) / 2, x + (w + bitmapW) / 2, y + (h + bitmapH) / 2);
bitmapDrawable.setBounds(drawRegion);
try {
bitmapDrawable.draw(canvas);
} catch (Exception e) {
if (currentPath != null) {
ImageLoader.getInstance().removeImage(currentPath);
currentPath = null;
}
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
}
canvas.restore();
} else { } else {
if (Math.abs(scaleW - scaleH) > 0.00001f) { int bitmapW = bitmapDrawable.getIntrinsicWidth();
int bitmapH = bitmapDrawable.getIntrinsicHeight();
float scaleW = bitmapW / (float) imageW;
float scaleH = bitmapH / (float) imageH;
if (isAspectFit) {
float scale = Math.max(scaleW, scaleH);
canvas.save(); canvas.save();
canvas.clipRect(x, y, x + w, y + h); bitmapW /= scale;
bitmapH /= scale;
if (bitmapW / scaleH > w) { drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2);
bitmapW /= scaleH;
drawRegion.set(x - (bitmapW - w) / 2, y, x + (bitmapW + w) / 2, y + h);
} else {
bitmapH /= scaleW;
drawRegion.set(x, y - (bitmapH - h) / 2, x + w, y + (bitmapH + h) / 2);
}
bitmapDrawable.setBounds(drawRegion); bitmapDrawable.setBounds(drawRegion);
if (isVisible) { try {
try { bitmapDrawable.draw(canvas);
bitmapDrawable.draw(canvas); } catch (Exception e) {
} catch (Exception e) { if (currentPath != null) {
if (currentPath != null) { ImageLoader.getInstance().removeImage(currentPath);
ImageLoader.getInstance().removeImage(currentPath); currentPath = null;
currentPath = null;
}
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
} }
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
} }
canvas.restore(); canvas.restore();
} else { } else {
drawRegion.set(x, y, x + w, y + h); if (Math.abs(scaleW - scaleH) > 0.00001f) {
bitmapDrawable.setBounds(drawRegion); canvas.save();
if (isVisible) { canvas.clipRect(imageX, imageY, imageX + imageW, imageY + imageH);
try {
bitmapDrawable.draw(canvas); if (bitmapW / scaleH > imageW) {
} catch (Exception e) { bitmapW /= scaleH;
if (currentPath != null) { drawRegion.set(imageX - (bitmapW - imageW) / 2, imageY, imageX + (bitmapW + imageW) / 2, imageY + imageH);
ImageLoader.getInstance().removeImage(currentPath); } else {
currentPath = null; bitmapH /= scaleW;
drawRegion.set(imageX, imageY - (bitmapH - imageH) / 2, imageX + imageW, imageY + (bitmapH + imageH) / 2);
}
bitmapDrawable.setBounds(drawRegion);
if (isVisible) {
try {
bitmapDrawable.draw(canvas);
} catch (Exception e) {
if (currentPath != null) {
ImageLoader.getInstance().removeImage(currentPath);
currentPath = null;
}
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
}
}
canvas.restore();
} else {
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
bitmapDrawable.setBounds(drawRegion);
if (isVisible) {
try {
bitmapDrawable.draw(canvas);
} catch (Exception e) {
if (currentPath != null) {
ImageLoader.getInstance().removeImage(currentPath);
currentPath = null;
}
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
} }
setImage(last_path, last_httpUrl, last_filter, last_placeholder, last_size, lastCacheOnly);
FileLog.e("tmessages", e);
} }
} }
} }
} }
return true; return true;
} else if (last_placeholder != null) { } 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); last_placeholder.setBounds(drawRegion);
if (isVisible) { if (isVisible) {
try { try {
@ -371,4 +404,23 @@ public class ImageReceiver {
public String getKey() { public String getKey() {
return currentPath; 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.content.SharedPreferences;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.AudioRecord; import android.media.AudioRecord;
@ -36,7 +38,9 @@ import android.os.Environment;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Vibrator; import android.os.Vibrator;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.view.Display;
import android.view.View; import android.view.View;
import android.view.WindowManager;
import org.telegram.android.video.InputSurface; import org.telegram.android.video.InputSurface;
import org.telegram.android.video.MP4Builder; import org.telegram.android.video.MP4Builder;
@ -58,6 +62,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
@ -340,13 +345,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
} }
} }
private String[] mediaProjections = new String[] { private String[] mediaProjections = null;
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 static volatile MediaController Instance = null; private static volatile MediaController Instance = null;
public static MediaController getInstance() { 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.FileDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileLoadProgressChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileLoadProgressChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog);
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() { BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
@Override @Override
@ -413,6 +414,26 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
if (UserConfig.isClientActivated()) { if (UserConfig.isClientActivated()) {
checkAutodownloadSettings(); 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() { private void startProgressTimer() {
@ -684,7 +705,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
public void startMediaObserver() { 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; return;
} }
ApplicationLoader.applicationHandler.removeCallbacks(stopMediaObserverRunnable); ApplicationLoader.applicationHandler.removeCallbacks(stopMediaObserverRunnable);
@ -706,7 +727,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
public void stopMediaObserver() { 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; return;
} }
if (stopMediaObserverRunnable == null) { if (stopMediaObserverRunnable == null) {
@ -718,6 +739,30 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
public void processMediaObserver(Uri uri) { public void processMediaObserver(Uri uri) {
try { 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"); Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, mediaProjections, null, null, "date_added DESC LIMIT 1");
final ArrayList<Long> screenshotDates = new ArrayList<Long>(); final ArrayList<Long> screenshotDates = new ArrayList<Long>();
if (cursor != null) { if (cursor != null) {
@ -726,75 +771,33 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
String data = cursor.getString(0); String data = cursor.getString(0);
String display_name = cursor.getString(1); String display_name = cursor.getString(1);
String album_name = cursor.getString(2); String album_name = cursor.getString(2);
String title = cursor.getString(4);
long date = cursor.getLong(3); 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") || if (data != null && data.toLowerCase().contains("screenshot") ||
display_name != null && display_name.toLowerCase().contains("screenshot") || display_name != null && display_name.toLowerCase().contains("screenshot") ||
album_name != null && album_name.toLowerCase().contains("screenshot") || album_name != null && album_name.toLowerCase().contains("screenshot") ||
title != null && title.toLowerCase().contains("screenshot")) { title != null && title.toLowerCase().contains("screenshot")) {
/*BitmapRegionDecoder bitmapRegionDecoder = null;
boolean added = false;
try { try {
int waitCount = 0; if (photoW == 0 || photoH == 0) {
while (waitCount < 5 && bitmapRegionDecoder == null) { BitmapFactory.Options bmOptions = new BitmapFactory.Options();
try { bmOptions.inJustDecodeBounds = true;
bitmapRegionDecoder = BitmapRegionDecoder.newInstance(data, true); BitmapFactory.decodeFile(data, bmOptions);
if (bitmapRegionDecoder != null) { photoW = bmOptions.outWidth;
break; photoH = bmOptions.outHeight;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
Thread.sleep(1000);
} }
if (bitmapRegionDecoder != null) { if (photoW <= 0 || photoH <= 0 || (photoW == width && photoH == height || photoH == width && photoW == height)) {
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) {
screenshotDates.add(date); screenshotDates.add(date);
} }
}*/ } catch (Exception e) {
screenshotDates.add(date); screenshotDates.add(date);
}
} }
FileLog.e("tmessages", "screenshot!");
} }
cursor.close(); cursor.close();
} }
@ -831,7 +834,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
} }
if (send) { 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(); deleteLaterArray.clear();
} }
@SuppressWarnings("unchecked")
@Override @Override
public void didReceivedNotification(int id, Object... args) { public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.FileDidFailedLoad) { if (id == NotificationCenter.FileDidFailedLoad) {
@ -961,6 +965,18 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
listenerInProgress = false; listenerInProgress = false;
processLaterArrays(); 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; return true;
} }
NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject);
clenupPlayer(true); clenupPlayer(true);
final File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); 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 = 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.setStereoVolume(1.0f, 1.0f);
//audioTrackPlayer.setNotificationMarkerPosition((int)currentTotalPcmDuration);
audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() {
@Override @Override
public void onMarkerReached(AudioTrack audioTrack) { public void onMarkerReached(AudioTrack audioTrack) {
@ -2081,12 +2097,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
if (end < 0 || info.presentationTimeUs < end) { if (end < 0 || info.presentationTimeUs < end) {
info.offset = 0; info.offset = 0;
info.flags = extractor.getSampleFlags(); info.flags = extractor.getSampleFlags();
if (!isAudio) { if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info, isAudio)) {
buffer.limit(info.offset + info.size);
buffer.position(info.offset);
buffer.putInt(info.size - 4);
}
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
didWriteData(messageObject, file, false, false); didWriteData(messageObject, file, false, false);
} }
extractor.advance(); extractor.advance();
@ -2168,10 +2179,28 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
resultWidth = temp; resultWidth = temp;
rotationValue = 90; rotationValue = 90;
rotateRender = 270; 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); File inputFile = new File(videoPath);
if (!inputFile.canRead()) { if (!inputFile.canRead()) {
didWriteData(messageObject, cacheFile, true, true);
return false; return false;
} }
@ -2374,10 +2403,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
} }
if (info.size > 1) { if (info.size > 1) {
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
encodedData.limit(info.offset + info.size); if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) {
encodedData.position(info.offset);
encodedData.putInt(Integer.reverseBytes(info.size - 4));
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
didWriteData(messageObject, cacheFile, false, false); didWriteData(messageObject, cacheFile, false, false);
} }
} else if (videoTrackIndex == -5) { } else if (videoTrackIndex == -5) {
@ -2552,6 +2578,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time)); FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
} }
} else { } else {
didWriteData(messageObject, cacheFile, true, true);
return false; return false;
} }
didWriteData(messageObject, cacheFile, true, error); didWriteData(messageObject, cacheFile, true, error);

View File

@ -12,15 +12,20 @@ import android.graphics.Bitmap;
import android.graphics.Paint; import android.graphics.Paint;
import android.text.Layout; import android.text.Layout;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout; import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextUtils;
import android.text.util.Linkify; import android.text.util.Linkify;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.ui.Views.URLSpanNoUnderline;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.ArrayList; import java.util.ArrayList;
@ -90,7 +95,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouCreateGroup", R.string.ActionYouCreateGroup); messageText = LocaleController.getString("ActionYouCreateGroup", R.string.ActionYouCreateGroup);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", ""); messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", "");
} }
@ -101,26 +106,27 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouLeftUser", R.string.ActionYouLeftUser); messageText = LocaleController.getString("ActionYouLeftUser", R.string.ActionYouLeftUser);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", ""); messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", "");
} }
} }
} else { } else {
TLRPC.User who = null; TLRPC.User whoUser = null;
if (users != null) { if (users != null) {
who = users.get(message.action.user_id); whoUser = users.get(message.action.user_id);
} }
if (who == null) { if (whoUser == null) {
who = MessagesController.getInstance().getUser(message.action.user_id); whoUser = MessagesController.getInstance().getUser(message.action.user_id);
} }
if (who != null && fromUser != null) { if (whoUser != null && fromUser != null) {
if (isFromMe()) { 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()) { } 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 { } 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 { } else {
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", "").replace("un1", ""); messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", "").replace("un1", "");
@ -136,11 +142,12 @@ public class MessageObject {
} }
if (whoUser != null && fromUser != null) { if (whoUser != null && fromUser != null) {
if (isFromMe()) { 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()) { } 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 { } 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 { } else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", "").replace("un1", ""); 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); messageText = LocaleController.getString("ActionYouChangedPhoto", R.string.ActionYouChangedPhoto);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", ""); 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); messageText = LocaleController.getString("ActionYouChangedTitle", R.string.ActionYouChangedTitle).replace("un2", message.action.title);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", "").replace("un2", message.action.title); 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); messageText = LocaleController.getString("ActionYouRemovedPhoto", R.string.ActionYouRemovedPhoto);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", ""); messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", "");
} }
} }
} else if (message.action instanceof TLRPC.TL_messageActionTTLChange) { } else if (message.action instanceof TLRPC.TL_messageActionTTLChange) {
if (message.action.ttl != 0) { 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()) { if (isFromMe()) {
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, timeString); messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, AndroidUtilities.formatTTLString(message.action.ttl));
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", timeString); messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", AndroidUtilities.formatTTLString(message.action.ttl));
} }
} }
} else { } else {
@ -241,17 +232,40 @@ public class MessageObject {
} else { } else {
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, ""); 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 (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
if (isFromMe()) { if (isFromMe()) {
messageText = LocaleController.formatString("ActionTakeScreenshootYou", R.string.ActionTakeScreenshootYou); messageText = LocaleController.formatString("ActionTakeScreenshootYou", R.string.ActionTakeScreenshootYou);
} else { } else {
if (fromUser != null) { 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 { } else {
messageText = LocaleController.formatString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot).replace("un1", ""); 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) { } else if (message.action instanceof TLRPC.TL_messageActionCreatedBroadcastList) {
messageText = LocaleController.formatString("YouCreatedBroadcastList", R.string.YouCreatedBroadcastList); messageText = LocaleController.formatString("YouCreatedBroadcastList", R.string.YouCreatedBroadcastList);
@ -278,7 +292,7 @@ public class MessageObject {
} }
messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20)); 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) { if (message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty) {
contentType = type = 0; contentType = type = 0;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) { } else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) {
@ -290,13 +304,8 @@ public class MessageObject {
contentType = 1; contentType = 1;
type = 3; type = 3;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaContact) { } else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaContact) {
if (isFromMe()) { contentType = 3;
contentType = 3; type = 12;
type = 12;
} else {
contentType = 4;
type = 13;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaUnsupported) { } else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaUnsupported) {
contentType = type = 0; contentType = type = 0;
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaDocument) { } 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) { if (message.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
contentType = type = 0; contentType = type = 0;
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto || message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { } else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto || message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
contentType = 8; contentType = 4;
type = 11; 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 = -1;
type = -1;
}
} else { } else {
contentType = 7; contentType = 4;
type = 10; type = 10;
} }
} else if (message instanceof TLRPC.TL_messageForwarded) {
contentType = type = 0;
} }
Calendar rightNow = new GregorianCalendar(); Calendar rightNow = new GregorianCalendar();
@ -334,13 +349,22 @@ public class MessageObject {
generateThumbs(false, preview); 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) { public void generateThumbs(boolean update, int preview) {
if (messageOwner instanceof TLRPC.TL_messageService) { if (messageOwner instanceof TLRPC.TL_messageService) {
if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) { if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
if (!update) { if (!update) {
photoThumbs = new ArrayList<PhotoObject>(); photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : messageOwner.action.photo.sizes) { 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()) { } else if (photoThumbs != null && !photoThumbs.isEmpty()) {
for (PhotoObject photoObject : photoThumbs) { for (PhotoObject photoObject : photoThumbs) {
@ -361,7 +385,7 @@ public class MessageObject {
if (!update) { if (!update) {
photoThumbs = new ArrayList<PhotoObject>(); photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : messageOwner.media.photo.sizes) { for (TLRPC.PhotoSize size : messageOwner.media.photo.sizes) {
PhotoObject obj = new PhotoObject(size, preview); PhotoObject obj = new PhotoObject(size, preview, isSecretMedia());
photoThumbs.add(obj); photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) { if (imagePreview == null && obj.image != null) {
imagePreview = obj.image; imagePreview = obj.image;
@ -383,7 +407,7 @@ public class MessageObject {
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaVideo) { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
if (!update) { if (!update) {
photoThumbs = new ArrayList<PhotoObject>(); 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); photoThumbs.add(obj);
if (imagePreview == null && obj.image != null) { if (imagePreview == null && obj.image != null) {
imagePreview = obj.image; imagePreview = obj.image;
@ -396,7 +420,7 @@ public class MessageObject {
if (!(messageOwner.media.document.thumb instanceof TLRPC.TL_photoSizeEmpty)) { if (!(messageOwner.media.document.thumb instanceof TLRPC.TL_photoSizeEmpty)) {
if (!update) { if (!update) {
photoThumbs = new ArrayList<PhotoObject>(); 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); photoThumbs.add(obj);
} else if (photoThumbs != null && !photoThumbs.isEmpty() && messageOwner.media.document.thumb != null) { } else if (photoThumbs != null && !photoThumbs.isEmpty() && messageOwner.media.document.thumb != null) {
PhotoObject photoObject = photoThumbs.get(0); PhotoObject photoObject = photoThumbs.get(0);
@ -599,15 +623,46 @@ public class MessageObject {
} }
public boolean isOut() { public boolean isOut() {
return messageOwner.out; return (messageOwner.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
} }
public boolean isFromMe() { public boolean isFromMe() {
return messageOwner.from_id == UserConfig.getClientUserId(); return messageOwner.from_id == UserConfig.getClientUserId();
} }
public boolean isUnread () { public boolean isUnread() {
return messageOwner.unread; 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() { public long getDialogId() {
@ -635,4 +690,21 @@ public class MessageObject {
public boolean isSent() { public boolean isSent() {
return messageOwner.send_state == MESSAGE_SEND_STATE_SENT; 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.content.pm.PackageInfo;
import android.os.Build; import android.os.Build;
import android.text.Html; import android.text.Html;
import android.util.SparseArray;
import org.telegram.messenger.BuffersStorage; import org.telegram.messenger.BuffersStorage;
import org.telegram.messenger.ByteBufferDesc; import org.telegram.messenger.ByteBufferDesc;
@ -66,11 +67,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
private long updatesStartWaitTime = 0; private long updatesStartWaitTime = 0;
public ArrayList<TLRPC.Update> delayedEncryptedChatUpdates = new ArrayList<TLRPC.Update>(); public ArrayList<TLRPC.Update> delayedEncryptedChatUpdates = new ArrayList<TLRPC.Update>();
private boolean startingSecretChat = false; private boolean startingSecretChat = false;
private ArrayList<Integer> loadingFullUsers = new ArrayList<Integer>();
private ArrayList<Integer> loadedFullUsers = new ArrayList<Integer>();
private boolean gettingNewDeleteTask = false; private boolean gettingNewDeleteTask = false;
private int currentDeletingTaskTime = 0; private int currentDeletingTaskTime = 0;
private Long currentDeletingTask = null;
private ArrayList<Integer> currentDeletingTaskMids = null; private ArrayList<Integer> currentDeletingTaskMids = null;
private Runnable currentDeleteTaskRunnable = null;
public int totalDialogsCount = 0; public int totalDialogsCount = 0;
public boolean loadingDialogs = false; public boolean loadingDialogs = false;
@ -317,12 +320,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
delayedEncryptedChatUpdates.clear(); delayedEncryptedChatUpdates.clear();
blockedUsers.clear(); blockedUsers.clear();
sendingTypings.clear(); sendingTypings.clear();
loadingFullUsers.clear();
loadedFullUsers.clear();
updatesStartWaitTime = 0; updatesStartWaitTime = 0;
currentDeletingTaskTime = 0; currentDeletingTaskTime = 0;
currentDeletingTaskMids = null; currentDeletingTaskMids = null;
gettingNewDeleteTask = false; gettingNewDeleteTask = false;
currentDeletingTask = null;
loadingDialogs = false; loadingDialogs = false;
dialogsEndReached = false; dialogsEndReached = false;
gettingDifference = false; gettingDifference = false;
@ -337,6 +341,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter
startingSecretChat = false; startingSecretChat = false;
statusRequest = 0; statusRequest = 0;
statusSettingState = 0; statusSettingState = 0;
if (currentDeleteTaskRunnable != null) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
currentDeleteTaskRunnable = null;
}
addSupportUser(); addSupportUser();
} }
@ -383,6 +393,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
users.put(user.id, user); users.put(user.id, user);
if (user.id == UserConfig.getClientUserId()) { if (user.id == UserConfig.getClientUserId()) {
UserConfig.setCurrentUser(user); UserConfig.setCurrentUser(user);
UserConfig.saveConfig(true);
} }
if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) { if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) {
return true; 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) { 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; return;
} }
loadingFullUsers.add(user.id);
TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser(); TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser();
req.id = getInputUser(user); req.id = getInputUser(user);
long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@ -466,10 +482,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { 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; TLRPC.TL_userFull userFull = (TLRPC.TL_userFull)response;
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>(); ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(userFull.user); users.add(userFull.user);
putUsers(users, false); 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() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
if (currentDeletingTask == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) { if (currentDeletingTaskMids == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
getNewDeleteTask(null); 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() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { 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(); int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
if (currentDeletingTask != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) { if (currentDeletingTaskMids != null && (runnable || currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime)) {
currentDeletingTaskTime = 0; currentDeletingTaskTime = 0;
if (currentDeleteTaskRunnable != null && !runnable) {
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
}
currentDeleteTaskRunnable = null;
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -538,30 +578,44 @@ public class MessagesController implements NotificationCenter.NotificationCenter
Utilities.stageQueue.postRunnable(new Runnable() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
getNewDeleteTask(currentDeletingTask); getNewDeleteTask(currentDeletingTaskMids);
currentDeletingTaskTime = 0; 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() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
gettingNewDeleteTask = false; gettingNewDeleteTask = false;
if (taskId != null) { if (messages != null) {
currentDeletingTaskTime = taskTime; currentDeletingTaskTime = taskTime;
currentDeletingTask = taskId;
currentDeletingTaskMids = messages; 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 { } else {
currentDeletingTaskTime = 0; currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null; currentDeletingTaskMids = null;
} }
} }
@ -926,7 +980,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, messages); NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, messages);
if (randoms != null && encryptedChat != null && !randoms.isEmpty()) { if (randoms != null && encryptedChat != null && !randoms.isEmpty()) {
SendMessagesHelper.getInstance().sendMessagesDeleteMessage(randoms, encryptedChat); SendMessagesHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, randoms, null);
} }
ArrayList<Integer> toSend = new ArrayList<Integer>(); ArrayList<Integer> toSend = new ArrayList<Integer>();
@ -1017,7 +1071,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}); });
} else { } else {
if (onlyHistory) { if (onlyHistory) {
SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id)); SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id), null);
} else { } else {
declineSecretChat(high_id); declineSecretChat(high_id);
} }
@ -1066,7 +1120,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public void updateTimerProc() { public void updateTimerProc() {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
checkDeletingTask(); checkDeletingTask(false);
if (UserConfig.isClientActivated()) { if (UserConfig.isClientActivated()) {
if (ConnectionsManager.getInstance().getPauseTime() == 0 && ApplicationLoader.isScreenOn && !ApplicationLoader.mainInterfacePaused) { 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; int lower_part = (int)dialog_id;
if (fromCache || lower_part == 0) { 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 { } else {
TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory(); TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory();
if (lower_part < 0) { if (lower_part < 0) {
@ -1303,7 +1357,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public void run(TLObject response, TLRPC.TL_error error) { public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) { if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; 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() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -1320,10 +1374,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
MessagesStorage.getInstance().putMessages(messagesRes, dialog_id); MessagesStorage.getInstance().putMessages(messagesRes, dialog_id);
} }
if (lower_id != 0 && isCache && messagesRes.messages.size() == 0 && !isForward) { if (lower_id != 0 && isCache && messagesRes.messages.size() == 0 && !isForward) {
if (semaphore != null) {
semaphore.release();
}
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { 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; return;
@ -1337,14 +1394,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.dialog_id = dialog_id; message.dialog_id = dialog_id;
objects.add(new MessageObject(message, usersLocal, 2)); objects.add(new MessageObject(message, usersLocal, 2));
} }
AndroidUtilities.RunOnUIThread(new Runnable() { if (semaphore != null) {
@Override putUsers(messagesRes.users, isCache);
public void run() { putChats(messagesRes.chats, isCache);
putUsers(messagesRes.users, isCache); NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDidLoaded, dialog_id, count, objects, isCache, first_unread, last_unread, unread_count, last_date, isForward);
putChats(messagesRes.chats, isCache); semaphore.release();
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDidLoaded, dialog_id, count, objects, isCache, first_unread, last_unread, unread_count, last_date, isForward); } else {
} AndroidUtilities.RunOnUIThread(new Runnable() {
}); @Override
public void run() {
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);
}
});
}
} }
}); });
} }
@ -1579,6 +1643,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
putChats(dialogsRes.chats, isCache); putChats(dialogsRes.chats, isCache);
if (encChats != null) { if (encChats != null) {
for (TLRPC.EncryptedChat encryptedChat : encChats) { 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); 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) { 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 lower_part = (int)dialog_id;
int high_id = (int)(dialog_id >> 32); int high_id = (int)(dialog_id >> 32);
@ -1756,18 +1843,17 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (chat.ttl > 0 && was) { if (chat.ttl > 0 && was) {
int serverTime = Math.max(ConnectionsManager.getInstance().getCurrentTime(), max_date); 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() { private void processPendingEncMessages() {
if (pendingEncMessagesToDelete.isEmpty()) { if (!pendingEncMessagesToDelete.isEmpty()) {
return; ArrayList<Long> arr = new ArrayList<Long>(pendingEncMessagesToDelete);
MessagesStorage.getInstance().markMessagesAsDeletedByRandoms(arr);
pendingEncMessagesToDelete.clear();
} }
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) { public long createChat(String title, ArrayList<Integer> selectedContacts, final TLRPC.InputFile uploadedAvatar, boolean isBroadcast) {
@ -1803,11 +1889,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMsg.action = new TLRPC.TL_messageActionCreatedBroadcastList(); newMsg.action = new TLRPC.TL_messageActionCreatedBroadcastList();
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.getClientUserId(); newMsg.from_id = UserConfig.getClientUserId();
newMsg.unread = false;
newMsg.dialog_id = AndroidUtilities.makeBroadcastId(chat.id); newMsg.dialog_id = AndroidUtilities.makeBroadcastId(chat.id);
newMsg.to_id = new TLRPC.TL_peerChat(); newMsg.to_id = new TLRPC.TL_peerChat();
newMsg.to_id.chat_id = chat.id; newMsg.to_id.chat_id = chat.id;
newMsg.out = false;
newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
newMsg.random_id = 0; newMsg.random_id = 0;
UserConfig.saveConfig(false); UserConfig.saveConfig(false);
@ -2570,7 +2654,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.message = updates.message; message.message = updates.message;
message.date = updates.date; message.date = updates.date;
message.flags = TLRPC.MESSAGE_FLAG_UNREAD; message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
message.unread = true;
message.media = new TLRPC.TL_messageMediaEmpty(); message.media = new TLRPC.TL_messageMediaEmpty();
MessagesStorage.lastSeqValue = updates.seq; MessagesStorage.lastSeqValue = updates.seq;
MessagesStorage.lastPtsValue = updates.pts; MessagesStorage.lastPtsValue = updates.pts;
@ -2635,7 +2718,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.to_id.user_id = updates.from_id; message.to_id.user_id = updates.from_id;
message.message = updates.message; message.message = updates.message;
message.date = updates.date; message.date = updates.date;
message.unread = true;
message.flags = TLRPC.MESSAGE_FLAG_UNREAD; message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
message.media = new TLRPC.TL_messageMediaEmpty(); message.media = new TLRPC.TL_messageMediaEmpty();
MessagesStorage.lastSeqValue = updates.seq; MessagesStorage.lastSeqValue = updates.seq;
@ -2914,13 +2996,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.action = new TLRPC.TL_messageActionUserJoined(); newMessage.action = new TLRPC.TL_messageActionUserJoined();
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false); UserConfig.saveConfig(false);
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.date = update.date; newMessage.date = update.date;
newMessage.from_id = update.user_id; newMessage.from_id = update.user_id;
newMessage.to_id = new TLRPC.TL_peerUser(); newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = update.user_id; newMessage.dialog_id = update.user_id;
messagesArr.add(newMessage); messagesArr.add(newMessage);
@ -2960,13 +3040,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.action.address = update.location; newMessage.action.address = update.location;
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false); UserConfig.saveConfig(false);
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.date = update.date; newMessage.date = update.date;
newMessage.from_id = 777000; newMessage.from_id = 777000;
newMessage.to_id = new TLRPC.TL_peerUser(); newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = 777000; newMessage.dialog_id = 777000;
messagesArr.add(newMessage); messagesArr.add(newMessage);
@ -3099,6 +3177,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newChat.user_id = exist.user_id; newChat.user_id = exist.user_id;
newChat.auth_key = exist.auth_key; newChat.auth_key = exist.auth_key;
newChat.ttl = exist.ttl; newChat.ttl = exist.ttl;
newChat.seq_in = exist.seq_in;
newChat.seq_out = exist.seq_out;
putEncryptedChat(newChat, false); putEncryptedChat(newChat, false);
} }
MessagesStorage.getInstance().updateEncryptedChat(newChat); MessagesStorage.getInstance().updateEncryptedChat(newChat);
@ -3135,6 +3215,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}); });
} else if (update instanceof TLRPC.TL_updateNotifySettings) { } else if (update instanceof TLRPC.TL_updateNotifySettings) {
updatesOnMainThread.add(update); updatesOnMainThread.add(update);
} else if (update instanceof TLRPC.TL_updateServiceNotification) {
//TODO
} }
} }
if (!messages.isEmpty()) { if (!messages.isEmpty()) {
@ -3203,9 +3285,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (currentUser != null) { if (currentUser != null) {
currentUser.first_name = update.first_name; currentUser.first_name = update.first_name;
currentUser.last_name = update.last_name; currentUser.last_name = update.last_name;
currentUser.username = update.username;
} }
toDbUser.first_name = update.first_name; toDbUser.first_name = update.first_name;
toDbUser.last_name = update.last_name; toDbUser.last_name = update.last_name;
toDbUser.username = update.username;
dbUsers.add(toDbUser); dbUsers.add(toDbUser);
} else if (update instanceof TLRPC.TL_updateUserPhoto) { } else if (update instanceof TLRPC.TL_updateUserPhoto) {
if (currentUser != null) { if (currentUser != null) {
@ -3295,7 +3379,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
for (Integer id : markAsReadMessages) { for (Integer id : markAsReadMessages) {
MessageObject obj = dialogMessage.get(id); MessageObject obj = dialogMessage.get(id);
if (obj != null) { if (obj != null) {
obj.messageOwner.unread = false; obj.setIsRead();
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE; updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
} }
} }
@ -3308,7 +3392,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (dialog != null) { if (dialog != null) {
MessageObject message = dialogMessage.get(dialog.top_message); MessageObject message = dialogMessage.get(dialog.top_message);
if (message != null && message.messageOwner.date <= entry.getValue()) { if (message != null && message.messageOwner.date <= entry.getValue()) {
message.messageOwner.unread = false; message.setIsRead();
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE; updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
} }
} }
@ -3345,7 +3429,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} }
if (!tasks.isEmpty()) { if (!tasks.isEmpty()) {
for (TLRPC.TL_updateEncryptedMessagesRead update : tasks) { 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) { public TLRPC.Message decryptMessage(TLRPC.EncryptedMessage message) {
TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id); final TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id);
if (chat == null) { if (chat == null || chat instanceof TLRPC.TL_encryptedChatDiscarded) {
return null; return null;
} }
ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length); ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length);
@ -3496,9 +3580,53 @@ public class MessagesController implements NotificationCenter.NotificationCenter
from_id = chat.participant_id; 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) { if (object instanceof TLRPC.TL_decryptedMessage) {
TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object; 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.message = decryptedMessage.message;
newMessage.date = message.date; newMessage.date = message.date;
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
@ -3508,10 +3636,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newMessage.random_id = message.random_id; newMessage.random_id = message.random_id;
newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.out = false;
newMessage.unread = true;
newMessage.dialog_id = ((long)chat.id) << 32; newMessage.dialog_id = ((long)chat.id) << 32;
newMessage.ttl = chat.ttl;
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) { if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) {
newMessage.media = new TLRPC.TL_messageMediaEmpty(); newMessage.media = new TLRPC.TL_messageMediaEmpty();
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) { } 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.date = newMessage.date;
newMessage.media.photo.caption = ""; newMessage.media.photo.caption = "";
newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); 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(); TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize();
small.w = decryptedMessage.media.thumb_w; small.w = decryptedMessage.media.thumb_w;
small.h = decryptedMessage.media.thumb_h; small.h = decryptedMessage.media.thumb_h;
@ -3564,7 +3689,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} }
newMessage.media = new TLRPC.TL_messageMediaVideo(); newMessage.media = new TLRPC.TL_messageMediaVideo();
newMessage.media.video = new TLRPC.TL_videoEncrypted(); 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 = new TLRPC.TL_photoCachedSize();
newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb; newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb;
newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w; 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.key = decryptedMessage.media.key;
newMessage.media.video.iv = decryptedMessage.media.iv; newMessage.media.video.iv = decryptedMessage.media.iv;
newMessage.media.video.mime_type = decryptedMessage.media.mime_type; 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) { if (newMessage.media.video.mime_type == null) {
newMessage.media.video.mime_type = "video/mp4"; 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.size = message.file.size;
newMessage.media.document.key = decryptedMessage.media.key; newMessage.media.document.key = decryptedMessage.media.key;
newMessage.media.document.iv = decryptedMessage.media.iv; 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 = new TLRPC.TL_photoCachedSize();
newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb; newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb;
newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w; 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.dc_id = message.file.dc_id;
newMessage.media.audio.duration = decryptedMessage.media.duration; newMessage.media.audio.duration = decryptedMessage.media.duration;
newMessage.media.audio.mime_type = decryptedMessage.media.mime_type; 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) { if (newMessage.media.audio.mime_type == null) {
newMessage.media.audio.mime_type = "audio/ogg"; newMessage.media.audio.mime_type = "audio/ogg";
} }
@ -3642,29 +3773,29 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} }
return newMessage; return newMessage;
} else if (object instanceof TLRPC.TL_decryptedMessageService) { } 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) { if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService();
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
newMessage.action = new TLRPC.TL_messageActionTTLChange(); newMessage.action = new TLRPC.TL_messageEncryptedAction();
newMessage.action.ttl = chat.ttl = serviceMessage.action.ttl_seconds; if (serviceMessage.action.ttl_seconds < 0 || serviceMessage.action.ttl_seconds > 60 * 60 * 24 * 365) {
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { serviceMessage.action.ttl_seconds = 60 * 60 * 24 * 365;
newMessage.action = new TLRPC.TL_messageEcryptedAction(); }
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; newMessage.action.encryptedAction = serviceMessage.action;
} else {
return null;
} }
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false); UserConfig.saveConfig(false);
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
newMessage.unread = true;
newMessage.date = message.date; newMessage.date = message.date;
newMessage.from_id = from_id; newMessage.from_id = from_id;
newMessage.to_id = new TLRPC.TL_peerUser(); newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.getClientUserId(); newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.out = false;
newMessage.dialog_id = ((long)chat.id) << 32; newMessage.dialog_id = ((long)chat.id) << 32;
MessagesStorage.getInstance().updateEncryptedChatTTL(chat);
return newMessage; return newMessage;
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) {
final long did = ((long)chat.id) << 32; final long did = ((long)chat.id) << 32;
@ -3701,6 +3832,25 @@ public class MessagesController implements NotificationCenter.NotificationCenter
pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids); pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids);
} }
return null; 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 { } else {
return null; return null;
} }
@ -3747,12 +3897,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
long fingerprint = Utilities.bytesToLong(authKeyId); long fingerprint = Utilities.bytesToLong(authKeyId);
if (encryptedChat.key_fingerprint == fingerprint) { if (encryptedChat.key_fingerprint == fingerprint) {
encryptedChat.auth_key = authKey; encryptedChat.auth_key = authKey;
encryptedChat.seq_in = 0;
encryptedChat.seq_out = 1;
MessagesStorage.getInstance().updateEncryptedChat(encryptedChat); MessagesStorage.getInstance().updateEncryptedChat(encryptedChat);
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
putEncryptedChat(encryptedChat, false); putEncryptedChat(encryptedChat, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat); NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat);
SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null);
} }
}); });
} else { } else {
@ -3760,6 +3913,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
newChat.id = encryptedChat.id; newChat.id = encryptedChat.id;
newChat.user_id = encryptedChat.user_id; newChat.user_id = encryptedChat.user_id;
newChat.auth_key = encryptedChat.auth_key; newChat.auth_key = encryptedChat.auth_key;
newChat.seq_in = encryptedChat.seq_in;
newChat.seq_out = encryptedChat.seq_out;
MessagesStorage.getInstance().updateEncryptedChat(newChat); MessagesStorage.getInstance().updateEncryptedChat(newChat);
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
@ -3813,6 +3968,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]); salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]);
} }
encryptedChat.a_or_b = salt; encryptedChat.a_or_b = salt;
encryptedChat.seq_in = 1;
encryptedChat.seq_out = 0;
BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes);
BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG); BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG);
g_b = g_b.modPow(new BigInteger(1, salt), p); 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; final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat) response;
newChat.auth_key = encryptedChat.auth_key; newChat.auth_key = encryptedChat.auth_key;
newChat.user_id = encryptedChat.user_id; newChat.user_id = encryptedChat.user_id;
newChat.seq_in = encryptedChat.seq_in;
newChat.seq_out = encryptedChat.seq_out;
MessagesStorage.getInstance().updateEncryptedChat(newChat); MessagesStorage.getInstance().updateEncryptedChat(newChat);
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
putEncryptedChat(newChat, false); putEncryptedChat(newChat, false);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); 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; TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) response;
chat.user_id = chat.participant_id; chat.user_id = chat.participant_id;
putEncryptedChat(chat, false); chat.seq_in = 0;
chat.seq_out = 1;
chat.a_or_b = salt; chat.a_or_b = salt;
putEncryptedChat(chat, false);
TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); TLRPC.TL_dialog dialog = new TLRPC.TL_dialog();
dialog.id = ((long) chat.id) << 32; dialog.id = ((long) chat.id) << 32;
dialog.unread_count = 0; dialog.unread_count = 0;
@ -4012,7 +4174,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
} }
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); 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.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
builder.show().setCanceledOnTouchOutside(true); builder.show().setCanceledOnTouchOutside(true);
} }

View File

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

View File

@ -41,6 +41,7 @@ public class NotificationCenter {
public static final int openedChatChanged = 29; public static final int openedChatChanged = 29;
public static final int hideEmojiKeyboard = 30; public static final int hideEmojiKeyboard = 30;
public static final int stopEncodingService = 31; public static final int stopEncodingService = 31;
public static final int didCreatedNewDeleteTask = 32;
public static final int wallpapersDidLoaded = 171; public static final int wallpapersDidLoaded = 171;
public static final int closeOtherAppActivities = 702; public static final int closeOtherAppActivities = 702;
@ -67,6 +68,7 @@ public class NotificationCenter {
public final static int screenshotTook = 50007; public final static int screenshotTook = 50007;
public final static int albumsDidLoaded = 50008; public final static int albumsDidLoaded = 50008;
public final static int audioDidSent = 50009; public final static int audioDidSent = 50009;
public final static int audioDidStarted = 50010;
final private HashMap<Integer, ArrayList<Object>> observers = new HashMap<Integer, ArrayList<Object>>(); 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 TLRPC.PhotoSize photoOwner;
public Bitmap image; public Bitmap image;
public PhotoObject(TLRPC.PhotoSize photo, int preview) { public PhotoObject(TLRPC.PhotoSize photo, int preview, boolean secret) {
photoOwner = photo; photoOwner = photo;
if (preview != 0 && photo instanceof TLRPC.TL_photoCachedSize) { 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); image = BitmapFactory.decodeByteArray(photoOwner.bytes, 0, photoOwner.bytes.length, opts);
if (image != null) { if (image != null) {
if (preview == 2) { 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) { if (ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackFree(image.getRowBytes() * image.getHeight()); 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) { public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.FileUploadProgressChanged) { if (id == NotificationCenter.FileUploadProgressChanged) {
String fileName = (String)args[0]; String fileName = (String)args[0];
if (path.equals(fileName)) { if (path != null && path.equals(fileName)) {
Float progress = (Float) args[1]; Float progress = (Float) args[1];
Boolean enc = (Boolean) args[2]; Boolean enc = (Boolean) args[2];
currentProgress = (int)(progress * 100); currentProgress = (int)(progress * 100);

View File

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

View File

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

View File

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

View File

@ -176,7 +176,7 @@ public class FileLoader {
} }
if (small) { if (small) {
currentUploadSmallOperationsCount--; currentUploadSmallOperationsCount--;
if (currentUploadSmallOperationsCount < 2) { if (currentUploadSmallOperationsCount < 1) {
FileUploadOperation operation = uploadSmallOperationQueue.poll(); FileUploadOperation operation = uploadSmallOperationQueue.poll();
if (operation != null) { if (operation != null) {
currentUploadSmallOperationsCount++; currentUploadSmallOperationsCount++;
@ -185,7 +185,7 @@ public class FileLoader {
} }
} else { } else {
currentUploadOperationsCount--; currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) { if (currentUploadOperationsCount < 1) {
FileUploadOperation operation = uploadOperationQueue.poll(); FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) { if (operation != null) {
currentUploadOperationsCount++; currentUploadOperationsCount++;
@ -227,7 +227,7 @@ public class FileLoader {
}); });
if (small) { if (small) {
currentUploadSmallOperationsCount--; currentUploadSmallOperationsCount--;
if (currentUploadSmallOperationsCount < 2) { if (currentUploadSmallOperationsCount < 1) {
FileUploadOperation operation = uploadSmallOperationQueue.poll(); FileUploadOperation operation = uploadSmallOperationQueue.poll();
if (operation != null) { if (operation != null) {
currentUploadSmallOperationsCount++; currentUploadSmallOperationsCount++;
@ -236,7 +236,7 @@ public class FileLoader {
} }
} else { } else {
currentUploadOperationsCount--; currentUploadOperationsCount--;
if (currentUploadOperationsCount < 2) { if (currentUploadOperationsCount < 1) {
FileUploadOperation operation = uploadOperationQueue.poll(); FileUploadOperation operation = uploadOperationQueue.poll();
if (operation != null) { if (operation != null) {
currentUploadOperationsCount++; currentUploadOperationsCount++;
@ -259,14 +259,14 @@ public class FileLoader {
} }
}; };
if (small) { if (small) {
if (currentUploadSmallOperationsCount < 2) { if (currentUploadSmallOperationsCount < 1) {
currentUploadSmallOperationsCount++; currentUploadSmallOperationsCount++;
operation.start(); operation.start();
} else { } else {
uploadSmallOperationQueue.add(operation); uploadSmallOperationQueue.add(operation);
} }
} else { } else {
if (currentUploadOperationsCount < 2) { if (currentUploadOperationsCount < 1) {
currentUploadOperationsCount++; currentUploadOperationsCount++;
operation.start(); operation.start();
} else { } else {
@ -564,18 +564,30 @@ public class FileLoader {
if (message == null) { if (message == null) {
return new File(""); return new File("");
} }
if (message.media instanceof TLRPC.TL_messageMediaVideo) { if (message instanceof TLRPC.TL_messageService) {
return getPathToAttach(message.media.video); if (message.action.photo != null) {
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) { ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
return getPathToAttach(message.media.document); if (sizes.size() > 0) {
} else if (message.media instanceof TLRPC.TL_messageMediaAudio) { TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
return getPathToAttach(message.media.audio); if (sizeFull != null) {
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { return getPathToAttach(sizeFull);
ArrayList<TLRPC.PhotoSize> sizes = message.media.photo.sizes; }
if (sizes.size() > 0) { }
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize()); }
if (sizeFull != null) { } else {
return getPathToAttach(sizeFull); if (message.media instanceof TLRPC.TL_messageMediaVideo) {
return getPathToAttach(message.media.video);
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
return getPathToAttach(message.media.document);
} else if (message.media instanceof TLRPC.TL_messageMediaAudio) {
return getPathToAttach(message.media.audio);
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
if (sizeFull != null) {
return getPathToAttach(sizeFull);
}
} }
} }
} }
@ -692,4 +704,26 @@ public class FileLoader {
} }
return ""; 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_updateReadMessages.constructor, TLRPC.TL_updateReadMessages.class);
classStore.put(TLRPC.TL_updateChatParticipantDelete.constructor, TLRPC.TL_updateChatParticipantDelete.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_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_updateNotifySettings.constructor, TLRPC.TL_updateNotifySettings.class);
classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class); classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class);
classStore.put(TLRPC.TL_updateChatUserTyping.constructor, TLRPC.TL_updateChatUserTyping.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_inputEncryptedFileEmpty.constructor, TLRPC.TL_inputEncryptedFileEmpty.class);
classStore.put(TLRPC.TL_inputEncryptedFileUploaded.constructor, TLRPC.TL_inputEncryptedFileUploaded.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_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_decryptedMessageActionNotifyLayer.constructor, TLRPC.TL_decryptedMessageActionNotifyLayer.class);
classStore.put(TLRPC.TL_decryptedMessageActionSetMessageTTL.constructor, TLRPC.TL_decryptedMessageActionSetMessageTTL.class); classStore.put(TLRPC.TL_decryptedMessageActionSetMessageTTL.constructor, TLRPC.TL_decryptedMessageActionSetMessageTTL.class);
classStore.put(TLRPC.TL_decryptedMessageActionDeleteMessages.constructor, TLRPC.TL_decryptedMessageActionDeleteMessages.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_messageService_old.constructor, TLRPC.TL_messageService_old.class);
classStore.put(TLRPC.TL_decryptedMessageService_old.constructor, TLRPC.TL_decryptedMessageService_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_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; static TLClassStore store = null;

View File

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

View File

@ -9,7 +9,6 @@
package org.telegram.messenger; package org.telegram.messenger;
import android.app.Activity; import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -28,7 +27,6 @@ import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.CrashManagerListener; import net.hockeyapp.android.CrashManagerListener;
import net.hockeyapp.android.UpdateManager; import net.hockeyapp.android.UpdateManager;
import org.telegram.android.LocaleController;
import org.telegram.ui.ApplicationLoader; import org.telegram.ui.ApplicationLoader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -74,8 +72,6 @@ public class Utilities {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static ProgressDialog progressDialog;
static { static {
try { try {
File URANDOM_FILE = new File("/dev/urandom"); File URANDOM_FILE = new File("/dev/urandom");
@ -112,7 +108,7 @@ public class Utilities {
public native static long doPQNative(long _what); 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 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); 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); 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; 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 { public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException {
OutputStream out = new FileOutputStream(destFile); OutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[4096]; 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; import android.widget.BaseAdapter;
public class BaseFragmentAdapter extends BaseAdapter { public class BaseFragmentAdapter extends BaseAdapter {
public void onFragmentCreate() { public void onFragmentCreate() {
} }

View File

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

View File

@ -9,10 +9,13 @@
package org.telegram.ui.Adapters; package org.telegram.ui.Adapters;
import android.content.Context; import android.content.Context;
import android.text.Html;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.telegram.android.AndroidUtilities; import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.android.ContactsController; import org.telegram.android.ContactsController;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
@ -20,28 +23,34 @@ import org.telegram.android.MessagesController;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
import org.telegram.ui.Cells.ChatOrUserCell; import org.telegram.ui.Cells.ChatOrUserCell;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
public class ContactsActivitySearchAdapter extends BaseFragmentAdapter { public class ContactsActivitySearchAdapter extends BaseContactsSearchAdapter {
private Context mContext; private Context mContext;
private HashMap<Integer, TLRPC.User> ignoreUsers; private HashMap<Integer, TLRPC.User> ignoreUsers;
private ArrayList<TLRPC.User> searchResult; private ArrayList<TLRPC.User> searchResult;
private ArrayList<CharSequence> searchResultNames; private ArrayList<CharSequence> searchResultNames;
private Timer searchTimer; 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; mContext = context;
ignoreUsers = arg1; ignoreUsers = arg1;
allowUsernameSearch = usernameSearch;
} }
public void searchDialogs(final String query) { public void searchDialogs(final String query) {
if (query == null) { if (query == null) {
searchResult = null; searchResult.clear();
searchResultNames = null; searchResultNames.clear();
if (allowUsernameSearch) {
queryServerSearch(null);
}
notifyDataSetChanged(); notifyDataSetChanged();
} else { } else {
try { try {
@ -63,7 +72,7 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
} }
processSearch(query); processSearch(query);
} }
}, 100, 300); }, 200, 300);
} }
} }
@ -71,6 +80,9 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (allowUsernameSearch) {
queryServerSearch(query);
}
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<TLRPC.TL_contact>(); final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<TLRPC.TL_contact>();
contactsCopy.addAll(ContactsController.getInstance().contacts); contactsCopy.addAll(ContactsController.getInstance().contacts);
Utilities.searchQueue.postRunnable(new Runnable() { Utilities.searchQueue.postRunnable(new Runnable() {
@ -87,12 +99,25 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
for (TLRPC.TL_contact contact : contactsCopy) { for (TLRPC.TL_contact contact : contactsCopy) {
TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id); TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id);
if (user.id == UserConfig.getClientUserId()) {
continue;
}
String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase(); String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
int found = 0;
if (name.startsWith(q) || name.contains(" " + q)) { if (name.startsWith(q) || name.contains(" " + q)) {
if (user.id == UserConfig.getClientUserId()) { found = 1;
continue; } 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));
} }
resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q));
resultArray.add(user); resultArray.add(user);
} }
} }
@ -117,28 +142,43 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override @Override
public boolean areAllItemsEnabled() { public boolean areAllItemsEnabled() {
return true; return false;
} }
@Override @Override
public boolean isEnabled(int i) { public boolean isEnabled(int i) {
return true; return i != searchResult.size();
} }
@Override @Override
public int getCount() { public int getCount() {
if (searchResult == null) { int count = searchResult.size();
return 0; 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 @Override
public TLRPC.User getItem(int i) { public TLRPC.User getItem(int i) {
if (searchResult != null) { int localCount = searchResult.size();
if (i >= 0 && i < searchResult.size()) { int globalCount = globalSearch.size();
return searchResult.get(i); if (i >= 0 && i < localCount) {
} return searchResult.get(i);
} else if (i > localCount && i <= globalCount + localCount) {
return globalSearch.get(i - localCount - 1);
} }
return null; return null;
} }
@ -155,24 +195,47 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override @Override
public View getView(int i, View view, ViewGroup viewGroup) { public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) { if (i == searchResult.size()) {
view = new ChatOrUserCell(mContext); if (view == null) {
((ChatOrUserCell)view).usePadding = false; 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).useSeparator = i != searchResult.size() - 1; ((ChatOrUserCell) view).useSeparator = (i != getCount() - 1 && i != searchResult.size() - 1);
TLRPC.User user = getItem(i);
if (user != 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);
}
}
Object obj = searchResult.get(i); ((ChatOrUserCell) view).setData(user, null, null, name, username);
TLRPC.User user = MessagesController.getInstance().getUser(((TLRPC.User)obj).id);
if (user != null) { if (ignoreUsers != null) {
((ChatOrUserCell)view).setData(user, null, null, searchResultNames.get(i), null); if (ignoreUsers.containsKey(user.id)) {
((ChatOrUserCell) view).drawAlpha = 0.5f;
if (ignoreUsers != null) { } else {
if (ignoreUsers.containsKey(user.id)) { ((ChatOrUserCell) view).drawAlpha = 1.0f;
((ChatOrUserCell)view).drawAlpha = 0.5f; }
} else {
((ChatOrUserCell)view).drawAlpha = 1.0f;
} }
} }
} }
@ -181,16 +244,19 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
@Override @Override
public int getItemViewType(int i) { public int getItemViewType(int i) {
if (i == searchResult.size()) {
return 1;
}
return 0; return 0;
} }
@Override @Override
public int getViewTypeCount() { public int getViewTypeCount() {
return 1; return 2;
} }
@Override @Override
public boolean isEmpty() { 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.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewConfiguration;
public class BaseCell extends View { 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) { public BaseCell(Context context) {
super(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) { protected void setDrawableBounds(Drawable drawable, int x, int y, int w, int h) {
drawable.setBounds(x, y, x + w, y + 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 static TextPaint timePaint;
private ImageReceiver avatarImage; private ImageReceiver avatarImage;
private boolean needAvatarImage = false;
private SeekBar seekBar; private SeekBar seekBar;
private ProgressView progressView; private ProgressView progressView;
private int seekBarX; private int seekBarX;
@ -44,9 +45,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
private int buttonState = 0; private int buttonState = 0;
private int buttonX; private int buttonX;
private int buttonY; private int buttonY;
private int buttonPressed = 0; private boolean buttonPressed = false;
private int avatarPressed = 0; private boolean avatarPressed = false;
private StaticLayout timeLayout; private StaticLayout timeLayout;
private int timeX; private int timeX;
@ -56,7 +57,6 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
public TLRPC.User audioUser; public TLRPC.User audioUser;
private TLRPC.FileLocation currentPhoto; private TLRPC.FileLocation currentPhoto;
private String currentNameString;
public ChatAudioCell(Context context) { public ChatAudioCell(Context context) {
super(context); super(context);
@ -115,40 +115,40 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
int side = AndroidUtilities.dp(36); int side = AndroidUtilities.dp(36);
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) { if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
buttonPressed = 1; buttonPressed = true;
invalidate(); invalidate();
result = true; result = true;
} else if (avatarImage.isInsideImage(x, y)) { } else if (needAvatarImage && avatarImage.isInsideImage(x, y)) {
avatarPressed = 1; avatarPressed = true;
result = true; result = true;
} }
} else if (buttonPressed == 1) { } else if (buttonPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_UP) {
buttonPressed = 0; buttonPressed = false;
playSoundEffect(SoundEffectConstants.CLICK); playSoundEffect(SoundEffectConstants.CLICK);
didPressedButton(); didPressedButton();
invalidate(); invalidate();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) { } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
buttonPressed = 0; buttonPressed = false;
invalidate(); invalidate();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) { } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) { if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) {
buttonPressed = 0; buttonPressed = false;
invalidate(); invalidate();
} }
} }
} else if (avatarPressed == 1) { } else if (avatarPressed) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_UP) {
avatarPressed = 0; avatarPressed = false;
playSoundEffect(SoundEffectConstants.CLICK); playSoundEffect(SoundEffectConstants.CLICK);
if (delegate != null) { if (delegate != null) {
delegate.didPressedUserAvatar(this, audioUser); delegate.didPressedUserAvatar(this, audioUser);
} }
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) { } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
avatarPressed = 0; avatarPressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) { } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!avatarImage.isInsideImage(x, y)) { if (!avatarImage.isInsideImage(x, y)) {
avatarPressed = 0; avatarPressed = false;
} }
} }
} }
@ -301,7 +301,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
int x; int x;
if (currentMessageObject.isOut()) { if (currentMessageObject.isOut()) {
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(9); x = layoutWidth - backgroundWidth + AndroidUtilities.dp(8);
seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(97); seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(97);
buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67); buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67);
timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(71); timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(71);
@ -318,11 +318,19 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
timeX = AndroidUtilities.dp(80); timeX = AndroidUtilities.dp(80);
} }
} }
avatarImage.setImageCoords(x, AndroidUtilities.dp(9), AndroidUtilities.dp(50), AndroidUtilities.dp(50)); 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); seekBar.height = AndroidUtilities.dp(30);
progressView.width = backgroundWidth - AndroidUtilities.dp(136); progressView.width = backgroundWidth - AndroidUtilities.dp(136) + diff;
progressView.height = AndroidUtilities.dp(30); progressView.height = AndroidUtilities.dp(30);
seekBarY = AndroidUtilities.dp(13); seekBarY = AndroidUtilities.dp(13);
buttonY = AndroidUtilities.dp(10); buttonY = AndroidUtilities.dp(10);
@ -349,14 +357,18 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
if (uid == 0) { if (uid == 0) {
uid = messageObject.messageOwner.from_id; 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); audioUser = MessagesController.getInstance().getUser(uid);
if (audioUser != null) {
if (audioUser.photo != null) { if (needAvatarImage) {
currentPhoto = audioUser.photo.photo_small; 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(null, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
} }
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);
} }
if (messageObject.isOut()) { if (messageObject.isOut()) {
@ -380,7 +392,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
return; return;
} }
avatarImage.draw(canvas, avatarImage.getImageX(), avatarImage.getImageY(), AndroidUtilities.dp(50), AndroidUtilities.dp(50)); if (needAvatarImage) {
avatarImage.draw(canvas);
}
canvas.save(); canvas.save();
if (buttonState == 0 || buttonState == 1) { if (buttonState == 0 || buttonState == 1) {
@ -399,7 +413,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
} else { } else {
timePaint.setColor(0xff70b15c); timePaint.setColor(0xff70b15c);
} }
Drawable buttonDrawable = statesDrawable[state][buttonPressed]; Drawable buttonDrawable = statesDrawable[state][buttonPressed ? 1 : 0];
int side = AndroidUtilities.dp(36); int side = AndroidUtilities.dp(36);
int x = (side - buttonDrawable.getIntrinsicWidth()) / 2; int x = (side - buttonDrawable.getIntrinsicWidth()) / 2;
int y = (side - buttonDrawable.getIntrinsicHeight()) / 2; int y = (side - buttonDrawable.getIntrinsicHeight()) / 2;

View File

@ -17,10 +17,8 @@ import android.text.Layout;
import android.text.StaticLayout; import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SoundEffectConstants; import android.view.SoundEffectConstants;
import android.view.ViewConfiguration;
import org.telegram.android.AndroidUtilities; import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController; import org.telegram.android.ContactsController;
@ -96,7 +94,7 @@ public class ChatBaseCell extends BaseCell {
private StaticLayout timeLayout; private StaticLayout timeLayout;
protected int timeWidth; protected int timeWidth;
protected int timeX; private int timeX;
private TextPaint currentTimePaint; private TextPaint currentTimePaint;
private String currentTimeString; private String currentTimeString;
protected boolean drawTime = true; protected boolean drawTime = true;
@ -108,58 +106,15 @@ public class ChatBaseCell extends BaseCell {
private TLRPC.User currentForwardUser; private TLRPC.User currentForwardUser;
private String currentForwardNameString; private String currentForwardNameString;
public ChatBaseCellDelegate delegate; protected ChatBaseCellDelegate delegate;
protected int namesOffset = 0; 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 int last_send_state = 0;
private int last_delete_date = 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);
}
}
}
}
public ChatBaseCell(Context context) { public ChatBaseCell(Context context) {
super(context); super(context);
init();
avatarImage = new ImageReceiver(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
avatarImage.clearImage();
currentPhoto = null;
}
private void init() {
if (backgroundDrawableIn == null) { if (backgroundDrawableIn == null) {
backgroundDrawableIn = getResources().getDrawable(R.drawable.msg_in); backgroundDrawableIn = getResources().getDrawable(R.drawable.msg_in);
backgroundDrawableInSelected = getResources().getDrawable(R.drawable.msg_in_selected); 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 = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
forwardNamePaint.setTextSize(AndroidUtilities.dp(14)); forwardNamePaint.setTextSize(AndroidUtilities.dp(14));
} }
avatarImage = new ImageReceiver(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
avatarImage.clearImage();
currentPhoto = null;
} }
@Override @Override
@ -206,6 +169,10 @@ public class ChatBaseCell extends BaseCell {
invalidate(); invalidate();
} }
public void setDelegate(ChatBaseCellDelegate delegate) {
this.delegate = delegate;
}
public void setCheckPressed(boolean value, boolean pressed) { public void setCheckPressed(boolean value, boolean pressed) {
isCheckPressed = value; isCheckPressed = value;
isPressed = pressed; isPressed = pressed;
@ -219,6 +186,9 @@ public class ChatBaseCell extends BaseCell {
if (last_send_state != currentMessageObject.messageOwner.send_state) { if (last_send_state != currentMessageObject.messageOwner.send_state) {
return true; return true;
} }
if (last_delete_date != currentMessageObject.messageOwner.destroyTime) {
return true;
}
TLRPC.User newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id); TLRPC.User newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id);
TLRPC.FileLocation newPhoto = null; TLRPC.FileLocation newPhoto = null;
@ -251,6 +221,7 @@ public class ChatBaseCell extends BaseCell {
public void setMessageObject(MessageObject messageObject) { public void setMessageObject(MessageObject messageObject) {
currentMessageObject = messageObject; currentMessageObject = messageObject;
last_send_state = messageObject.messageOwner.send_state; last_send_state = messageObject.messageOwner.send_state;
last_delete_date = messageObject.messageOwner.destroyTime;
isPressed = false; isPressed = false;
isCheckPressed = true; isCheckPressed = true;
isAvatarVisible = false; isAvatarVisible = false;
@ -344,27 +315,6 @@ public class ChatBaseCell extends BaseCell {
return backgroundWidth - AndroidUtilities.dp(8); 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 @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
boolean result = false; boolean result = false;
@ -461,6 +411,12 @@ public class ChatBaseCell extends BaseCell {
} }
@Override
protected void onLongPress() {
if (delegate != null) {
delegate.didLongPressed(this);
}
}
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
@ -474,7 +430,7 @@ public class ChatBaseCell extends BaseCell {
} }
if (isAvatarVisible) { if (isAvatarVisible) {
avatarImage.draw(canvas, AndroidUtilities.dp(6), layoutHeight - AndroidUtilities.dp(45), AndroidUtilities.dp(42), AndroidUtilities.dp(42)); avatarImage.draw(canvas);
} }
Drawable currentBackgroundDrawable = null; 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.AndroidUtilities;
import org.telegram.android.ImageLoader; import org.telegram.android.ImageLoader;
import org.telegram.android.LocaleController; import org.telegram.android.LocaleController;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLoader;
import org.telegram.android.MediaController; import org.telegram.android.MediaController;
import org.telegram.messenger.R; import org.telegram.messenger.R;
@ -41,7 +42,7 @@ import java.util.Locale;
public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener { public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener {
public static interface ChatMediaCellDelegate { public static interface ChatMediaCellDelegate {
public abstract void didPressedImage(ChatMediaCell cell); public abstract void didClickedImage(ChatMediaCell cell);
public abstract void didPressedOther(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 videoIconDrawable;
private static Drawable docMenuInDrawable; private static Drawable docMenuInDrawable;
private static Drawable docMenuOutDrawable; 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 Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][2];
private static TextPaint infoPaint; private static TextPaint infoPaint;
private static MessageObject lastDownloadedGifMessage = null; private static MessageObject lastDownloadedGifMessage = null;
private static TextPaint namePaint; private static TextPaint namePaint;
private static Paint docBackPaint; private static Paint docBackPaint;
private static Paint progressPaint; private static Paint progressPaint;
private static Paint deleteProgressPaint;
private static DecelerateInterpolator decelerateInterpolator; private static DecelerateInterpolator decelerateInterpolator;
private GifDrawable gifDrawable = null; private GifDrawable gifDrawable = null;
@ -91,7 +93,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private int nameWidth = 0; private int nameWidth = 0;
private String currentNameString; private String currentNameString;
public ChatMediaCellDelegate mediaDelegate = null; private ChatMediaCellDelegate mediaDelegate = null;
private float currentProgress = 0; private float currentProgress = 0;
private RectF progressRect = new RectF(); private RectF progressRect = new RectF();
@ -101,6 +103,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private float animatedProgressValue = 0; private float animatedProgressValue = 0;
private long currentProgressTime = 0; private long currentProgressTime = 0;
private float animationProgressStart = 0; private float animationProgressStart = 0;
private RectF deleteProgressRect = new RectF();
private int lastSecretSecondsLeft = 0;
public ChatMediaCell(Context context) { public ChatMediaCell(Context context) {
super(context); super(context);
@ -115,6 +119,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
buttonStatesDrawables[2] = getResources().getDrawable(R.drawable.photogif); buttonStatesDrawables[2] = getResources().getDrawable(R.drawable.photogif);
buttonStatesDrawables[3] = getResources().getDrawable(R.drawable.playvideo); buttonStatesDrawables[3] = getResources().getDrawable(R.drawable.playvideo);
buttonStatesDrawables[4] = getResources().getDrawable(R.drawable.photopause); 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[0][0] = getResources().getDrawable(R.drawable.docload_b);
buttonStatesDrawablesDoc[1][0] = getResources().getDrawable(R.drawable.doccancel_b); buttonStatesDrawablesDoc[1][0] = getResources().getDrawable(R.drawable.doccancel_b);
buttonStatesDrawablesDoc[2][0] = getResources().getDrawable(R.drawable.docpause_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.setStrokeCap(Paint.Cap.ROUND);
progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
deleteProgressPaint.setColor(0xffe4e2e0);
decelerateInterpolator = new DecelerateInterpolator(); decelerateInterpolator = new DecelerateInterpolator();
} }
@ -155,6 +165,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} }
} }
public void setMediaDelegate(ChatMediaCellDelegate delegate) {
this.mediaDelegate = delegate;
}
@Override @Override
protected void onDetachedFromWindow() { protected void onDetachedFromWindow() {
super.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(); startCheckLongPress();
} }
} }
@ -225,8 +241,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} else if (imagePressed) { } else if (imagePressed) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_UP) {
imagePressed = false; imagePressed = false;
playSoundEffect(SoundEffectConstants.CLICK); if (buttonState == -1 || buttonState == 2 || buttonState == 3) {
didPressedImage(); playSoundEffect(SoundEffectConstants.CLICK);
didClickedImage();
}
invalidate(); invalidate();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) { } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
imagePressed = false; imagePressed = false;
@ -269,11 +287,11 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
return result; return result;
} }
private void didPressedImage() { private void didClickedImage() {
if (currentMessageObject.type == 1) { if (currentMessageObject.type == 1) {
if (buttonState == -1) { if (buttonState == -1) {
if (mediaDelegate != null) { if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this); mediaDelegate.didClickedImage(this);
} }
} else if (buttonState == 0) { } else if (buttonState == 0) {
didPressedButton(); didPressedButton();
@ -294,12 +312,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} }
} else if (currentMessageObject.type == 4) { } else if (currentMessageObject.type == 4) {
if (mediaDelegate != null) { if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this); mediaDelegate.didClickedImage(this);
} }
} else if (currentMessageObject.type == 9) { } else if (currentMessageObject.type == 9) {
if (buttonState == -1) { if (buttonState == -1) {
if (mediaDelegate != null) { 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) { } else if (buttonState == 3) {
if (mediaDelegate != null) { if (mediaDelegate != null) {
mediaDelegate.didPressedImage(this); mediaDelegate.didClickedImage(this);
} }
} }
} }
@ -467,6 +485,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
currentNameString = null; currentNameString = null;
infoLayout = null; infoLayout = null;
nameLayout = null; nameLayout = null;
updateSecretTimeText();
} }
if (messageObject.type == 9) { if (messageObject.type == 9) {
@ -549,6 +568,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
w = timeWidthTotal; 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; photoWidth = w;
photoHeight = h; photoHeight = h;
backgroundWidth = w + AndroidUtilities.dp(12); backgroundWidth = w + AndroidUtilities.dp(12);
@ -589,6 +616,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
photoImage.setImageBitmap(messageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable); photoImage.setImageBitmap(messageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable);
} }
} }
photoImage.setForcePreview(messageObject.isSecretPhoto());
invalidate(); invalidate();
} }
@ -754,6 +782,25 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
buttonX = (int)(x + (photoWidth - size) / 2.0f); buttonX = (int)(x + (photoWidth - size) / 2.0f);
buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - 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)); 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 @Override
@ -766,7 +813,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
canvas.restore(); canvas.restore();
} else { } else {
photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false); photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false);
imageDrawn = photoImage.draw(canvas, photoImage.getImageX(), photoImage.getImageY(), photoWidth, photoHeight); imageDrawn = photoImage.draw(canvas);
drawTime = photoImage.getVisible(); drawTime = photoImage.getVisible();
} }
@ -826,6 +873,29 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
currentButtonDrawable.draw(canvas); 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) { if (progressVisible) {
canvas.drawArc(progressRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint); 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); infoLayout.draw(canvas);
canvas.restore(); 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); infoPaint.setColor(0xffffffff);
setDrawableBounds(mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dpf(16.5f)); setDrawableBounds(mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dpf(16.5f));
mediaBackgroundDrawable.draw(canvas); mediaBackgroundDrawable.draw(canvas);

View File

@ -43,36 +43,41 @@ public class ChatMessageCell extends ChatBaseCell {
y -= textY; y -= textY;
int blockNum = Math.max(0, y / currentMessageObject.blockHeight); int blockNum = Math.max(0, y / currentMessageObject.blockHeight);
if (blockNum < currentMessageObject.textLayoutBlocks.size()) { if (blockNum < currentMessageObject.textLayoutBlocks.size()) {
MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum); try {
x -= textX - (int)Math.ceil(block.textXOffset); MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
y -= block.textYOffset; x -= textX - (int)Math.ceil(block.textXOffset);
final int line = block.textLayout.getLineForVertical(y); y -= block.textYOffset;
final int off = block.textLayout.getOffsetForHorizontal(line, x) + block.charactersOffset; final int line = block.textLayout.getLineForVertical(y);
final int off = block.textLayout.getOffsetForHorizontal(line, x) + block.charactersOffset;
final float left = block.textLayout.getLineLeft(line); final float left = block.textLayout.getLineLeft(line);
if (left <= x && left + block.textLayout.getLineWidth(line) >= x) { if (left <= x && left + block.textLayout.getLineWidth(line) >= x) {
Spannable buffer = (Spannable)currentMessageObject.messageText; Spannable buffer = (Spannable)currentMessageObject.messageText;
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) { if (link.length != 0) {
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getAction() == MotionEvent.ACTION_DOWN) {
pressedLink = link[0]; pressedLink = link[0];
return true;
} else {
if (link[0] == pressedLink) {
try {
pressedLink.onClick(this);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return true; return true;
} else {
if (link[0] == pressedLink) {
try {
pressedLink.onClick(this);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return true;
}
} }
} else {
pressedLink = null;
} }
} else { } else {
pressedLink = null; pressedLink = null;
} }
} else { } catch (Exception e) {
pressedLink = null; pressedLink = null;
FileLog.e("tmessages", e);
} }
} else { } else {
pressedLink = null; pressedLink = null;

View File

@ -41,7 +41,7 @@ public class ChatOrUserCell extends BaseCell {
private CharSequence currentName; private CharSequence currentName;
private ImageReceiver avatarImage; private ImageReceiver avatarImage;
private String subLabel; private CharSequence subLabel;
private ChatOrUserCellLayout cellLayout; private ChatOrUserCellLayout cellLayout;
private TLRPC.User user = null; 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; currentName = n;
user = u; user = u;
chat = c; chat = c;
@ -236,6 +236,15 @@ public class ChatOrUserCell extends BaseCell {
return; 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) { if (drawAlpha != 1) {
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int)(255 * drawAlpha), Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); 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(); canvas.restore();
} }
avatarImage.draw(canvas, cellLayout.avatarLeft, cellLayout.avatarTop, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); avatarImage.draw(canvas);
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);
}
}
} }
private class ChatOrUserCellLayout { private class ChatOrUserCellLayout {
@ -381,7 +381,7 @@ public class ChatOrUserCell extends BaseCell {
onlineLeft = usePadding ? AndroidUtilities.dp(11) : 0; onlineLeft = usePadding ? AndroidUtilities.dp(11) : 0;
} }
String onlineString = ""; CharSequence onlineString = "";
TextPaint currentOnlinePaint = offlinePaint; TextPaint currentOnlinePaint = offlinePaint;
if (subLabel != null) { if (subLabel != null) {

View File

@ -10,6 +10,7 @@ package org.telegram.ui.Cells;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.Html; import android.text.Html;
import android.text.Layout; import android.text.Layout;
@ -48,6 +49,8 @@ public class DialogCell extends BaseCell {
private static Drawable groupDrawable; private static Drawable groupDrawable;
private static Drawable broadcastDrawable; private static Drawable broadcastDrawable;
private static Paint linePaint;
private TLRPC.TL_dialog currentDialog; private TLRPC.TL_dialog currentDialog;
private ImageReceiver avatarImage; private ImageReceiver avatarImage;
@ -57,6 +60,8 @@ public class DialogCell extends BaseCell {
private TLRPC.EncryptedChat encryptedChat = null; private TLRPC.EncryptedChat encryptedChat = null;
private CharSequence lastPrintString = null; private CharSequence lastPrintString = null;
public boolean useSeparator = false;
private void init() { private void init() {
if (namePaint == null) { if (namePaint == null) {
namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
@ -85,6 +90,11 @@ public class DialogCell extends BaseCell {
messagePaint.setColor(0xff808080); messagePaint.setColor(0xff808080);
} }
if (linePaint == null) {
linePaint = new Paint();
linePaint.setColor(0xffdcdcdc);
}
if (messagePrintingPaint == null) { if (messagePrintingPaint == null) {
messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
messagePrintingPaint.setTextSize(AndroidUtilities.dp(16)); messagePrintingPaint.setTextSize(AndroidUtilities.dp(16));
@ -340,7 +350,16 @@ public class DialogCell extends BaseCell {
canvas.restore(); 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 { 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.AvatarUpdater;
import org.telegram.ui.Views.BackupImageView; import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -476,6 +477,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
args.putBoolean("destroyAfterSelect", true); args.putBoolean("destroyAfterSelect", true);
args.putBoolean("usersAsSections", true); args.putBoolean("usersAsSections", true);
args.putBoolean("returnAsResult", true); args.putBoolean("returnAsResult", true);
//args.putBoolean("allowUsernameSearch", false);
if (chat_id > 0) { if (chat_id > 0) {
args.putString("selectAlertString", LocaleController.getString("AddToTheGroup", R.string.AddToTheGroup)); args.putString("selectAlertString", LocaleController.getString("AddToTheGroup", R.string.AddToTheGroup));
} }
@ -646,21 +648,19 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
return view; return view;
} else if (type == 1) { } else if (type == 1) {
if (view == null) { if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = new SettingsSectionLayout(mContext);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
} }
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == settingsSectionRow) { if (i == settingsSectionRow) {
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); ((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
} else if (i == sharedMediaSectionRow) { } 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) { } else if (i == membersSectionRow) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id); TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id);
int count = chat.participants_count; int count = chat.participants_count;
if (info != null) { if (info != null) {
count = info.participants.size(); count = info.participants.size();
} }
textView.setText(LocaleController.formatPluralString("Members", count).toUpperCase()); ((SettingsSectionLayout) view).setText(LocaleController.formatPluralString("Members", count).toUpperCase());
} }
} else if (type == 2) { } else if (type == 2) {
if (view == null) { if (view == null) {

View File

@ -11,6 +11,9 @@ package org.telegram.ui;
import android.app.Activity; import android.app.Activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -18,6 +21,7 @@ import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.telegram.android.AndroidUtilities; import org.telegram.android.AndroidUtilities;
@ -26,6 +30,7 @@ import org.telegram.messenger.TLRPC;
import org.telegram.android.MessagesController; import org.telegram.android.MessagesController;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
public class ChatProfileChangeNameActivity extends BaseFragment { public class ChatProfileChangeNameActivity extends BaseFragment {
private EditText firstNameField; private EditText firstNameField;
@ -71,16 +76,27 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text); TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase()); 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); TLRPC.Chat currentChat = MessagesController.getInstance().getChat(chat_id);
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field); fragmentView = new LinearLayout(inflater.getContext());
if (chat_id > 0) { fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName)); fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
} else { ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
firstNameField.setHint(LocaleController.getString("EnterListName", R.string.EnterListName));
} 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() { firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override @Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
@ -91,15 +107,25 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
return false; return false;
} }
}); });
firstNameField.setText(currentChat.title); if (LocaleController.isRTL) {
firstNameField.setSelection(firstNameField.length()); firstNameField.setGravity(Gravity.RIGHT);
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());
} }
((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 { } else {
ViewGroup parent = (ViewGroup)fragmentView.getParent(); ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) { if (parent != null) {

View File

@ -30,6 +30,7 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities; import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController; import org.telegram.android.LocaleController;
import org.telegram.android.MessagesStorage;
import org.telegram.messenger.TLObject; import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.ConnectionsManager;
@ -72,6 +73,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
private String inviteText; private String inviteText;
private boolean updatingInviteText = false; private boolean updatingInviteText = false;
private boolean allowUsernameSearch = true;
private ContactsActivityDelegate delegate; private ContactsActivityDelegate delegate;
public static interface ContactsActivityDelegate { public static interface ContactsActivityDelegate {
@ -91,11 +93,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatCreated); NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatCreated);
if (arguments != null) { if (arguments != null) {
onlyUsers = getArguments().getBoolean("onlyUsers", false); onlyUsers = getArguments().getBoolean("onlyUsers", false);
destroyAfterSelect = getArguments().getBoolean("destroyAfterSelect", false); destroyAfterSelect = arguments.getBoolean("destroyAfterSelect", false);
usersAsSections = getArguments().getBoolean("usersAsSections", false); usersAsSections = arguments.getBoolean("usersAsSections", false);
returnAsResult = getArguments().getBoolean("returnAsResult", false); returnAsResult = arguments.getBoolean("returnAsResult", false);
createSecretChat = getArguments().getBoolean("createSecretChat", false); createSecretChat = arguments.getBoolean("createSecretChat", false);
selectAlertString = arguments.getString("selectAlertString"); selectAlertString = arguments.getString("selectAlertString");
allowUsernameSearch = arguments.getBoolean("allowUsernameSearch", true);
} }
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); 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 = (TextView)fragmentView.findViewById(R.id.searchEmptyView);
emptyTextView.setText(LocaleController.getString("NoContacts", R.string.NoContacts)); 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 = (PinnedHeaderListView)fragmentView.findViewById(R.id.listView);
listView.setEmptyView(emptyTextView); listView.setEmptyView(emptyTextView);
@ -221,6 +224,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
if (user == null || user.id == UserConfig.getClientUserId()) { if (user == null || user.id == UserConfig.getClientUserId()) {
return; 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 (returnAsResult) {
if (ignoreUsers != null && ignoreUsers.containsKey(user.id)) { if (ignoreUsers != null && ignoreUsers.containsKey(user.id)) {
return; 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.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView; import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter; import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStream; import java.io.InputStream;
@ -484,12 +485,10 @@ public class CountrySelectActivity extends BaseFragment {
@Override @Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) { public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) { if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = new SettingsSectionLayout(mContext);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView.setBackgroundColor(0xfffafafa); convertView.setBackgroundColor(0xfffafafa);
} }
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text); ((SettingsSectionLayout) convertView).setText(sortedCountries.get(section).toUpperCase());
textView.setText(sortedCountries.get(section).toUpperCase());
return convertView; 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.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView; import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter; import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -597,15 +598,13 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
@Override @Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) { public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) { if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = new SettingsSectionLayout(mContext);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView.setBackgroundColor(0xffffffff); convertView.setBackgroundColor(0xffffffff);
} }
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
if (searching && searchWas) { if (searching && searchWas) {
textView.setText(LocaleController.getString("AllContacts", R.string.AllContacts)); ((SettingsSectionLayout) convertView).setText(LocaleController.getString("AllContacts", R.string.AllContacts));
} else { } else {
textView.setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section)); ((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
} }
return convertView; 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.ActionBar.BaseFragment;
import org.telegram.ui.Views.PinnedHeaderListView; import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter; import org.telegram.ui.Views.SectionedBaseAdapter;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
@ -81,11 +82,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
if (!usersToLoad.isEmpty()) { if (!usersToLoad.isEmpty()) {
final Semaphore semaphore = new Semaphore(0); final Semaphore semaphore = new Semaphore(0);
final ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>(); final ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
final boolean[] error = new boolean[1];
MessagesStorage.getInstance().storageQueue.postRunnable(new Runnable() { MessagesStorage.getInstance().storageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad, error)); users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad));
semaphore.release(); semaphore.release();
} }
}); });
@ -94,7 +94,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
if (error[0]) { if (usersToLoad.size() != users.size()) {
return false; return false;
} }
if (!users.isEmpty()) { if (!users.isEmpty()) {
@ -420,12 +420,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
@Override @Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) { public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) { if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = new SettingsSectionLayout(mContext);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView.setBackgroundColor(0xffffffff); convertView.setBackgroundColor(0xffffffff);
} }
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text); ((SettingsSectionLayout) convertView).setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
textView.setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
return convertView; return convertView;
} }
} }

View File

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

View File

@ -26,7 +26,6 @@ import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.android.LocaleController; import org.telegram.android.LocaleController;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.ActionBar.ActionBarLayer; import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu; import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
@ -55,7 +54,14 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
v.onDestroyActivity(); v.onDestroyActivity();
} }
} }
Utilities.HideProgressDialog(getParentActivity()); if (progressDialog != null) {
try {
progressDialog.dismiss();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
progressDialog = null;
}
} }
@Override @Override
@ -255,6 +261,7 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
progressDialog = null;
} }
public void setPage(int page, boolean animated, Bundle params, boolean back) { 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 @Override
public void onItemClick(int id) { public void onItemClick(int id) {
if (id == -1) { if (id == -1) {
if (Build.VERSION.SDK_INT < 11) { if (Build.VERSION.SDK_INT < 11 && listView != null) {
listView.setAdapter(null); listView.setAdapter(null);
listView = null; listView = null;
listAdapter = null; listAdapter = null;

View File

@ -12,6 +12,7 @@ import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -35,13 +36,14 @@ import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities; 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.ChatOrUserCell;
import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Views.ActionBar.ActionBarLayer; import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu; import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.ActionBarMenuItem; import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Timer; 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 int activityToken = (int)(Utilities.random.nextDouble() * Integer.MAX_VALUE);
private long selectedDialog; private long selectedDialog;
private Timer searchTimer;
public ArrayList<TLObject> searchResult;
public ArrayList<CharSequence> searchResultNames;
private MessagesActivityDelegate delegate; private MessagesActivityDelegate delegate;
private long openedDialogId = 0; private long openedDialogId = 0;
@ -144,7 +142,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override @Override
public void onSearchCollapse() { public void onSearchCollapse() {
searchDialogs(null);
searching = false; searching = false;
searchWas = false; searchWas = false;
if (messagesListView != null) { if (messagesListView != null) {
@ -152,14 +149,16 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
searchEmptyView.setVisibility(View.GONE); searchEmptyView.setVisibility(View.GONE);
} }
if (messagesListViewAdapter != null) { if (messagesListViewAdapter != null) {
messagesListViewAdapter.notifyDataSetChanged(); messagesListViewAdapter.searchDialogs(null);
} }
} }
@Override @Override
public void onTextChanged(EditText editText) { public void onTextChanged(EditText editText) {
String text = editText.getText().toString(); String text = editText.getText().toString();
searchDialogs(text); if (messagesListViewAdapter != null) {
messagesListViewAdapter.searchDialogs(text);
}
if (text.length() != 0) { if (text.length() != 0) {
searchWas = true; searchWas = true;
if (messagesListViewAdapter != null) { if (messagesListViewAdapter != null) {
@ -231,10 +230,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view); messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view);
messagesListView.setAdapter(messagesListViewAdapter); 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); progressView = fragmentView.findViewById(R.id.progressLayout);
messagesListViewAdapter.notifyDataSetChanged(); messagesListViewAdapter.notifyDataSetChanged();
@ -277,38 +272,34 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
messagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { messagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
long dialog_id = 0; if (messagesListViewAdapter == null) {
if (searching && searchWas) { return;
if (i >= searchResult.size()) {
return;
}
TLObject obj = searchResult.get(i);
if (obj instanceof TLRPC.User) {
dialog_id = ((TLRPC.User) obj).id;
} else if (obj instanceof TLRPC.Chat) {
if (((TLRPC.Chat) obj).id > 0) {
dialog_id = -((TLRPC.Chat) obj).id;
} else {
dialog_id = AndroidUtilities.makeBroadcastId(((TLRPC.Chat) obj).id);
}
} else if (obj instanceof TLRPC.EncryptedChat) {
dialog_id = ((long)((TLRPC.EncryptedChat) obj).id) << 32;
}
} 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;
}
} }
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;
} else {
dialog_id = AndroidUtilities.makeBroadcastId(((TLRPC.Chat) obj).id);
}
} 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;
}
if (onlySelect) { if (onlySelect) {
didSelectResult(dialog_id, true, false); didSelectResult(dialog_id, true, false);
} else { } else {
@ -497,7 +488,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
} else if (id == NotificationCenter.reloadSearchResults) { } else if (id == NotificationCenter.reloadSearchResults) {
int token = (Integer)args[0]; int token = (Integer)args[0];
if (token == activityToken) { 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) { } else if (id == NotificationCenter.appDidLogout) {
dialogsLoaded = false; dialogsLoaded = false;
@ -624,86 +615,113 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
} }
} }
public void updateSearchResults(final ArrayList<TLObject> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> encUsers) { private class MessagesAdapter extends BaseContactsSearchAdapter {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLObject obj : result) {
if (obj instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) obj;
MessagesController.getInstance().putUser(user, true);
} else if (obj instanceof TLRPC.Chat) {
TLRPC.Chat chat = (TLRPC.Chat) obj;
MessagesController.getInstance().putChat(chat, true);
} else if (obj instanceof TLRPC.EncryptedChat) {
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) obj;
MessagesController.getInstance().putEncryptedChat(chat, true);
}
}
for (TLRPC.User user : encUsers) {
MessagesController.getInstance().putUser(user, true);
}
searchResult = result;
searchResultNames = names;
if (searching) {
messagesListViewAdapter.notifyDataSetChanged();
}
}
});
}
public void searchDialogs(final String query) {
if (query == null) {
searchResult = null;
searchResultNames = null;
} else {
try {
if (searchTimer != null) {
searchTimer.cancel();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
searchTimer = new Timer();
searchTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
searchTimer.cancel();
searchTimer = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
MessagesStorage.getInstance().searchDialogs(activityToken, query, !serverOnly);
}
}, 100, 300);
}
}
private class MessagesAdapter extends BaseFragmentAdapter {
private Context mContext; private Context mContext;
private Timer searchTimer;
private ArrayList<TLObject> searchResult = new ArrayList<TLObject>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<CharSequence>();
public MessagesAdapter(Context context) { public MessagesAdapter(Context context) {
mContext = context; mContext = context;
} }
public void updateSearchResults(final ArrayList<TLObject> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> encUsers) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLObject obj : result) {
if (obj instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) obj;
MessagesController.getInstance().putUser(user, true);
} else if (obj instanceof TLRPC.Chat) {
TLRPC.Chat chat = (TLRPC.Chat) obj;
MessagesController.getInstance().putChat(chat, true);
} else if (obj instanceof TLRPC.EncryptedChat) {
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) obj;
MessagesController.getInstance().putEncryptedChat(chat, true);
}
}
for (TLRPC.User user : encUsers) {
MessagesController.getInstance().putUser(user, true);
}
searchResult = result;
searchResultNames = names;
if (searching) {
messagesListViewAdapter.notifyDataSetChanged();
}
}
});
}
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.clear();
searchResultNames.clear();
queryServerSearch(null);
notifyDataSetChanged();
} else {
try {
if (searchTimer != null) {
searchTimer.cancel();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
searchTimer = new Timer();
searchTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
searchTimer.cancel();
searchTimer = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
MessagesStorage.getInstance().searchDialogs(activityToken, query, !serverOnly);
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
queryServerSearch(query);
}
});
}
}, 200, 300);
}
}
@Override @Override
public boolean areAllItemsEnabled() { public boolean areAllItemsEnabled() {
return true; return false;
} }
@Override @Override
public boolean isEnabled(int i) { public boolean isEnabled(int i) {
return true; return !(searching && searchWas) || i != searchResult.size();
} }
@Override @Override
public int getCount() { public int getCount() {
if (searching && searchWas) { if (searching && searchWas) {
if (searchResult == null) { int count = searchResult.size();
return 0; int globalCount = globalSearch.size();
if (globalCount != 0) {
count += globalCount + 1;
} }
return searchResult.size(); return count;
} }
int count; int count;
if (serverOnly) { if (serverOnly) {
@ -721,8 +739,28 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
} }
@Override @Override
public Object getItem(int i) { public TLObject getItem(int i) {
return null; 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 @Override
@ -732,57 +770,86 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override @Override
public boolean hasStableIds() { public boolean hasStableIds() {
return false; return true;
} }
@Override @Override
public View getView(int i, View view, ViewGroup viewGroup) { 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) { if (view == null) {
view = new ChatOrUserCell(mContext); view = new ChatOrUserCell(mContext);
} }
TLRPC.User user = null; if (searching && searchWas) {
TLRPC.Chat chat = null; TLRPC.User user = null;
TLRPC.EncryptedChat encryptedChat = null; TLRPC.Chat chat = null;
TLRPC.EncryptedChat encryptedChat = null;
TLObject obj = searchResult.get(i); ((ChatOrUserCell) view).useSeparator = (i != getCount() - 1 && i != searchResult.size() - 1);
if (obj instanceof TLRPC.User) { TLObject obj = getItem(i);
user = MessagesController.getInstance().getUser(((TLRPC.User)obj).id); if (obj instanceof TLRPC.User) {
} else if (obj instanceof TLRPC.Chat) { user = MessagesController.getInstance().getUser(((TLRPC.User) obj).id);
chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id); if (user == null) {
} else if (obj instanceof TLRPC.EncryptedChat) { user = (TLRPC.User) obj;
encryptedChat = MessagesController.getInstance().getEncryptedChat(((TLRPC.EncryptedChat) obj).id); }
user = MessagesController.getInstance().getUser(encryptedChat.user_id); } else if (obj instanceof TLRPC.Chat) {
chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id);
} else if (obj instanceof TLRPC.EncryptedChat) {
encryptedChat = MessagesController.getInstance().getEncryptedChat(((TLRPC.EncryptedChat) obj).id);
user = MessagesController.getInstance().getUser(encryptedChat.user_id);
}
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 != 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) {
((ChatOrUserCell)view).setData(user, chat, encryptedChat, searchResultNames.get(i), null);
return view;
}
int type = getItemViewType(i);
if (type == 1) {
if (view == null) { if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.loading_more_layout, viewGroup, false); view = li.inflate(R.layout.loading_more_layout, viewGroup, false);
} }
return view; } else if (type == 0) {
} if (view == null) {
view = new DialogCell(mContext);
if (view == null) { }
view = new DialogCell(mContext); ((DialogCell) view).useSeparator = (i != getCount() - 1);
} if (serverOnly) {
if (serverOnly) { ((DialogCell) view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
((DialogCell)view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i)); } else {
} else { TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i); if (AndroidUtilities.isTablet()) {
if (AndroidUtilities.isTablet()) { if (dialog.id == openedDialogId) {
if (dialog.id == openedDialogId) { view.setBackgroundColor(0x0f000000);
view.setBackgroundColor(0x0f000000); } else {
} else { view.setBackgroundColor(0);
view.setBackgroundColor(0); }
} }
((DialogCell) view).setDialog(dialog);
} }
((DialogCell)view).setDialog(dialog);
} }
return view; return view;
@ -791,12 +858,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override @Override
public int getItemViewType(int i) { public int getItemViewType(int i) {
if (searching && searchWas) { if (searching && searchWas) {
TLObject obj = searchResult.get(i); if (i == searchResult.size()) {
if (obj instanceof TLRPC.User || obj instanceof TLRPC.EncryptedChat) {
return 2;
} else {
return 3; return 3;
} }
return 2;
} }
if (serverOnly && i == MessagesController.getInstance().dialogsServerOnly.size() || !serverOnly && i == MessagesController.getInstance().dialogs.size()) { if (serverOnly && i == MessagesController.getInstance().dialogsServerOnly.size() || !serverOnly && i == MessagesController.getInstance().dialogs.size()) {
return 1; return 1;
@ -812,7 +877,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
if (searching && searchWas) { if (searching && searchWas) {
return searchResult == null || searchResult.size() == 0; return searchResult.size() == 0 && globalSearch.isEmpty();
} }
if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) { if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) {
return false; return false;

View File

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

View File

@ -101,6 +101,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private View pickerView; private View pickerView;
private TextView doneButtonTextView; private TextView doneButtonTextView;
private TextView doneButtonBadgeTextView; private TextView doneButtonBadgeTextView;
private ImageView shareButton;
private boolean canShowBottom = true; private boolean canShowBottom = true;
private boolean overlayViewVisible = true; private boolean overlayViewVisible = true;
@ -234,7 +235,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
public int getSelectedCount(); public int getSelectedCount();
} }
private static class FrameLayoutTouchListener extends FrameLayout { private class FrameLayoutTouchListener extends FrameLayout {
public FrameLayoutTouchListener(Context context) { public FrameLayoutTouchListener(Context context) {
super(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) { public FrameLayoutDrawer(Context context) {
super(context); super(context);
setWillNotDraw(false); setWillNotDraw(false);
@ -595,7 +596,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
bottomLayout.setLayoutParams(layoutParams); bottomLayout.setLayoutParams(layoutParams);
bottomLayout.setBackgroundColor(0x7F000000); bottomLayout.setBackgroundColor(0x7F000000);
ImageView shareButton = new ImageView(containerView.getContext()); shareButton = new ImageView(containerView.getContext());
shareButton.setImageResource(R.drawable.ic_ab_share_white); shareButton.setImageResource(R.drawable.ic_ab_share_white);
shareButton.setScaleType(ImageView.ScaleType.CENTER); shareButton.setScaleType(ImageView.ScaleType.CENTER);
shareButton.setBackgroundResource(R.drawable.bar_selector_white); shareButton.setBackgroundResource(R.drawable.bar_selector_white);
@ -611,12 +612,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
return; return;
} }
try { try {
int size[] = new int[1]; File f = null;
TLRPC.FileLocation fileLocation = getFileLocation(currentIndex, size);
if (fileLocation == null) { if (currentMessageObject != null) {
return; 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()) { if (f.exists()) {
Intent intent = new Intent(Intent.ACTION_SEND); Intent intent = new Intent(Intent.ACTION_SEND);
if (f.toString().endsWith("mp4")) { if (f.toString().endsWith("mp4")) {
@ -654,7 +657,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (obj.isSent()) { if (obj.isSent()) {
ArrayList<Integer> arr = new ArrayList<Integer>(); ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(obj.messageOwner.id); 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); closePhoto(false);
} }
} else if (!avatarsArr.isEmpty()) { } else if (!avatarsArr.isEmpty()) {
@ -1157,6 +1169,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} else { } else {
menuItem.hideSubItem(gallery_menu_showall); 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); setImageIndex(0, true);
} else if (fileLocation != null) { } else if (fileLocation != null) {
avatarsUserId = object.user_id; avatarsUserId = object.user_id;
@ -1164,6 +1183,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
imagesArrLocationsSizes.add(object.size); imagesArrLocationsSizes.add(object.size);
avatarsArr.add(new TLRPC.TL_photoEmpty()); avatarsArr.add(new TLRPC.TL_photoEmpty());
bottomLayout.setVisibility(View.GONE); bottomLayout.setVisibility(View.GONE);
shareButton.setVisibility(View.VISIBLE);
menuItem.hideSubItem(gallery_menu_showall); menuItem.hideSubItem(gallery_menu_showall);
setImageIndex(0, true); setImageIndex(0, true);
currentUserAvatarLocation = fileLocation; 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; opennedFromMedia = true;
setImageIndex(index, true); setImageIndex(index, true);
} else if (photos != null) { } else if (photos != null) {
@ -1201,6 +1228,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
setImageIndex(index, true); setImageIndex(index, true);
pickerView.setVisibility(View.VISIBLE); pickerView.setVisibility(View.VISIBLE);
bottomLayout.setVisibility(View.GONE); bottomLayout.setVisibility(View.GONE);
shareButton.setVisibility(View.VISIBLE);
canShowBottom = false; canShowBottom = false;
updateSelectedCount(); updateSelectedCount();
} }
@ -2138,7 +2166,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float ai = -1; float ai = -1;
if (System.currentTimeMillis() - animationStartTime < animationDuration) { if (System.currentTimeMillis() - animationStartTime < animationDuration) {
ai = interpolator.getInterpolation((float)(System.currentTimeMillis() - animationStartTime) / animationDuration); ai = interpolator.getInterpolation((float)(System.currentTimeMillis() - animationStartTime) / animationDuration);
if (ai >= 0.95) { if (ai >= 0.95f) {
ai = -1; ai = -1;
} }
} }
@ -2219,7 +2247,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
int height = (int) (bitmapHeight * scale); int height = (int) (bitmapHeight * scale);
centerImage.setImageCoords(-width / 2, -height / 2, width, height); centerImage.setImageCoords(-width / 2, -height / 2, width, height);
centerImage.draw(canvas, -width / 2, -height / 2, width, height); centerImage.draw(canvas);
} }
if (scale >= 1.0f) { if (scale >= 1.0f) {
@ -2250,7 +2278,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
int height = (int) (bitmapHeight * scale); int height = (int) (bitmapHeight * scale);
sideImage.setImageCoords(-width / 2, -height / 2, width, height); sideImage.setImageCoords(-width / 2, -height / 2, width, height);
sideImage.draw(canvas, -width / 2, -height / 2, width, height); sideImage.draw(canvas);
} }
} else { } else {
changingPage = false; 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.AvatarUpdater;
import org.telegram.ui.Views.BackupImageView; import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment; 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.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -72,6 +74,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
private int profileRow; private int profileRow;
private int numberSectionRow; private int numberSectionRow;
private int numberRow; private int numberRow;
private int usernameRow;
private int settingsSectionRow; private int settingsSectionRow;
private int textSizeRow; private int textSizeRow;
private int enableAnimationsRow; private int enableAnimationsRow;
@ -178,6 +181,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
profileRow = rowCount++; profileRow = rowCount++;
numberSectionRow = rowCount++; numberSectionRow = rowCount++;
numberRow = rowCount++; numberRow = rowCount++;
usernameRow = rowCount++;
settingsSectionRow = rowCount++; settingsSectionRow = rowCount++;
enableAnimationsRow = rowCount++; enableAnimationsRow = rowCount++;
languageRow = rowCount++; languageRow = rowCount++;
@ -207,12 +211,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
logoutRow = rowCount++; logoutRow = rowCount++;
versionRow = rowCount++; versionRow = rowCount++;
MessagesController.getInstance().loadFullUser(UserConfig.getCurrentUser(), classGuid);
return true; return true;
} }
@Override @Override
public void onFragmentDestroy() { public void onFragmentDestroy() {
super.onFragmentDestroy(); super.onFragmentDestroy();
MessagesController.getInstance().cancelLoadFullUser(UserConfig.getClientUserId());
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces);
avatarUpdater.clear(); avatarUpdater.clear();
} }
@ -245,39 +252,24 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
} }
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("TextSize", R.string.TextSize)); builder.setTitle(LocaleController.getString("TextSize", R.string.TextSize));
builder.setItems(new CharSequence[] { final NumberPicker numberPicker = new NumberPicker(getParentActivity());
String.format("%d", 12), numberPicker.setMinValue(12);
String.format("%d", 13), numberPicker.setMaxValue(30);
String.format("%d", 14), numberPicker.setValue(MessagesController.getInstance().fontSize);
String.format("%d", 15), builder.setView(numberPicker);
String.format("%d", 16), builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
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() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit(); SharedPreferences.Editor editor = preferences.edit();
editor.putInt("fons_size", 12 + which); editor.putInt("fons_size", numberPicker.getValue());
MessagesController.getInstance().fontSize = 12 + which; MessagesController.getInstance().fontSize = numberPicker.getValue();
editor.commit(); editor.commit();
if (listView != null) { if (listView != null) {
listView.invalidateViews(); listView.invalidateViews();
} }
} }
}); });
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showAlertDialog(builder); showAlertDialog(builder);
} else if (i == enableAnimationsRow) { } else if (i == enableAnimationsRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); 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); builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null);
showAlertDialog(builder); 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) { public boolean isEnabled(int i) {
return i == textSizeRow || i == enableAnimationsRow || i == blockedRow || i == notificationRow || i == backgroundRow || return i == textSizeRow || i == enableAnimationsRow || i == blockedRow || i == notificationRow || i == backgroundRow ||
i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == terminateSessionsRow || i == wifiDownloadRow || 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; i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow;
} }
@ -838,22 +832,20 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
return view; return view;
} else if (type == 1) { } else if (type == 1) {
if (view == null) { if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = new SettingsSectionLayout(mContext);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
} }
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == numberSectionRow) { if (i == numberSectionRow) {
textView.setText(LocaleController.getString("YourPhoneNumber", R.string.YourPhoneNumber)); ((SettingsSectionLayout) view).setText(LocaleController.getString("Info", R.string.Info));
} else if (i == settingsSectionRow) { } 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) { } 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) { } 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) { } 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) { } 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) { } else if (type == 2) {
if (view == null) { if (view == null) {
@ -862,15 +854,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
} }
TextView textView = (TextView)view.findViewById(R.id.settings_row_text); TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
View divider = view.findViewById(R.id.settings_row_divider); View divider = view.findViewById(R.id.settings_row_divider);
if (i == numberRow) { if (i == notificationRow) {
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) {
textView.setText(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); textView.setText(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds));
divider.setVisibility(View.VISIBLE); divider.setVisibility(View.VISIBLE);
} else if (i == blockedRow) { } 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 textView = (TextView)view.findViewById(R.id.settings_row_text);
TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail); TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail);
View divider = view.findViewById(R.id.settings_row_divider); 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); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16); int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
detailTextView.setText(String.format("%d", size)); detailTextView.setText(String.format("%d", size));
@ -1002,6 +995,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
} else if (sort == 2) { } else if (sort == 2) {
detailTextView.setText(LocaleController.getString("LastName", R.string.SortLastName)); 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) { } else if (type == 6) {
if (view == null) { if (view == null) {
@ -1075,11 +1077,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
return 0; return 0;
} else if (i == numberSectionRow || i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) { } else if (i == numberSectionRow || i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) {
return 1; return 1;
} else if (i == textSizeRow || i == languageRow || i == contactsSortRow) { } else if (i == textSizeRow || i == languageRow || i == contactsSortRow || i == numberRow || i == usernameRow) {
return 5; return 5;
} else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow) { } else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow) {
return 3; 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; return 2;
} else if (i == logoutRow) { } else if (i == logoutRow) {
return 4; return 4;

View File

@ -249,7 +249,7 @@ public class SettingsBlockedUsersActivity extends BaseFragment implements Notifi
((ChatOrUserCell)view).useSeparator = true; ((ChatOrUserCell)view).useSeparator = true;
} }
TLRPC.User user = MessagesController.getInstance().getUser(MessagesController.getInstance().blockedUsers.get(i)); 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) { } else if (type == 1) {
if (view == null) { if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 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.app.Activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -17,6 +20,7 @@ import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.telegram.android.AndroidUtilities; import org.telegram.android.AndroidUtilities;
@ -30,6 +34,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.RPCRequest; import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.SettingsSectionLayout;
public class SettingsChangeNameActivity extends BaseFragment { public class SettingsChangeNameActivity extends BaseFragment {
private EditText firstNameField; private EditText firstNameField;
@ -63,14 +68,31 @@ public class SettingsChangeNameActivity extends BaseFragment {
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text); TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase()); 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()); TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
if (user == null) { if (user == null) {
user = UserConfig.getCurrentUser(); 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.setHint(LocaleController.getString("FirstName", R.string.FirstName));
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() { firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override @Override
@ -83,7 +105,25 @@ public class SettingsChangeNameActivity extends BaseFragment {
return false; 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.setHint(LocaleController.getString("LastName", R.string.LastName));
lastNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() { lastNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override @Override
@ -95,15 +135,19 @@ public class SettingsChangeNameActivity extends BaseFragment {
return false; 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) { if (user != null) {
firstNameField.setText(user.first_name); firstNameField.setText(user.first_name);
firstNameField.setSelection(firstNameField.length()); firstNameField.setSelection(firstNameField.length());
lastNameField.setText(user.last_name); lastNameField.setText(user.last_name);
} }
TextView headerLabel = (TextView)fragmentView.findViewById(R.id.settings_section_text);
headerLabel.setText(LocaleController.getString("YourFirstNameAndLastName", R.string.YourFirstNameAndLastName));
} else { } else {
ViewGroup parent = (ViewGroup)fragmentView.getParent(); ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) { if (parent != null) {
@ -125,12 +169,18 @@ public class SettingsChangeNameActivity extends BaseFragment {
} }
private void saveName() { private void saveName() {
TLRPC.TL_account_updateProfile req = new TLRPC.TL_account_updateProfile(); TLRPC.User currentUser = UserConfig.getCurrentUser();
if (UserConfig.getCurrentUser() == null || lastNameField.getText() == null || firstNameField.getText() == null) { if (currentUser == null || lastNameField.getText() == null || firstNameField.getText() == null) {
return; return;
} }
UserConfig.getCurrentUser().first_name = req.first_name = firstNameField.getText().toString(); String newFirst = firstNameField.getText().toString();
UserConfig.getCurrentUser().last_name = req.last_name = lastNameField.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()); TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
if (user != null) { if (user != null) {
user.first_name = req.first_name; 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.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.BaseFragment; import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.ColorPickerView; import org.telegram.ui.Views.ColorPickerView;
import org.telegram.ui.Views.SettingsSectionLayout;
public class SettingsNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public class SettingsNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private ListView listView; private ListView listView;
@ -541,22 +542,20 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
int type = getItemViewType(i); int type = getItemViewType(i);
if (type == 0) { if (type == 0) {
if (view == null) { if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = new SettingsSectionLayout(mContext);
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
} }
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
if (i == messageSectionRow) { if (i == messageSectionRow) {
textView.setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications)); ((SettingsSectionLayout) view).setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications));
} else if (i == groupSectionRow) { } 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) { } 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) { } 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) { } 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) { } 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 (type == 1) {
if (view == null) { if (view == null) {

View File

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

View File

@ -58,6 +58,7 @@ import java.util.List;
@TargetApi(16) @TargetApi(16)
public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener { public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener {
private boolean created = false;
private MediaPlayer videoPlayer = null; private MediaPlayer videoPlayer = null;
private VideoTimelineView videoTimelineView = null; private VideoTimelineView videoTimelineView = null;
private View videoContainerView = null; private View videoContainerView = null;
@ -161,6 +162,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
@Override @Override
public boolean onFragmentCreate() { public boolean onFragmentCreate() {
if (created) {
return true;
}
if (videoPath == null || !processOpenVideo()) { if (videoPath == null || !processOpenVideo()) {
return false; return false;
} }
@ -191,6 +195,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
return false; return false;
} }
created = true;
return super.onFragmentCreate(); return super.onFragmentCreate();
} }
@ -276,22 +282,27 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
}); });
if (Build.VERSION.SDK_INT < 18) { if (Build.VERSION.SDK_INT < 18) {
MediaCodecInfo codecInfo = MediaController.selectCodec(MediaController.MIME_TYPE); try {
if (codecInfo == null) { MediaCodecInfo codecInfo = MediaController.selectCodec(MediaController.MIME_TYPE);
compressVideo.setVisibility(View.GONE); if (codecInfo == null) {
} else {
String name = codecInfo.getName();
if (name.equals("OMX.google.h264.encoder") ||
name.equals("OMX.ST.VFM.H264Enc") ||
name.equals("OMX.Exynos.avc.enc") ||
name.equals("OMX.MARVELL.VIDEO.HW.CODA7542ENCODER") ||
name.equals("OMX.MARVELL.VIDEO.H264ENCODER")) {
compressVideo.setVisibility(View.GONE); compressVideo.setVisibility(View.GONE);
} else { } else {
if (MediaController.selectColorFormat(codecInfo, MediaController.MIME_TYPE) == 0) { String name = codecInfo.getName();
if (name.equals("OMX.google.h264.encoder") ||
name.equals("OMX.ST.VFM.H264Enc") ||
name.equals("OMX.Exynos.avc.enc") ||
name.equals("OMX.MARVELL.VIDEO.HW.CODA7542ENCODER") ||
name.equals("OMX.MARVELL.VIDEO.H264ENCODER")) {
compressVideo.setVisibility(View.GONE); compressVideo.setVisibility(View.GONE);
} else {
if (MediaController.selectColorFormat(codecInfo, MediaController.MIME_TYPE) == 0) {
compressVideo.setVisibility(View.GONE);
}
} }
} }
} catch (Exception e) {
compressVideo.setVisibility(View.GONE);
FileLog.e("tmessages", e);
} }
} }
@ -446,11 +457,17 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
} }
private void onPlayComplete() { private void onPlayComplete() {
playButton.setImageResource(R.drawable.video_play); if (playButton != null) {
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress()); playButton.setImageResource(R.drawable.video_play);
}
if (videoSeekBarView != null && videoTimelineView != null) {
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
}
try { try {
if (videoPlayer != null) { if (videoPlayer != null) {
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration)); if (videoTimelineView != null) {
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
}
} }
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);

View File

@ -171,9 +171,9 @@ public class ActionBarLayer extends FrameLayout {
x = AndroidUtilities.dp(16 + leftMargin); x = AndroidUtilities.dp(16 + leftMargin);
} else { } else {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 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 { } 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) { if (fragmentView != null) {
ViewGroup parent = (ViewGroup) fragmentView.getParent(); ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) { if (parent != null) {
parent.removeView(fragmentView); try {
parent.removeView(fragmentView);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} }
fragmentView = null; fragmentView = null;
} }

View File

@ -91,6 +91,6 @@ public class BackupImageView extends View {
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
imageReceiver.setImageCoords(0, 0, getWidth(), getHeight()); 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)); messsageEditText.dispatchKeyEvent(new KeyEvent(0, 67));
} }
public void onEmojiSelected(String paramAnonymousString) { public void onEmojiSelected(String symbol) {
int i = messsageEditText.getSelectionEnd(); int i = messsageEditText.getSelectionEnd();
CharSequence localCharSequence = Emoji.replaceEmoji(paramAnonymousString, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); if (i < 0) {
messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence)); i = 0;
int j = i + localCharSequence.length(); }
messsageEditText.setSelection(j, j); 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); 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) { public void setDelegate(ChatActivityEnterViewDelegate delegate) {

View File

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

View File

@ -10,11 +10,17 @@ package org.telegram.ui.Views;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
public class LayoutListView extends ListView { public class LayoutListView extends ListView {
public static interface OnInterceptTouchEventListener {
public abstract boolean onInterceptTouchEvent(MotionEvent event);
}
private OnInterceptTouchEventListener onInterceptTouchEventListener;
private int height = -1; private int height = -1;
public LayoutListView(Context context) { public LayoutListView(Context context) {
@ -29,6 +35,18 @@ public class LayoutListView extends ListView {
super(context, attrs, defStyle); 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 @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
View v = getChildAt(getChildCount() - 1); 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,20 +65,33 @@ public class TimerButton extends View {
time = value; time = value;
String timeString = null; String timeString = null;
if (time == 2) { if (time >= 1 && time < 60) {
timeString = "2s"; timeString = "" + value;
} else if (time == 5) { if (timeString.length() < 2) {
timeString = "5s"; timeString += "s";
} else if (time == 60) { }
timeString = "1m"; } else if (time >= 60 && time < 60 * 60) {
} else if (time == 60 * 60) { timeString = "" + value / 60;
timeString = "1h"; if (timeString.length() < 2) {
} else if (time == 60 * 60 * 24) { timeString += "m";
timeString = "1d"; }
} else if (time == 60 * 60 * 24 * 7) { } else if (time >= 60 * 60 && time < 60 * 60 * 24) {
timeString = "1w"; 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 { } else {
timeString = "c"; timeString = "" + value / 60 / 60 / 24 / 7;
if (timeString.length() < 2) {
timeString += "w";
} else if (timeString.length() > 2) {
timeString = "c";
}
} }
timeWidth = timePaint.measureText(timeString); timeWidth = timePaint.measureText(timeString);
@ -110,7 +123,7 @@ public class TimerButton extends View {
drawable.draw(canvas); drawable.draw(canvas);
if (time != 0 && timeLayout != null) { 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); 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) { public void setVideoPath(String path) {
mediaMetadataRetriever = new MediaMetadataRetriever(); mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(path); try {
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); mediaMetadataRetriever.setDataSource(path);
videoLength = Long.parseLong(duration); String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
videoLength = Long.parseLong(duration);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} }
public void setDelegate(VideoTimelineViewDelegate delegate) { 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"?> <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"> <set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="0.9" <!--<scale-->
android:fromYScale="0.9" <!--android:fromXScale="0.9"-->
android:toXScale="1.0" <!--android:fromYScale="0.9"-->
android:toYScale="1.0" <!--android:toXScale="1.0"-->
android:pivotX="50%" <!--android:toYScale="1.0"-->
android:pivotY="50%" <!--android:pivotX="50%"-->
android:duration="150"/> <!--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" <alpha
android:toAlpha="1.0" android:fromAlpha="0.0"
android:duration="150" /> android:toAlpha="1.0"
android:interpolator="@anim/decelerate_cubic"
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> </set>

View File

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