Merge branch 'dev'
21
README.md
@ -1,21 +1,30 @@
|
||||
## Telegram messenger for Android
|
||||
|
||||
[Telegram](http://telegram.org) is a messaging app with a focus on speed and security. It’s superfast, simple and free.
|
||||
This repo contains the official source code for [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger).
|
||||
|
||||
This repo contains official [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger) source code.
|
||||
##Creating your Telegram Application
|
||||
|
||||
We welcome all developers to use our API and source code to create applications on our platform.
|
||||
There are several things we require from **all developers** for the moment.
|
||||
|
||||
1. [**Obtain your own api_id**](https://core.telegram.org/api/obtaining_api_id) for your application.
|
||||
2. Please **do not** use the name Telegram for your app — or make sure your users understand that it is unofficial.
|
||||
3. Kindly **do not** use our standard logo (white paper plane in a blue circle) as your app's logo.
|
||||
3. Please study our [**security guidelines**](https://core.telegram.org/mtproto/security_guidelines) and take good care of your users' data and privacy.
|
||||
4. Please remember to publish **your** code too in order to comply with the licences.
|
||||
|
||||
### API, Protocol documentation
|
||||
|
||||
Documentation for Telegram API is available here: http://core.telegram.org/api
|
||||
Telegram API manuals: http://core.telegram.org/api
|
||||
|
||||
Documentation for MTproto protocol is available here: http://core.telegram.org/mtproto
|
||||
MTproto protocol manuals: http://core.telegram.org/mtproto
|
||||
|
||||
### Usage
|
||||
|
||||
**Beware of using dev branch and uploading it to any markets, in most cases it will work as you expecting**
|
||||
|
||||
First of all your should take a look to **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
|
||||
**Beware of using the dev branch and uploading it to any markets, in many cases it not will work as expected**.
|
||||
|
||||
First of all, take a look at **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
|
||||
Import the root folder into your IDE (tested on Android Studio), then run project.
|
||||
|
||||
### Localization
|
||||
|
@ -19,13 +19,13 @@ tasks.withType(JavaCompile) {
|
||||
dependencies {
|
||||
compile 'com.android.support:support-v4:20.0.+'
|
||||
compile 'com.google.android.gms:play-services:3.2.+'
|
||||
compile 'net.hockeyapp.android:HockeySDK:3.0.1'
|
||||
compile 'net.hockeyapp.android:HockeySDK:3.0.2'
|
||||
compile 'com.googlecode.mp4parser:isoparser:1.0.+'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion '20.0.0'
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion '21.0.2'
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
@ -80,7 +80,7 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 8
|
||||
targetSdkVersion 19
|
||||
versionCode 355
|
||||
versionName "1.9.4"
|
||||
versionCode 374
|
||||
versionName "1.9.6"
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,11 @@ static inline uint64_t get_colors (const uint8_t *p) {
|
||||
return p[0] + (p[1] << 16) + ((uint64_t)p[2] << 32);
|
||||
}
|
||||
|
||||
static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pixels) {
|
||||
static void fastBlurMore(int imageWidth, int imageHeight, int imageStride, void *pixels, int radius) {
|
||||
uint8_t *pix = (uint8_t *)pixels;
|
||||
const int w = imageWidth;
|
||||
const int h = imageHeight;
|
||||
const int stride = imageStride;
|
||||
const int radius = 3;
|
||||
const int r1 = radius + 1;
|
||||
const int div = radius * 2 + 1;
|
||||
|
||||
@ -23,6 +22,98 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix
|
||||
}
|
||||
|
||||
uint64_t *rgb = malloc(imageWidth * imageHeight * sizeof(uint64_t));
|
||||
if (rgb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y, i;
|
||||
|
||||
int yw = 0;
|
||||
const int we = w - r1;
|
||||
for (y = 0; y < h; y++) {
|
||||
uint64_t cur = get_colors (&pix[yw]);
|
||||
uint64_t rgballsum = -radius * cur;
|
||||
uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1);
|
||||
|
||||
for (i = 1; i <= radius; i++) {
|
||||
uint64_t cur = get_colors (&pix[yw + i * 4]);
|
||||
rgbsum += cur * (r1 - i);
|
||||
rgballsum += cur;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
|
||||
#define update(start, middle, end) \
|
||||
rgb[y * w + x] = (rgbsum >> 6) & 0x00FF00FF00FF00FF; \
|
||||
rgballsum += get_colors (&pix[yw + (start) * 4]) - 2 * get_colors (&pix[yw + (middle) * 4]) + get_colors (&pix[yw + (end) * 4]); \
|
||||
rgbsum += rgballsum; \
|
||||
x++; \
|
||||
|
||||
while (x < r1) {
|
||||
update (0, x, x + r1);
|
||||
}
|
||||
while (x < we) {
|
||||
update (x - r1, x, x + r1);
|
||||
}
|
||||
while (x < w) {
|
||||
update (x - r1, x, w - 1);
|
||||
}
|
||||
#undef update
|
||||
|
||||
yw += stride;
|
||||
}
|
||||
|
||||
const int he = h - r1;
|
||||
for (x = 0; x < w; x++) {
|
||||
uint64_t rgballsum = -radius * rgb[x];
|
||||
uint64_t rgbsum = rgb[x] * ((r1 * (r1 + 1)) >> 1);
|
||||
for (i = 1; i <= radius; i++) {
|
||||
rgbsum += rgb[i * w + x] * (r1 - i);
|
||||
rgballsum += rgb[i * w + x];
|
||||
}
|
||||
|
||||
y = 0;
|
||||
int yi = x * 4;
|
||||
|
||||
#define update(start, middle, end) \
|
||||
int64_t res = rgbsum >> 6; \
|
||||
pix[yi] = res; \
|
||||
pix[yi + 1] = res >> 16; \
|
||||
pix[yi + 2] = res >> 32; \
|
||||
rgballsum += rgb[x + (start) * w] - 2 * rgb[x + (middle) * w] + rgb[x + (end) * w]; \
|
||||
rgbsum += rgballsum; \
|
||||
y++; \
|
||||
yi += stride;
|
||||
|
||||
while (y < r1) {
|
||||
update (0, y, y + r1);
|
||||
}
|
||||
while (y < he) {
|
||||
update (y - r1, y, y + r1);
|
||||
}
|
||||
while (y < h) {
|
||||
update (y - r1, y, h - 1);
|
||||
}
|
||||
#undef update
|
||||
}
|
||||
}
|
||||
|
||||
static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pixels, int radius) {
|
||||
uint8_t *pix = (uint8_t *)pixels;
|
||||
const int w = imageWidth;
|
||||
const int h = imageHeight;
|
||||
const int stride = imageStride;
|
||||
const int r1 = radius + 1;
|
||||
const int div = radius * 2 + 1;
|
||||
|
||||
if (radius > 15 || div >= w || div >= h || w * h > 90 * 90 || imageStride > imageWidth * 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t *rgb = malloc(imageWidth * imageHeight * sizeof(uint64_t));
|
||||
if (rgb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y, i;
|
||||
|
||||
@ -111,7 +202,7 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap) {
|
||||
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius) {
|
||||
if (!bitmap) {
|
||||
return;
|
||||
}
|
||||
@ -130,7 +221,11 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl
|
||||
if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
|
||||
return;
|
||||
}
|
||||
fastBlur(info.width, info.height, info.stride, pixels);
|
||||
if (radius <= 3) {
|
||||
fastBlur(info.width, info.height, info.stride, pixels, radius);
|
||||
} else {
|
||||
fastBlurMore(info.width, info.height, info.stride, pixels, radius);
|
||||
}
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.8.4.1"
|
||||
#define SQLITE_VERSION_NUMBER 3008004
|
||||
#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"
|
||||
#define SQLITE_VERSION "3.8.6"
|
||||
#define SQLITE_VERSION_NUMBER 3008006
|
||||
#define SQLITE_SOURCE_ID "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -269,7 +269,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
**
|
||||
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
||||
** for the [sqlite3] object.
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
|
||||
** the [sqlite3] object is successfully destroyed and all associated
|
||||
** resources are deallocated.
|
||||
**
|
||||
@ -277,7 +277,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
||||
** will leave the database connection open and return [SQLITE_BUSY].
|
||||
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
||||
** and unfinished sqlite3_backups, then the database connection becomes
|
||||
** and/or unfinished sqlite3_backups, then the database connection becomes
|
||||
** an unusable "zombie" which will automatically be deallocated when the
|
||||
** last prepared statement is finalized or the last sqlite3_backup is
|
||||
** finished. The sqlite3_close_v2() interface is intended for use with
|
||||
@ -290,7 +290,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
** with the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** sqlite3_close_v2() is called on a [database connection] that still has
|
||||
** outstanding [prepared statements], [BLOB handles], and/or
|
||||
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
|
||||
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
||||
** of resources is deferred until all [prepared statements], [BLOB handles],
|
||||
** and [sqlite3_backup] objects are also destroyed.
|
||||
**
|
||||
@ -386,16 +386,14 @@ SQLITE_API int sqlite3_exec(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Result Codes
|
||||
** KEYWORDS: SQLITE_OK {error code} {error codes}
|
||||
** KEYWORDS: {result code} {result codes}
|
||||
** KEYWORDS: {result code definitions}
|
||||
**
|
||||
** Many SQLite functions return an integer result code from the set shown
|
||||
** here in order to indicate success or failure.
|
||||
**
|
||||
** New error codes may be added in future versions of SQLite.
|
||||
**
|
||||
** See also: [SQLITE_IOERR_READ | extended result codes],
|
||||
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
|
||||
** See also: [extended result code definitions]
|
||||
*/
|
||||
#define SQLITE_OK 0 /* Successful result */
|
||||
/* beginning-of-error-codes */
|
||||
@ -433,26 +431,19 @@ SQLITE_API int sqlite3_exec(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Extended Result Codes
|
||||
** KEYWORDS: {extended error code} {extended error codes}
|
||||
** KEYWORDS: {extended result code} {extended result codes}
|
||||
** KEYWORDS: {extended result code definitions}
|
||||
**
|
||||
** In its default configuration, SQLite API routines return one of 26 integer
|
||||
** [SQLITE_OK | result codes]. However, experience has shown that many of
|
||||
** In its default configuration, SQLite API routines return one of 30 integer
|
||||
** [result codes]. However, experience has shown that many of
|
||||
** these result codes are too coarse-grained. They do not provide as
|
||||
** much information about problems as programmers might like. In an effort to
|
||||
** address this, newer versions of SQLite (version 3.3.8 and later) include
|
||||
** support for additional result codes that provide more detailed information
|
||||
** about errors. The extended result codes are enabled or disabled
|
||||
** about errors. These [extended result codes] are enabled or disabled
|
||||
** on a per database connection basis using the
|
||||
** [sqlite3_extended_result_codes()] API.
|
||||
**
|
||||
** Some of the available extended result codes are listed here.
|
||||
** One may expect the number of extended result codes will increase
|
||||
** over time. Software that uses extended result codes should expect
|
||||
** to see new result codes in future releases of SQLite.
|
||||
**
|
||||
** The SQLITE_OK result code will never be extended. It will always
|
||||
** be exactly zero.
|
||||
** [sqlite3_extended_result_codes()] API. Or, the extended code for
|
||||
** the most recent error can be obtained using
|
||||
** [sqlite3_extended_errcode()].
|
||||
*/
|
||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||
@ -560,7 +551,10 @@ SQLITE_API int sqlite3_exec(
|
||||
** file that were written at the application level might have changed
|
||||
** and that adjacent bytes, even bytes within the same sector are
|
||||
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
||||
** flag indicate that a file cannot be deleted when open.
|
||||
** flag indicate that a file cannot be deleted when open. The
|
||||
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
|
||||
** read-only media and cannot be changed even by processes with
|
||||
** elevated privileges.
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
@ -575,6 +569,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
||||
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
|
||||
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@ -681,7 +676,7 @@ struct sqlite3_file {
|
||||
** locking strategy (for example to use dot-file locks), to inquire
|
||||
** about the status of a lock, or to break stale locks. The SQLite
|
||||
** core reserves all opcodes less than 100 for its own use.
|
||||
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
|
||||
** A [file control opcodes | list of opcodes] less than 100 is available.
|
||||
** Applications that define a custom xFileControl method should use opcodes
|
||||
** greater than 100 to avoid conflicts. VFS implementations should
|
||||
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
|
||||
@ -754,6 +749,7 @@ struct sqlite3_io_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Standard File Control Opcodes
|
||||
** KEYWORDS: {file control opcodes} {file control opcode}
|
||||
**
|
||||
** These integer constants are opcodes for the xFileControl method
|
||||
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
|
||||
@ -943,6 +939,12 @@ struct sqlite3_io_methods {
|
||||
** on whether or not the file has been renamed, moved, or deleted since it
|
||||
** was first opened.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
|
||||
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
|
||||
** opcode causes the xFileControl method to swap the file handle with the one
|
||||
** pointed to by the pArg argument. This capability is used during testing
|
||||
** and only needs to be supported when SQLITE_TEST is defined.
|
||||
**
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@ -966,6 +968,7 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_HAS_MOVED 20
|
||||
#define SQLITE_FCNTL_SYNC 21
|
||||
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
||||
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@ -2026,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
|
||||
/*
|
||||
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
|
||||
**
|
||||
** ^This routine sets a callback function that might be invoked whenever
|
||||
** an attempt is made to open a database table that another thread
|
||||
** or process has locked.
|
||||
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
|
||||
** that might be invoked with argument P whenever
|
||||
** an attempt is made to access a database table associated with
|
||||
** [database connection] D when another thread
|
||||
** or process has the table locked.
|
||||
** The sqlite3_busy_handler() interface is used to implement
|
||||
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
|
||||
**
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY]
|
||||
** is returned immediately upon encountering the lock. ^If the busy callback
|
||||
** is not NULL, then the callback might be invoked with two arguments.
|
||||
**
|
||||
** ^The first argument to the busy handler is a copy of the void* pointer which
|
||||
** is the third argument to sqlite3_busy_handler(). ^The second argument to
|
||||
** the busy handler callback is the number of times that the busy handler has
|
||||
** been invoked for this locking event. ^If the
|
||||
** been invoked for the same locking event. ^If the
|
||||
** busy callback returns 0, then no additional attempts are made to
|
||||
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
|
||||
** access the database and [SQLITE_BUSY] is returned
|
||||
** to the application.
|
||||
** ^If the callback returns non-zero, then another attempt
|
||||
** is made to open the database for reading and the cycle repeats.
|
||||
** is made to access the database and the cycle repeats.
|
||||
**
|
||||
** The presence of a busy handler does not guarantee that it will be invoked
|
||||
** when there is lock contention. ^If SQLite determines that invoking the busy
|
||||
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
|
||||
** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
|
||||
** to the application instead of invoking the
|
||||
** busy handler.
|
||||
** Consider a scenario where one process is holding a read lock that
|
||||
** it is trying to promote to a reserved lock and
|
||||
** a second process is holding a reserved lock that it is trying
|
||||
@ -2060,28 +2069,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
|
||||
**
|
||||
** ^The default busy callback is NULL.
|
||||
**
|
||||
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
|
||||
** when SQLite is in the middle of a large transaction where all the
|
||||
** changes will not fit into the in-memory cache. SQLite will
|
||||
** already hold a RESERVED lock on the database file, but it needs
|
||||
** to promote this lock to EXCLUSIVE so that it can spill cache
|
||||
** pages into the database file without harm to concurrent
|
||||
** readers. ^If it is unable to promote the lock, then the in-memory
|
||||
** cache will be left in an inconsistent state and so the error
|
||||
** code is promoted from the relatively benign [SQLITE_BUSY] to
|
||||
** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
|
||||
** forces an automatic rollback of the changes. See the
|
||||
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
|
||||
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
|
||||
** this is important.
|
||||
**
|
||||
** ^(There can only be a single busy handler defined for each
|
||||
** [database connection]. Setting a new busy handler clears any
|
||||
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
|
||||
** will also set or clear the busy handler.
|
||||
** or evaluating [PRAGMA busy_timeout=N] will change the
|
||||
** busy handler and thus clear any previously set busy handler.
|
||||
**
|
||||
** The busy callback should not take any actions which modify the
|
||||
** database connection that invoked the busy handler. Any such actions
|
||||
** database connection that invoked the busy handler. In other words,
|
||||
** the busy handler is not reentrant. Any such actions
|
||||
** result in undefined behavior.
|
||||
**
|
||||
** A busy handler must not close the database connection
|
||||
@ -2097,7 +2093,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
||||
** will sleep multiple times until at least "ms" milliseconds of sleeping
|
||||
** have accumulated. ^After at least "ms" milliseconds of sleeping,
|
||||
** the handler returns 0 which causes [sqlite3_step()] to return
|
||||
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
|
||||
** [SQLITE_BUSY].
|
||||
**
|
||||
** ^Calling this routine with an argument less than or equal to zero
|
||||
** turns off all busy handlers.
|
||||
@ -2106,6 +2102,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
||||
** [database connection] any any given moment. If another busy handler
|
||||
** was defined (using [sqlite3_busy_handler()]) prior to calling
|
||||
** this routine, that other busy handler is cleared.)^
|
||||
**
|
||||
** See also: [PRAGMA busy_timeout]
|
||||
*/
|
||||
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
|
||||
|
||||
@ -2507,8 +2505,8 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
** [sqlite3_set_authorizer | authorizer documentation] for additional
|
||||
** information.
|
||||
**
|
||||
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
|
||||
** from the [sqlite3_vtab_on_conflict()] interface.
|
||||
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
|
||||
** returned from the [sqlite3_vtab_on_conflict()] interface.
|
||||
*/
|
||||
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
|
||||
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
|
||||
@ -2779,6 +2777,30 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
||||
** a URI filename, its value overrides any behavior requested by setting
|
||||
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
||||
**
|
||||
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
|
||||
** "1") or "false" (or "off" or "no" or "0") to indicate that the
|
||||
** [powersafe overwrite] property does or does not apply to the
|
||||
** storage media on which the database file resides. ^The psow query
|
||||
** parameter only works for the built-in unix and Windows VFSes.
|
||||
**
|
||||
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
|
||||
** which if set disables file locking in rollback journal modes. This
|
||||
** is useful for accessing a database on a filesystem that does not
|
||||
** support locking. Caution: Database corruption might result if two
|
||||
** or more processes write to the same database and any one of those
|
||||
** processes uses nolock=1.
|
||||
**
|
||||
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
|
||||
** parameter that indicates that the database file is stored on
|
||||
** read-only media. ^When immutable is set, SQLite assumes that the
|
||||
** database file cannot be changed, even by a process with higher
|
||||
** privilege, and so the database is opened read-only and all locking
|
||||
** and change detection is disabled. Caution: Setting the immutable
|
||||
** property on a database file that does in fact change can result
|
||||
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
|
||||
** See also: [SQLITE_IOCAP_IMMUTABLE].
|
||||
**
|
||||
** </ul>
|
||||
**
|
||||
** ^Specifying an unknown parameter in the query component of a URI is not an
|
||||
@ -2808,8 +2830,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** Open file "data.db" in the current directory for read-only access.
|
||||
** Regardless of whether or not shared-cache mode is enabled by
|
||||
** default, use a private cache.
|
||||
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
|
||||
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
|
||||
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
|
||||
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
|
||||
** that uses dot-files in place of posix advisory locking.
|
||||
** <tr><td> file:data.db?mode=readonly <td>
|
||||
** An error. "readonly" is not a valid option for the "mode" parameter.
|
||||
** </table>
|
||||
@ -4670,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
|
||||
** is a NULL pointer, then SQLite performs a search for an appropriate
|
||||
** temporary file directory.
|
||||
**
|
||||
** Applications are strongly discouraged from using this global variable.
|
||||
** It is required to set a temporary folder on Windows Runtime (WinRT).
|
||||
** But for all other platforms, it is highly recommended that applications
|
||||
** neither read nor write this variable. This global variable is a relic
|
||||
** that exists for backwards compatibility of legacy applications and should
|
||||
** be avoided in new projects.
|
||||
**
|
||||
** It is not safe to read or modify this variable in more than one
|
||||
** thread at a time. It is not safe to read or modify this variable
|
||||
** if a [database connection] is being used at the same time in a separate
|
||||
@ -4688,6 +4718,11 @@ SQLITE_API int sqlite3_sleep(int);
|
||||
** Hence, if this variable is modified directly, either it should be
|
||||
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
||||
** or else the use of the [temp_store_directory pragma] should be avoided.
|
||||
** Except when requested by the [temp_store_directory pragma], SQLite
|
||||
** does not free the memory that sqlite3_temp_directory points to. If
|
||||
** the application wants that memory to be freed, it must do
|
||||
** so itself, taking care to only do so after all [database connection]
|
||||
** objects have been destroyed.
|
||||
**
|
||||
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
||||
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
|
||||
@ -5822,10 +5857,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
|
||||
** <li> SQLITE_MUTEX_RECURSIVE
|
||||
** <li> SQLITE_MUTEX_STATIC_MASTER
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM
|
||||
** <li> SQLITE_MUTEX_STATIC_MEM2
|
||||
** <li> SQLITE_MUTEX_STATIC_OPEN
|
||||
** <li> SQLITE_MUTEX_STATIC_PRNG
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU
|
||||
** <li> SQLITE_MUTEX_STATIC_LRU2
|
||||
** <li> SQLITE_MUTEX_STATIC_PMEM
|
||||
** <li> SQLITE_MUTEX_STATIC_APP1
|
||||
** <li> SQLITE_MUTEX_STATIC_APP2
|
||||
** </ul>)^
|
||||
**
|
||||
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
|
||||
@ -6029,6 +6066,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
|
||||
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
|
||||
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
|
||||
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
|
||||
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Retrieve the mutex for a database connection
|
||||
@ -6123,7 +6163,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
|
||||
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
|
||||
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
|
||||
#define SQLITE_TESTCTRL_LAST 21
|
||||
#define SQLITE_TESTCTRL_BYTEORDER 22
|
||||
#define SQLITE_TESTCTRL_ISINIT 23
|
||||
#define SQLITE_TESTCTRL_LAST 23
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
@ -7107,6 +7149,9 @@ SQLITE_API void *sqlite3_wal_hook(
|
||||
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
|
||||
** from SQL.
|
||||
**
|
||||
** ^Checkpoints initiated by this mechanism are
|
||||
** [sqlite3_wal_checkpoint_v2|PASSIVE].
|
||||
**
|
||||
** ^Every new [database connection] defaults to having the auto-checkpoint
|
||||
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
|
||||
** pages. The use of this interface
|
||||
@ -7123,6 +7168,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
||||
** empty string, then a checkpoint is run on all databases of
|
||||
** connection D. ^If the database connection D is not in
|
||||
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
|
||||
** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
|
||||
** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
|
||||
** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
|
||||
** or RESET checkpoint.
|
||||
**
|
||||
** ^The [wal_checkpoint pragma] can be used to invoke this interface
|
||||
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
|
||||
@ -7145,10 +7194,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
||||
** Checkpoint as many frames as possible without waiting for any database
|
||||
** readers or writers to finish. Sync the db file if all frames in the log
|
||||
** are checkpointed. This mode is the same as calling
|
||||
** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
|
||||
** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
|
||||
** is never invoked.
|
||||
**
|
||||
** <dt>SQLITE_CHECKPOINT_FULL<dd>
|
||||
** This mode blocks (calls the busy-handler callback) until there is no
|
||||
** This mode blocks (it invokes the
|
||||
** [sqlite3_busy_handler|busy-handler callback]) until there is no
|
||||
** database writer and all readers are reading from the most recent database
|
||||
** snapshot. It then checkpoints all frames in the log file and syncs the
|
||||
** database file. This call blocks database writers while it is running,
|
||||
@ -7156,7 +7207,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
||||
**
|
||||
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
|
||||
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
|
||||
** checkpointing the log file it blocks (calls the busy-handler callback)
|
||||
** checkpointing the log file it blocks (calls the
|
||||
** [sqlite3_busy_handler|busy-handler callback])
|
||||
** until all readers are reading from the database file only. This ensures
|
||||
** that the next client to write to the database file restarts the log file
|
||||
** from the beginning. This call blocks database writers while it is running,
|
||||
@ -7294,6 +7346,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
**
|
||||
** These constants are returned by [sqlite3_vtab_on_conflict()] to
|
||||
** inform a [virtual table] implementation what the [ON CONFLICT] mode
|
||||
@ -7346,6 +7399,16 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
|
||||
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
|
||||
|
||||
/* The double-precision datatype used by RTree depends on the
|
||||
** SQLITE_RTREE_INT_ONLY compile-time option.
|
||||
*/
|
||||
#ifdef SQLITE_RTREE_INT_ONLY
|
||||
typedef sqlite3_int64 sqlite3_rtree_dbl;
|
||||
#else
|
||||
typedef double sqlite3_rtree_dbl;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Register a geometry callback named zGeom that can be used as part of an
|
||||
@ -7356,11 +7419,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
|
||||
SQLITE_API int sqlite3_rtree_geometry_callback(
|
||||
sqlite3 *db,
|
||||
const char *zGeom,
|
||||
#ifdef SQLITE_RTREE_INT_ONLY
|
||||
int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
|
||||
#else
|
||||
int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
|
||||
#endif
|
||||
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
|
||||
void *pContext
|
||||
);
|
||||
|
||||
@ -7372,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
|
||||
struct sqlite3_rtree_geometry {
|
||||
void *pContext; /* Copy of pContext passed to s_r_g_c() */
|
||||
int nParam; /* Size of array aParam[] */
|
||||
double *aParam; /* Parameters passed to SQL geom function */
|
||||
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
|
||||
void *pUser; /* Callback implementation user data */
|
||||
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
|
||||
};
|
||||
|
||||
/*
|
||||
** Register a 2nd-generation geometry callback named zScore that can be
|
||||
** used as part of an R-Tree geometry query as follows:
|
||||
**
|
||||
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
|
||||
*/
|
||||
SQLITE_API int sqlite3_rtree_query_callback(
|
||||
sqlite3 *db,
|
||||
const char *zQueryFunc,
|
||||
int (*xQueryFunc)(sqlite3_rtree_query_info*),
|
||||
void *pContext,
|
||||
void (*xDestructor)(void*)
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** A pointer to a structure of the following type is passed as the
|
||||
** argument to scored geometry callback registered using
|
||||
** sqlite3_rtree_query_callback().
|
||||
**
|
||||
** Note that the first 5 fields of this structure are identical to
|
||||
** sqlite3_rtree_geometry. This structure is a subclass of
|
||||
** sqlite3_rtree_geometry.
|
||||
*/
|
||||
struct sqlite3_rtree_query_info {
|
||||
void *pContext; /* pContext from when function registered */
|
||||
int nParam; /* Number of function parameters */
|
||||
sqlite3_rtree_dbl *aParam; /* value of function parameters */
|
||||
void *pUser; /* callback can use this, if desired */
|
||||
void (*xDelUser)(void*); /* function to free pUser */
|
||||
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
|
||||
unsigned int *anQueue; /* Number of pending entries in the queue */
|
||||
int nCoord; /* Number of coordinates */
|
||||
int iLevel; /* Level of current node or entry */
|
||||
int mxLevel; /* The largest iLevel value in the tree */
|
||||
sqlite3_int64 iRowid; /* Rowid for current entry */
|
||||
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
|
||||
int eParentWithin; /* Visibility of parent node */
|
||||
int eWithin; /* OUT: Visiblity */
|
||||
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
|
||||
*/
|
||||
#define NOT_WITHIN 0 /* Object completely outside of query region */
|
||||
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
|
||||
#define FULLY_WITHIN 2 /* Object fully contained within query region */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
|
@ -9,7 +9,9 @@
|
||||
package org.telegram.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
@ -21,17 +23,23 @@ import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.ui.ApplicationLoader;
|
||||
import org.telegram.ui.Views.NumberPicker;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AndroidUtilities {
|
||||
|
||||
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<String, Typeface>();
|
||||
private static int prevOrientation = -10;
|
||||
private static boolean waitingForSms = false;
|
||||
@ -210,7 +218,7 @@ public class AndroidUtilities {
|
||||
}
|
||||
|
||||
public static File getCacheDir() {
|
||||
if (Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
|
||||
if (Environment.getExternalStorageState() == null || Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
|
||||
try {
|
||||
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
|
||||
if (file != null) {
|
||||
@ -239,6 +247,10 @@ public class AndroidUtilities {
|
||||
return (int)Math.ceil(density * value);
|
||||
}
|
||||
|
||||
public static float dpf2(float value) {
|
||||
return density * value;
|
||||
}
|
||||
|
||||
public static void checkDisplaySize() {
|
||||
try {
|
||||
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
@ -262,6 +274,22 @@ public class AndroidUtilities {
|
||||
return 0x0000000100000000L | ((long)id & 0x00000000FFFFFFFFL);
|
||||
}
|
||||
|
||||
public static int getMyLayerVersion(int layer) {
|
||||
return layer & 0xffff;
|
||||
}
|
||||
|
||||
public static int getPeerLayerVersion(int layer) {
|
||||
return (layer >> 16) & 0xffff;
|
||||
}
|
||||
|
||||
public static int setMyLayerVersion(int layer, int version) {
|
||||
return layer & 0xffff0000 | version;
|
||||
}
|
||||
|
||||
public static int setPeerLayerVersion(int layer, int version) {
|
||||
return layer & 0x0000ffff | (version << 16);
|
||||
}
|
||||
|
||||
public static void RunOnUIThread(Runnable runnable) {
|
||||
RunOnUIThread(runnable, 0);
|
||||
}
|
||||
@ -274,6 +302,10 @@ public class AndroidUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
public static void CancelRunOnUIThread(Runnable runnable) {
|
||||
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
|
||||
}
|
||||
|
||||
public static boolean isTablet() {
|
||||
if (isTablet == null) {
|
||||
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
|
||||
@ -367,4 +399,106 @@ public class AndroidUtilities {
|
||||
}
|
||||
return photoSize;
|
||||
}
|
||||
|
||||
public static String formatTTLString(int ttl) {
|
||||
if (ttl < 60) {
|
||||
return LocaleController.formatPluralString("Seconds", ttl);
|
||||
} else if (ttl < 60 * 60) {
|
||||
return LocaleController.formatPluralString("Minutes", ttl / 60);
|
||||
} else if (ttl < 60 * 60 * 24) {
|
||||
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
|
||||
} else if (ttl < 60 * 60 * 24 * 7) {
|
||||
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
|
||||
} else {
|
||||
int days = ttl / 60 / 60 / 24;
|
||||
if (ttl % 7 == 0) {
|
||||
return LocaleController.formatPluralString("Weeks", days / 7);
|
||||
} else {
|
||||
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AlertDialog.Builder buildTTLAlert(final Context context, final TLRPC.EncryptedChat encryptedChat) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
|
||||
final NumberPicker numberPicker = new NumberPicker(context);
|
||||
numberPicker.setMinValue(0);
|
||||
numberPicker.setMaxValue(20);
|
||||
if (encryptedChat.ttl > 0 && encryptedChat.ttl < 16) {
|
||||
numberPicker.setValue(encryptedChat.ttl);
|
||||
} else if (encryptedChat.ttl == 30) {
|
||||
numberPicker.setValue(16);
|
||||
} else if (encryptedChat.ttl == 60) {
|
||||
numberPicker.setValue(17);
|
||||
} else if (encryptedChat.ttl == 60 * 60) {
|
||||
numberPicker.setValue(18);
|
||||
} else if (encryptedChat.ttl == 60 * 60 * 24) {
|
||||
numberPicker.setValue(19);
|
||||
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
|
||||
numberPicker.setValue(20);
|
||||
} else if (encryptedChat.ttl == 0) {
|
||||
numberPicker.setValue(5);
|
||||
}
|
||||
numberPicker.setFormatter(new NumberPicker.Formatter() {
|
||||
@Override
|
||||
public String format(int value) {
|
||||
if (value == 0) {
|
||||
return LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever);
|
||||
} else if (value >= 1 && value < 16) {
|
||||
return AndroidUtilities.formatTTLString(value);
|
||||
} else if (value == 16) {
|
||||
return AndroidUtilities.formatTTLString(30);
|
||||
} else if (value == 17) {
|
||||
return AndroidUtilities.formatTTLString(60);
|
||||
} else if (value == 18) {
|
||||
return AndroidUtilities.formatTTLString(60 * 60);
|
||||
} else if (value == 19) {
|
||||
return AndroidUtilities.formatTTLString(60 * 60 * 24);
|
||||
} else if (value == 20) {
|
||||
return AndroidUtilities.formatTTLString(60 * 60 * 24 * 7);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
builder.setView(numberPicker);
|
||||
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int oldValue = encryptedChat.ttl;
|
||||
which = numberPicker.getValue();
|
||||
if (which >= 0 && which < 16) {
|
||||
encryptedChat.ttl = which;
|
||||
} else if (which == 16) {
|
||||
encryptedChat.ttl = 30;
|
||||
} else if (which == 17) {
|
||||
encryptedChat.ttl = 60;
|
||||
} else if (which == 18) {
|
||||
encryptedChat.ttl = 60 * 60;
|
||||
} else if (which == 19) {
|
||||
encryptedChat.ttl = 60 * 60 * 24;
|
||||
} else if (which == 20) {
|
||||
encryptedChat.ttl = 60 * 60 * 24 * 7;
|
||||
}
|
||||
if (oldValue != encryptedChat.ttl) {
|
||||
SendMessagesHelper.getInstance().sendTTLMessage(encryptedChat, null);
|
||||
MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat);
|
||||
}
|
||||
}
|
||||
});
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static void clearCursorDrawable(EditText editText) {
|
||||
if (editText == null || Build.VERSION.SDK_INT < 12) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
|
||||
mCursorDrawableRes.setAccessible(true);
|
||||
mCursorDrawableRes.setInt(editText, 0);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ public class ContactsController {
|
||||
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
|
||||
|
||||
HashMap<String, Contact> shortContacts = new HashMap<String, Contact>();
|
||||
String ids = "";
|
||||
StringBuilder ids = new StringBuilder();
|
||||
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
|
||||
if (pCur != null) {
|
||||
if (pCur.getCount() > 0) {
|
||||
@ -262,9 +262,9 @@ public class ContactsController {
|
||||
|
||||
Integer id = pCur.getInt(0);
|
||||
if (ids.length() != 0) {
|
||||
ids += ",";
|
||||
ids.append(",");
|
||||
}
|
||||
ids += id;
|
||||
ids.append(id);
|
||||
|
||||
int type = pCur.getInt(2);
|
||||
Contact contact = contactsMap.get(id);
|
||||
@ -299,7 +299,7 @@ public class ContactsController {
|
||||
pCur.close();
|
||||
}
|
||||
|
||||
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
|
||||
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids.toString() + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
|
||||
if (pCur != null && pCur.getCount() > 0) {
|
||||
while (pCur.moveToNext()) {
|
||||
int id = pCur.getInt(0);
|
||||
@ -844,14 +844,14 @@ public class ContactsController {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
String ids = "";
|
||||
StringBuilder ids = new StringBuilder();
|
||||
for (TLRPC.TL_contact aContactsArr : contactsArr) {
|
||||
if (ids.length() != 0) {
|
||||
ids += ",";
|
||||
ids.append(",");
|
||||
}
|
||||
ids += aContactsArr.user_id;
|
||||
ids.append(aContactsArr.user_id);
|
||||
}
|
||||
UserConfig.contactsHash = Utilities.MD5(ids);
|
||||
UserConfig.contactsHash = Utilities.MD5(ids.toString());
|
||||
UserConfig.saveConfig(false);
|
||||
}
|
||||
|
||||
@ -1084,7 +1084,7 @@ public class ContactsController {
|
||||
});
|
||||
}
|
||||
|
||||
String ids = "";
|
||||
StringBuilder ids = new StringBuilder();
|
||||
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
|
||||
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
|
||||
|
||||
@ -1114,11 +1114,11 @@ public class ContactsController {
|
||||
}
|
||||
arr.add(value);
|
||||
if (ids.length() != 0) {
|
||||
ids += ",";
|
||||
ids.append(",");
|
||||
}
|
||||
ids += value.user_id;
|
||||
ids.append(value.user_id);
|
||||
}
|
||||
UserConfig.contactsHash = Utilities.MD5(ids);
|
||||
UserConfig.contactsHash = Utilities.MD5(ids.toString());
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
Collections.sort(sortedSectionsArray, new Comparator<String>() {
|
||||
@ -1189,8 +1189,8 @@ public class ContactsController {
|
||||
}
|
||||
FileLog.e("tmessages", "process update - contacts add = " + newC.size() + " delete = " + contactsTD.size());
|
||||
|
||||
String toAdd = "";
|
||||
String toDelete = "";
|
||||
StringBuilder toAdd = new StringBuilder();
|
||||
StringBuilder toDelete = new StringBuilder();
|
||||
boolean reloadContacts = false;
|
||||
|
||||
for (TLRPC.TL_contact newContact : newC) {
|
||||
@ -1216,9 +1216,9 @@ public class ContactsController {
|
||||
}
|
||||
}
|
||||
if (toAdd.length() != 0) {
|
||||
toAdd += ",";
|
||||
toAdd.append(",");
|
||||
}
|
||||
toAdd += user.phone;
|
||||
toAdd.append(user.phone);
|
||||
}
|
||||
|
||||
for (final Integer uid : contactsTD) {
|
||||
@ -1252,14 +1252,14 @@ public class ContactsController {
|
||||
}
|
||||
}
|
||||
if (toDelete.length() != 0) {
|
||||
toDelete += ",";
|
||||
toDelete.append(",");
|
||||
}
|
||||
toDelete += user.phone;
|
||||
toDelete.append(user.phone);
|
||||
}
|
||||
}
|
||||
|
||||
if (toAdd.length() != 0 || toDelete.length() != 0) {
|
||||
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd, toDelete);
|
||||
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd.toString(), toDelete.toString());
|
||||
}
|
||||
|
||||
if (reloadContacts) {
|
||||
|
@ -28,7 +28,6 @@ import android.provider.MediaStore;
|
||||
import org.telegram.messenger.DispatchQueue;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
@ -293,7 +292,7 @@ public class ImageLoader {
|
||||
}
|
||||
}
|
||||
if (image != null && blur && bitmapH < 100 && bitmapW < 100) {
|
||||
Utilities.blurBitmap(image);
|
||||
Utilities.blurBitmap(image, 3);
|
||||
}
|
||||
}
|
||||
if (runtimeHack != null) {
|
||||
@ -832,6 +831,10 @@ public class ImageLoader {
|
||||
});
|
||||
}
|
||||
|
||||
public void putImageToCache(BitmapDrawable bitmap, String key) {
|
||||
memCache.put(key, bitmap);
|
||||
}
|
||||
|
||||
public void loadImage(final TLRPC.FileLocation fileLocation, final String httpUrl, final ImageReceiver imageView, final int size, final boolean cacheOnly) {
|
||||
if ((fileLocation == null && httpUrl == null) || imageView == null || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation))) {
|
||||
return;
|
||||
|
@ -9,8 +9,13 @@
|
||||
package org.telegram.android;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
@ -35,6 +40,13 @@ public class ImageReceiver {
|
||||
private boolean isVisible = true;
|
||||
private boolean isAspectFit = false;
|
||||
private boolean lastCacheOnly = false;
|
||||
private boolean forcePreview = false;
|
||||
private int roundRadius = 0;
|
||||
private BitmapShader bitmapShader = null;
|
||||
private Paint roundPaint = null;
|
||||
private RectF roundRect = null;
|
||||
private RectF bitmapRect = null;
|
||||
private Matrix shaderMatrix = null;
|
||||
|
||||
public ImageReceiver() {
|
||||
|
||||
@ -65,6 +77,7 @@ public class ImageReceiver {
|
||||
last_httpUrl = null;
|
||||
last_filter = null;
|
||||
lastCacheOnly = false;
|
||||
bitmapShader = null;
|
||||
last_placeholder = placeholder;
|
||||
last_size = 0;
|
||||
currentImage = null;
|
||||
@ -104,9 +117,13 @@ public class ImageReceiver {
|
||||
last_placeholder = placeholder;
|
||||
last_size = size;
|
||||
lastCacheOnly = cacheOnly;
|
||||
bitmapShader = null;
|
||||
if (img == null) {
|
||||
isPlaceholder = true;
|
||||
ImageLoader.getInstance().loadImage(fileLocation, httpUrl, this, size, cacheOnly);
|
||||
if (parentView != null) {
|
||||
parentView.invalidate();
|
||||
}
|
||||
} else {
|
||||
setImageBitmap(img, currentPath);
|
||||
}
|
||||
@ -119,6 +136,11 @@ public class ImageReceiver {
|
||||
isPlaceholder = false;
|
||||
ImageLoader.getInstance().incrementUseCount(currentPath);
|
||||
currentImage = bitmap;
|
||||
if (roundRadius != 0) {
|
||||
bitmapShader = new BitmapShader(bitmap.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
roundPaint.setShader(bitmapShader);
|
||||
bitmapRect.set(0, 0, bitmap.getIntrinsicWidth(), bitmap.getIntrinsicHeight());
|
||||
}
|
||||
if (parentView != null) {
|
||||
parentView.invalidate();
|
||||
}
|
||||
@ -138,6 +160,7 @@ public class ImageReceiver {
|
||||
last_httpUrl = null;
|
||||
last_filter = null;
|
||||
currentImage = null;
|
||||
bitmapShader = null;
|
||||
last_size = 0;
|
||||
lastCacheOnly = false;
|
||||
if (parentView != null) {
|
||||
@ -155,6 +178,7 @@ public class ImageReceiver {
|
||||
last_path = null;
|
||||
last_httpUrl = null;
|
||||
last_filter = null;
|
||||
bitmapShader = null;
|
||||
last_size = 0;
|
||||
lastCacheOnly = false;
|
||||
if (parentView != null) {
|
||||
@ -192,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 {
|
||||
Drawable bitmapDrawable = currentImage;
|
||||
if (bitmapDrawable == null && last_placeholder != null && last_placeholder instanceof BitmapDrawable) {
|
||||
if (forcePreview || bitmapDrawable == null && last_placeholder != null && last_placeholder instanceof BitmapDrawable) {
|
||||
bitmapDrawable = last_placeholder;
|
||||
}
|
||||
if (bitmapDrawable != null) {
|
||||
int bitmapW = bitmapDrawable.getIntrinsicWidth();
|
||||
int bitmapH = bitmapDrawable.getIntrinsicHeight();
|
||||
float scaleW = bitmapW / (float)w;
|
||||
float scaleH = bitmapH / (float)h;
|
||||
|
||||
if (isAspectFit) {
|
||||
float scale = Math.max(scaleW, scaleH);
|
||||
canvas.save();
|
||||
bitmapW /= scale;
|
||||
bitmapH /= scale;
|
||||
drawRegion.set(x + (w - bitmapW) / 2, y + (h - bitmapH) / 2, x + (w + bitmapW) / 2, y + (h + bitmapH) / 2);
|
||||
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();
|
||||
if (bitmapShader != null) {
|
||||
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
|
||||
roundRect.set(imageX, imageY, imageX + imageW, imageY + imageH);
|
||||
shaderMatrix.reset();
|
||||
shaderMatrix.setScale(1.5f, 1.5f);
|
||||
bitmapShader.setLocalMatrix(shaderMatrix);
|
||||
canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint);
|
||||
} else {
|
||||
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.clipRect(x, y, x + w, y + h);
|
||||
|
||||
if (bitmapW / scaleH > w) {
|
||||
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);
|
||||
}
|
||||
bitmapW /= scale;
|
||||
bitmapH /= scale;
|
||||
drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 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);
|
||||
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(x, y, x + w, y + h);
|
||||
bitmapDrawable.setBounds(drawRegion);
|
||||
if (isVisible) {
|
||||
try {
|
||||
bitmapDrawable.draw(canvas);
|
||||
} catch (Exception e) {
|
||||
if (currentPath != null) {
|
||||
ImageLoader.getInstance().removeImage(currentPath);
|
||||
currentPath = null;
|
||||
if (Math.abs(scaleW - scaleH) > 0.00001f) {
|
||||
canvas.save();
|
||||
canvas.clipRect(imageX, imageY, imageX + imageW, imageY + imageH);
|
||||
|
||||
if (bitmapW / scaleH > imageW) {
|
||||
bitmapW /= scaleH;
|
||||
drawRegion.set(imageX - (bitmapW - imageW) / 2, imageY, imageX + (bitmapW + imageW) / 2, imageY + imageH);
|
||||
} else {
|
||||
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;
|
||||
} else if (last_placeholder != null) {
|
||||
drawRegion.set(x, y, x + w, y + h);
|
||||
drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH);
|
||||
last_placeholder.setBounds(drawRegion);
|
||||
if (isVisible) {
|
||||
try {
|
||||
@ -371,4 +404,23 @@ public class ImageReceiver {
|
||||
public String getKey() {
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
public void setForcePreview(boolean value) {
|
||||
forcePreview = value;
|
||||
}
|
||||
|
||||
public void setRoundRadius(int value) {
|
||||
roundRadius = value;
|
||||
if (roundRadius != 0) {
|
||||
roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
roundRect = new RectF();
|
||||
shaderMatrix = new Matrix();
|
||||
bitmapRect = new RectF();
|
||||
} else {
|
||||
roundPaint = null;
|
||||
roundRect = null;
|
||||
shaderMatrix = null;
|
||||
bitmapRect = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Point;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioRecord;
|
||||
@ -36,7 +38,9 @@ import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.MediaStore;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.telegram.android.video.InputSurface;
|
||||
import org.telegram.android.video.MP4Builder;
|
||||
@ -58,6 +62,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
@ -340,13 +345,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
}
|
||||
}
|
||||
private String[] mediaProjections = new String[] {
|
||||
MediaStore.Images.ImageColumns.DATA,
|
||||
MediaStore.Images.ImageColumns.DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.DATE_TAKEN,
|
||||
MediaStore.Images.ImageColumns.TITLE
|
||||
};
|
||||
private String[] mediaProjections = null;
|
||||
|
||||
private static volatile MediaController Instance = null;
|
||||
public static MediaController getInstance() {
|
||||
@ -400,6 +399,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileLoadProgressChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog);
|
||||
|
||||
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@ -413,6 +414,26 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
if (UserConfig.isClientActivated()) {
|
||||
checkAutodownloadSettings();
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
mediaProjections = new String[] {
|
||||
MediaStore.Images.ImageColumns.DATA,
|
||||
MediaStore.Images.ImageColumns.DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.DATE_TAKEN,
|
||||
MediaStore.Images.ImageColumns.TITLE,
|
||||
MediaStore.Images.ImageColumns.WIDTH,
|
||||
MediaStore.Images.ImageColumns.HEIGHT
|
||||
};
|
||||
} else {
|
||||
mediaProjections = new String[] {
|
||||
MediaStore.Images.ImageColumns.DATA,
|
||||
MediaStore.Images.ImageColumns.DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.DATE_TAKEN,
|
||||
MediaStore.Images.ImageColumns.TITLE
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void startProgressTimer() {
|
||||
@ -684,7 +705,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
|
||||
public void startMediaObserver() {
|
||||
if (android.os.Build.VERSION.SDK_INT > 0) { //disable while it's not perferct
|
||||
if (android.os.Build.VERSION.SDK_INT < 14) {
|
||||
return;
|
||||
}
|
||||
ApplicationLoader.applicationHandler.removeCallbacks(stopMediaObserverRunnable);
|
||||
@ -706,7 +727,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
|
||||
public void stopMediaObserver() {
|
||||
if (android.os.Build.VERSION.SDK_INT > 0) { //disable while it's not perferct
|
||||
if (android.os.Build.VERSION.SDK_INT < 14) {
|
||||
return;
|
||||
}
|
||||
if (stopMediaObserverRunnable == null) {
|
||||
@ -718,6 +739,30 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
|
||||
public void processMediaObserver(Uri uri) {
|
||||
try {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
try {
|
||||
WindowManager windowManager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Point size = new Point();
|
||||
windowManager.getDefaultDisplay().getRealSize(size);
|
||||
width = size.x;
|
||||
height = size.y;
|
||||
} else {
|
||||
try {
|
||||
Method mGetRawW = Display.class.getMethod("getRawWidth");
|
||||
Method mGetRawH = Display.class.getMethod("getRawHeight");
|
||||
width = (Integer) mGetRawW.invoke(windowManager.getDefaultDisplay());
|
||||
height = (Integer) mGetRawH.invoke(windowManager.getDefaultDisplay());
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, mediaProjections, null, null, "date_added DESC LIMIT 1");
|
||||
final ArrayList<Long> screenshotDates = new ArrayList<Long>();
|
||||
if (cursor != null) {
|
||||
@ -726,75 +771,33 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
String data = cursor.getString(0);
|
||||
String display_name = cursor.getString(1);
|
||||
String album_name = cursor.getString(2);
|
||||
String title = cursor.getString(4);
|
||||
long date = cursor.getLong(3);
|
||||
String title = cursor.getString(4);
|
||||
int photoW = 0;
|
||||
int photoH = 0;
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
photoW = cursor.getInt(5);
|
||||
photoH = cursor.getInt(6);
|
||||
}
|
||||
if (data != null && data.toLowerCase().contains("screenshot") ||
|
||||
display_name != null && display_name.toLowerCase().contains("screenshot") ||
|
||||
album_name != null && album_name.toLowerCase().contains("screenshot") ||
|
||||
title != null && title.toLowerCase().contains("screenshot")) {
|
||||
/*BitmapRegionDecoder bitmapRegionDecoder = null;
|
||||
boolean added = false;
|
||||
try {
|
||||
int waitCount = 0;
|
||||
while (waitCount < 5 && bitmapRegionDecoder == null) {
|
||||
try {
|
||||
bitmapRegionDecoder = BitmapRegionDecoder.newInstance(data, true);
|
||||
if (bitmapRegionDecoder != null) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
if (photoW == 0 || photoH == 0) {
|
||||
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
||||
bmOptions.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(data, bmOptions);
|
||||
photoW = bmOptions.outWidth;
|
||||
photoH = bmOptions.outHeight;
|
||||
}
|
||||
if (bitmapRegionDecoder != null) {
|
||||
Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(0, 0, AndroidUtilities.dp(44), AndroidUtilities.dp(44)), null);
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
for (int y = 0; y < h; y++) {
|
||||
int rowCount = 0;
|
||||
for (int x = 0; x < w; x++) {
|
||||
int px = bitmap.getPixel(x, y);
|
||||
if (px == 0xffffffff) {
|
||||
rowCount++;
|
||||
} else {
|
||||
rowCount = 0;
|
||||
}
|
||||
if (rowCount > 8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rowCount > 8) {
|
||||
screenshotDates.add(date);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bitmapRegionDecoder.recycle();
|
||||
try {
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
try {
|
||||
if (bitmapRegionDecoder != null) {
|
||||
bitmapRegionDecoder.recycle();
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
FileLog.e("tmessages", e2);
|
||||
}
|
||||
if (!added) {
|
||||
if (photoW <= 0 || photoH <= 0 || (photoW == width && photoH == height || photoH == width && photoW == height)) {
|
||||
screenshotDates.add(date);
|
||||
}
|
||||
}*/
|
||||
screenshotDates.add(date);
|
||||
} catch (Exception e) {
|
||||
screenshotDates.add(date);
|
||||
}
|
||||
}
|
||||
FileLog.e("tmessages", "screenshot!");
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
@ -831,7 +834,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
}
|
||||
if (send) {
|
||||
SendMessagesHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages);
|
||||
SendMessagesHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -898,6 +901,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
deleteLaterArray.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileDidFailedLoad) {
|
||||
@ -961,6 +965,18 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
listenerInProgress = false;
|
||||
processLaterArrays();
|
||||
} else if (id == NotificationCenter.messagesDeleted) {
|
||||
if (playingMessageObject != null) {
|
||||
ArrayList<Integer> markAsDeletedMessages = (ArrayList<Integer>)args[0];
|
||||
if (markAsDeletedMessages.contains(playingMessageObject.messageOwner.id)) {
|
||||
clenupPlayer(false);
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.removeAllMessagesFromDialog) {
|
||||
long did = (Long)args[0];
|
||||
if (playingMessageObject != null && playingMessageObject.getDialogId() == did) {
|
||||
clenupPlayer(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1180,6 +1196,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
return true;
|
||||
}
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject);
|
||||
clenupPlayer(true);
|
||||
final File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner);
|
||||
|
||||
@ -1205,7 +1222,6 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
|
||||
audioTrackPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, playerBufferSize, AudioTrack.MODE_STREAM);
|
||||
audioTrackPlayer.setStereoVolume(1.0f, 1.0f);
|
||||
//audioTrackPlayer.setNotificationMarkerPosition((int)currentTotalPcmDuration);
|
||||
audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() {
|
||||
@Override
|
||||
public void onMarkerReached(AudioTrack audioTrack) {
|
||||
@ -2081,12 +2097,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
if (end < 0 || info.presentationTimeUs < end) {
|
||||
info.offset = 0;
|
||||
info.flags = extractor.getSampleFlags();
|
||||
if (!isAudio) {
|
||||
buffer.limit(info.offset + info.size);
|
||||
buffer.position(info.offset);
|
||||
buffer.putInt(info.size - 4);
|
||||
}
|
||||
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
|
||||
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info, isAudio)) {
|
||||
didWriteData(messageObject, file, false, false);
|
||||
}
|
||||
extractor.advance();
|
||||
@ -2168,10 +2179,28 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
resultWidth = temp;
|
||||
rotationValue = 90;
|
||||
rotateRender = 270;
|
||||
} else if (Build.VERSION.SDK_INT > 20) {
|
||||
if (rotationValue == 90) {
|
||||
int temp = resultHeight;
|
||||
resultHeight = resultWidth;
|
||||
resultWidth = temp;
|
||||
rotationValue = 0;
|
||||
rotateRender = 270;
|
||||
} else if (rotationValue == 180) {
|
||||
rotateRender = 180;
|
||||
rotationValue = 0;
|
||||
} else if (rotationValue == 270) {
|
||||
int temp = resultHeight;
|
||||
resultHeight = resultWidth;
|
||||
resultWidth = temp;
|
||||
rotationValue = 0;
|
||||
rotateRender = 90;
|
||||
}
|
||||
}
|
||||
|
||||
File inputFile = new File(videoPath);
|
||||
if (!inputFile.canRead()) {
|
||||
didWriteData(messageObject, cacheFile, true, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2374,10 +2403,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
}
|
||||
if (info.size > 1) {
|
||||
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
|
||||
encodedData.limit(info.offset + info.size);
|
||||
encodedData.position(info.offset);
|
||||
encodedData.putInt(Integer.reverseBytes(info.size - 4));
|
||||
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
|
||||
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) {
|
||||
didWriteData(messageObject, cacheFile, false, false);
|
||||
}
|
||||
} else if (videoTrackIndex == -5) {
|
||||
@ -2552,6 +2578,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
||||
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
|
||||
}
|
||||
} else {
|
||||
didWriteData(messageObject, cacheFile, true, true);
|
||||
return false;
|
||||
}
|
||||
didWriteData(messageObject, cacheFile, true, error);
|
||||
|
@ -12,15 +12,20 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Paint;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.util.Linkify;
|
||||
|
||||
import org.telegram.messenger.ConnectionsManager;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.ui.Views.URLSpanNoUnderline;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
@ -90,7 +95,7 @@ public class MessageObject {
|
||||
messageText = LocaleController.getString("ActionYouCreateGroup", R.string.ActionYouCreateGroup);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", "");
|
||||
}
|
||||
@ -101,26 +106,27 @@ public class MessageObject {
|
||||
messageText = LocaleController.getString("ActionYouLeftUser", R.string.ActionYouLeftUser);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", "");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TLRPC.User who = null;
|
||||
TLRPC.User whoUser = null;
|
||||
if (users != null) {
|
||||
who = users.get(message.action.user_id);
|
||||
whoUser = users.get(message.action.user_id);
|
||||
}
|
||||
if (who == null) {
|
||||
who = MessagesController.getInstance().getUser(message.action.user_id);
|
||||
if (whoUser == null) {
|
||||
whoUser = MessagesController.getInstance().getUser(message.action.user_id);
|
||||
}
|
||||
if (who != null && fromUser != null) {
|
||||
if (whoUser != null && fromUser != null) {
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser), "un2", whoUser);
|
||||
} else if (message.action.user_id == UserConfig.getClientUserId()) {
|
||||
messageText = LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionKickUser", R.string.ActionKickUser), "un2", whoUser);
|
||||
messageText = replaceWithLink(messageText, "un1", fromUser);
|
||||
}
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", "").replace("un1", "");
|
||||
@ -136,11 +142,12 @@ public class MessageObject {
|
||||
}
|
||||
if (whoUser != null && fromUser != null) {
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser), "un2", whoUser);
|
||||
} else if (message.action.user_id == UserConfig.getClientUserId()) {
|
||||
messageText = LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionAddUser", R.string.ActionAddUser), "un2", whoUser);
|
||||
messageText = replaceWithLink(messageText, "un1", fromUser);
|
||||
}
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", "").replace("un1", "");
|
||||
@ -150,7 +157,7 @@ public class MessageObject {
|
||||
messageText = LocaleController.getString("ActionYouChangedPhoto", R.string.ActionYouChangedPhoto);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", "");
|
||||
}
|
||||
@ -160,7 +167,7 @@ public class MessageObject {
|
||||
messageText = LocaleController.getString("ActionYouChangedTitle", R.string.ActionYouChangedTitle).replace("un2", message.action.title);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un2", message.action.title), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", "").replace("un2", message.action.title);
|
||||
}
|
||||
@ -170,36 +177,20 @@ public class MessageObject {
|
||||
messageText = LocaleController.getString("ActionYouRemovedPhoto", R.string.ActionYouRemovedPhoto);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", "");
|
||||
}
|
||||
}
|
||||
} else if (message.action instanceof TLRPC.TL_messageActionTTLChange) {
|
||||
if (message.action.ttl != 0) {
|
||||
String timeString;
|
||||
if (message.action.ttl == 2) {
|
||||
timeString = LocaleController.getString("MessageLifetime2s", R.string.MessageLifetime2s);
|
||||
} else if (message.action.ttl == 5) {
|
||||
timeString = LocaleController.getString("MessageLifetime5s", R.string.MessageLifetime5s);
|
||||
} else if (message.action.ttl == 60) {
|
||||
timeString = LocaleController.getString("MessageLifetime1m", R.string.MessageLifetime1m);
|
||||
} else if (message.action.ttl == 60 * 60) {
|
||||
timeString = LocaleController.getString("MessageLifetime1h", R.string.MessageLifetime1h);
|
||||
} else if (message.action.ttl == 60 * 60 * 24) {
|
||||
timeString = LocaleController.getString("MessageLifetime1d", R.string.MessageLifetime1d);
|
||||
} else if (message.action.ttl == 60 * 60 * 24 * 7) {
|
||||
timeString = LocaleController.getString("MessageLifetime1w", R.string.MessageLifetime1w);
|
||||
} else {
|
||||
timeString = String.format("%d", message.action.ttl);
|
||||
}
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, timeString);
|
||||
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, AndroidUtilities.formatTTLString(message.action.ttl));
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, timeString);
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, AndroidUtilities.formatTTLString(message.action.ttl));
|
||||
} else {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", timeString);
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", AndroidUtilities.formatTTLString(message.action.ttl));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -241,17 +232,40 @@ public class MessageObject {
|
||||
} else {
|
||||
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, "");
|
||||
}
|
||||
} else if (message.action instanceof TLRPC.TL_messageEcryptedAction) {
|
||||
} else if (message.action instanceof TLRPC.TL_messageEncryptedAction) {
|
||||
if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.formatString("ActionTakeScreenshootYou", R.string.ActionTakeScreenshootYou);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.formatString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot).replace("un1", fromUser.first_name);
|
||||
messageText = replaceWithLink(LocaleController.getString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot), "un1", fromUser);
|
||||
} else {
|
||||
messageText = LocaleController.formatString("ActionTakeScreenshoot", R.string.ActionTakeScreenshoot).replace("un1", "");
|
||||
}
|
||||
}
|
||||
} else if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
|
||||
TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL) message.action.encryptedAction;
|
||||
if (action.ttl_seconds != 0) {
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChangedOutgoing", R.string.MessageLifetimeChangedOutgoing, AndroidUtilities.formatTTLString(action.ttl_seconds));
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, fromUser.first_name, AndroidUtilities.formatTTLString(action.ttl_seconds));
|
||||
} else {
|
||||
messageText = LocaleController.formatString("MessageLifetimeChanged", R.string.MessageLifetimeChanged, "", AndroidUtilities.formatTTLString(action.ttl_seconds));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isFromMe()) {
|
||||
messageText = LocaleController.getString("MessageLifetimeYouRemoved", R.string.MessageLifetimeYouRemoved);
|
||||
} else {
|
||||
if (fromUser != null) {
|
||||
messageText = LocaleController.formatString("MessageLifetimeRemoved", R.string.MessageLifetimeRemoved, fromUser.first_name);
|
||||
} else {
|
||||
messageText = LocaleController.formatString("MessageLifetimeRemoved", R.string.MessageLifetimeRemoved, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (message.action instanceof TLRPC.TL_messageActionCreatedBroadcastList) {
|
||||
messageText = LocaleController.formatString("YouCreatedBroadcastList", R.string.YouCreatedBroadcastList);
|
||||
@ -278,7 +292,7 @@ public class MessageObject {
|
||||
}
|
||||
messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20));
|
||||
|
||||
if (message instanceof TLRPC.TL_message || (message instanceof TLRPC.TL_messageForwarded && (message.media == null || !(message.media instanceof TLRPC.TL_messageMediaEmpty)))) {
|
||||
if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded) {
|
||||
if (message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty) {
|
||||
contentType = type = 0;
|
||||
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
@ -290,13 +304,8 @@ public class MessageObject {
|
||||
contentType = 1;
|
||||
type = 3;
|
||||
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaContact) {
|
||||
if (isFromMe()) {
|
||||
contentType = 3;
|
||||
type = 12;
|
||||
} else {
|
||||
contentType = 4;
|
||||
type = 13;
|
||||
}
|
||||
contentType = 3;
|
||||
type = 12;
|
||||
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaUnsupported) {
|
||||
contentType = type = 0;
|
||||
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
@ -313,14 +322,20 @@ public class MessageObject {
|
||||
if (message.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
|
||||
contentType = type = 0;
|
||||
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto || message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
|
||||
contentType = 8;
|
||||
contentType = 4;
|
||||
type = 11;
|
||||
} else if (message.action instanceof TLRPC.TL_messageEncryptedAction) {
|
||||
if (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
|
||||
contentType = 4;
|
||||
type = 10;
|
||||
} else {
|
||||
contentType = -1;
|
||||
type = -1;
|
||||
}
|
||||
} else {
|
||||
contentType = 7;
|
||||
contentType = 4;
|
||||
type = 10;
|
||||
}
|
||||
} else if (message instanceof TLRPC.TL_messageForwarded) {
|
||||
contentType = type = 0;
|
||||
}
|
||||
|
||||
Calendar rightNow = new GregorianCalendar();
|
||||
@ -334,13 +349,22 @@ public class MessageObject {
|
||||
generateThumbs(false, preview);
|
||||
}
|
||||
|
||||
public CharSequence replaceWithLink(CharSequence source, String param, TLRPC.User user) {
|
||||
String name = ContactsController.formatName(user.first_name, user.last_name);
|
||||
int start = TextUtils.indexOf(source, param);
|
||||
URLSpanNoUnderline span = new URLSpanNoUnderline("" + user.id);
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new String[]{name}));
|
||||
builder.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public void generateThumbs(boolean update, int preview) {
|
||||
if (messageOwner instanceof TLRPC.TL_messageService) {
|
||||
if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
|
||||
if (!update) {
|
||||
photoThumbs = new ArrayList<PhotoObject>();
|
||||
for (TLRPC.PhotoSize size : messageOwner.action.photo.sizes) {
|
||||
photoThumbs.add(new PhotoObject(size, preview));
|
||||
photoThumbs.add(new PhotoObject(size, preview, isSecretMedia()));
|
||||
}
|
||||
} else if (photoThumbs != null && !photoThumbs.isEmpty()) {
|
||||
for (PhotoObject photoObject : photoThumbs) {
|
||||
@ -361,7 +385,7 @@ public class MessageObject {
|
||||
if (!update) {
|
||||
photoThumbs = new ArrayList<PhotoObject>();
|
||||
for (TLRPC.PhotoSize size : messageOwner.media.photo.sizes) {
|
||||
PhotoObject obj = new PhotoObject(size, preview);
|
||||
PhotoObject obj = new PhotoObject(size, preview, isSecretMedia());
|
||||
photoThumbs.add(obj);
|
||||
if (imagePreview == null && obj.image != null) {
|
||||
imagePreview = obj.image;
|
||||
@ -383,7 +407,7 @@ public class MessageObject {
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
|
||||
if (!update) {
|
||||
photoThumbs = new ArrayList<PhotoObject>();
|
||||
PhotoObject obj = new PhotoObject(messageOwner.media.video.thumb, preview);
|
||||
PhotoObject obj = new PhotoObject(messageOwner.media.video.thumb, preview, isSecretMedia());
|
||||
photoThumbs.add(obj);
|
||||
if (imagePreview == null && obj.image != null) {
|
||||
imagePreview = obj.image;
|
||||
@ -396,7 +420,7 @@ public class MessageObject {
|
||||
if (!(messageOwner.media.document.thumb instanceof TLRPC.TL_photoSizeEmpty)) {
|
||||
if (!update) {
|
||||
photoThumbs = new ArrayList<PhotoObject>();
|
||||
PhotoObject obj = new PhotoObject(messageOwner.media.document.thumb, preview);
|
||||
PhotoObject obj = new PhotoObject(messageOwner.media.document.thumb, preview, isSecretMedia());
|
||||
photoThumbs.add(obj);
|
||||
} else if (photoThumbs != null && !photoThumbs.isEmpty() && messageOwner.media.document.thumb != null) {
|
||||
PhotoObject photoObject = photoThumbs.get(0);
|
||||
@ -599,15 +623,46 @@ public class MessageObject {
|
||||
}
|
||||
|
||||
public boolean isOut() {
|
||||
return messageOwner.out;
|
||||
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
|
||||
}
|
||||
|
||||
public boolean isFromMe() {
|
||||
return messageOwner.from_id == UserConfig.getClientUserId();
|
||||
}
|
||||
|
||||
public boolean isUnread () {
|
||||
return messageOwner.unread;
|
||||
public boolean isUnread() {
|
||||
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
|
||||
}
|
||||
|
||||
public void setIsRead() {
|
||||
messageOwner.flags &=~ TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
}
|
||||
|
||||
public boolean isSecretPhoto() {
|
||||
return messageOwner instanceof TLRPC.TL_message_secret && messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60;
|
||||
}
|
||||
|
||||
public boolean isSecretMedia() {
|
||||
return messageOwner instanceof TLRPC.TL_message_secret &&
|
||||
(messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60 ||
|
||||
messageOwner.media instanceof TLRPC.TL_messageMediaAudio ||
|
||||
messageOwner.media instanceof TLRPC.TL_messageMediaVideo);
|
||||
}
|
||||
|
||||
public static void setIsUnread(TLRPC.Message message, boolean unread) {
|
||||
if (unread) {
|
||||
message.flags |= TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
} else {
|
||||
message.flags &=~ TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isUnread(TLRPC.Message message) {
|
||||
return (message.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
|
||||
}
|
||||
|
||||
public static boolean isOut(TLRPC.Message message) {
|
||||
return (message.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
|
||||
}
|
||||
|
||||
public long getDialogId() {
|
||||
@ -635,4 +690,21 @@ public class MessageObject {
|
||||
public boolean isSent() {
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SENT;
|
||||
}
|
||||
|
||||
public String getSecretTimeString() {
|
||||
if (!isSecretMedia()) {
|
||||
return null;
|
||||
}
|
||||
int secondsLeft = messageOwner.ttl;
|
||||
if (messageOwner.destroyTime != 0) {
|
||||
secondsLeft = Math.max(0, messageOwner.destroyTime - ConnectionsManager.getInstance().getCurrentTime());
|
||||
}
|
||||
String str;
|
||||
if (secondsLeft < 60) {
|
||||
str = secondsLeft + "s";
|
||||
} else {
|
||||
str = secondsLeft / 60 + "m";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import org.telegram.messenger.BuffersStorage;
|
||||
import org.telegram.messenger.ByteBufferDesc;
|
||||
@ -66,11 +67,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
private long updatesStartWaitTime = 0;
|
||||
public ArrayList<TLRPC.Update> delayedEncryptedChatUpdates = new ArrayList<TLRPC.Update>();
|
||||
private boolean startingSecretChat = false;
|
||||
private ArrayList<Integer> loadingFullUsers = new ArrayList<Integer>();
|
||||
private ArrayList<Integer> loadedFullUsers = new ArrayList<Integer>();
|
||||
|
||||
private boolean gettingNewDeleteTask = false;
|
||||
private int currentDeletingTaskTime = 0;
|
||||
private Long currentDeletingTask = null;
|
||||
private ArrayList<Integer> currentDeletingTaskMids = null;
|
||||
private Runnable currentDeleteTaskRunnable = null;
|
||||
|
||||
public int totalDialogsCount = 0;
|
||||
public boolean loadingDialogs = false;
|
||||
@ -317,12 +320,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
delayedEncryptedChatUpdates.clear();
|
||||
blockedUsers.clear();
|
||||
sendingTypings.clear();
|
||||
loadingFullUsers.clear();
|
||||
loadedFullUsers.clear();
|
||||
|
||||
updatesStartWaitTime = 0;
|
||||
currentDeletingTaskTime = 0;
|
||||
currentDeletingTaskMids = null;
|
||||
gettingNewDeleteTask = false;
|
||||
currentDeletingTask = null;
|
||||
loadingDialogs = false;
|
||||
dialogsEndReached = false;
|
||||
gettingDifference = false;
|
||||
@ -337,6 +341,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
startingSecretChat = false;
|
||||
statusRequest = 0;
|
||||
statusSettingState = 0;
|
||||
|
||||
if (currentDeleteTaskRunnable != null) {
|
||||
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
|
||||
currentDeleteTaskRunnable = null;
|
||||
}
|
||||
|
||||
addSupportUser();
|
||||
}
|
||||
|
||||
@ -383,6 +393,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
users.put(user.id, user);
|
||||
if (user.id == UserConfig.getClientUserId()) {
|
||||
UserConfig.setCurrentUser(user);
|
||||
UserConfig.saveConfig(true);
|
||||
}
|
||||
if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) {
|
||||
return true;
|
||||
@ -453,10 +464,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelLoadFullUser(int uid) {
|
||||
loadingFullUsers.remove((Integer) uid);
|
||||
}
|
||||
|
||||
public void loadFullUser(final TLRPC.User user, final int classGuid) {
|
||||
if (user == null) {
|
||||
if (user == null || loadingFullUsers.contains(user.id) || loadedFullUsers.contains(user.id)) {
|
||||
return;
|
||||
}
|
||||
loadingFullUsers.add(user.id);
|
||||
TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser();
|
||||
req.id = getInputUser(user);
|
||||
long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
|
||||
@ -466,10 +482,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadingFullUsers.remove((Integer)user.id);
|
||||
loadedFullUsers.add(user.id);
|
||||
String names = user.first_name + user.last_name + user.username;
|
||||
TLRPC.TL_userFull userFull = (TLRPC.TL_userFull)response;
|
||||
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
|
||||
users.add(userFull.user);
|
||||
putUsers(users, false);
|
||||
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
|
||||
if (!names.equals(userFull.user.first_name + userFull.user.last_name + userFull.user.username)) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_NAME);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadingFullUsers.remove((Integer)user.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -504,18 +534,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
}
|
||||
|
||||
public void didAddedNewTask(final int minDate) {
|
||||
public void didAddedNewTask(final int minDate, final SparseArray<ArrayList<Integer>> mids) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentDeletingTask == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
|
||||
if (currentDeletingTaskMids == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
|
||||
getNewDeleteTask(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didCreatedNewDeleteTask, mids);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getNewDeleteTask(final Long oldTask) {
|
||||
public void getNewDeleteTask(final ArrayList<Integer> oldTask) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -525,11 +561,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
});
|
||||
}
|
||||
|
||||
private void checkDeletingTask() {
|
||||
private boolean checkDeletingTask(boolean runnable) {
|
||||
int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
|
||||
|
||||
if (currentDeletingTask != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) {
|
||||
if (currentDeletingTaskMids != null && (runnable || currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime)) {
|
||||
currentDeletingTaskTime = 0;
|
||||
if (currentDeleteTaskRunnable != null && !runnable) {
|
||||
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
|
||||
}
|
||||
currentDeleteTaskRunnable = null;
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -538,30 +578,44 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getNewDeleteTask(currentDeletingTask);
|
||||
getNewDeleteTask(currentDeletingTaskMids);
|
||||
currentDeletingTaskTime = 0;
|
||||
currentDeletingTask = null;
|
||||
currentDeletingTaskMids = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void processLoadedDeleteTask(final Long taskId, final int taskTime, final ArrayList<Integer> messages) {
|
||||
public void processLoadedDeleteTask(final int taskTime, final ArrayList<Integer> messages) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
gettingNewDeleteTask = false;
|
||||
if (taskId != null) {
|
||||
if (messages != null) {
|
||||
currentDeletingTaskTime = taskTime;
|
||||
currentDeletingTask = taskId;
|
||||
currentDeletingTaskMids = messages;
|
||||
|
||||
checkDeletingTask();
|
||||
if (currentDeleteTaskRunnable != null) {
|
||||
Utilities.stageQueue.cancelRunnable(currentDeleteTaskRunnable);
|
||||
currentDeleteTaskRunnable = null;
|
||||
}
|
||||
|
||||
if (!checkDeletingTask(false)) {
|
||||
currentDeleteTaskRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
checkDeletingTask(true);
|
||||
}
|
||||
};
|
||||
int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
|
||||
Utilities.stageQueue.postRunnable(currentDeleteTaskRunnable, (long)Math.abs(currentServerTime - currentDeletingTaskTime) * 1000);
|
||||
}
|
||||
} else {
|
||||
currentDeletingTaskTime = 0;
|
||||
currentDeletingTask = null;
|
||||
currentDeletingTaskMids = null;
|
||||
}
|
||||
}
|
||||
@ -926,7 +980,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, messages);
|
||||
|
||||
if (randoms != null && encryptedChat != null && !randoms.isEmpty()) {
|
||||
SendMessagesHelper.getInstance().sendMessagesDeleteMessage(randoms, encryptedChat);
|
||||
SendMessagesHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, randoms, null);
|
||||
}
|
||||
|
||||
ArrayList<Integer> toSend = new ArrayList<Integer>();
|
||||
@ -1017,7 +1071,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
});
|
||||
} else {
|
||||
if (onlyHistory) {
|
||||
SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id));
|
||||
SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id), null);
|
||||
} else {
|
||||
declineSecretChat(high_id);
|
||||
}
|
||||
@ -1066,7 +1120,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
public void updateTimerProc() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
checkDeletingTask();
|
||||
checkDeletingTask(false);
|
||||
|
||||
if (UserConfig.isClientActivated()) {
|
||||
if (ConnectionsManager.getInstance().getPauseTime() == 0 && ApplicationLoader.isScreenOn && !ApplicationLoader.mainInterfacePaused) {
|
||||
@ -1275,10 +1329,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
}
|
||||
|
||||
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward) {
|
||||
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward, final Semaphore semaphore) {
|
||||
int lower_part = (int)dialog_id;
|
||||
if (fromCache || lower_part == 0) {
|
||||
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward);
|
||||
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward, semaphore);
|
||||
} else {
|
||||
TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory();
|
||||
if (lower_part < 0) {
|
||||
@ -1303,7 +1357,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
public void run(TLObject response, TLRPC.TL_error error) {
|
||||
if (error == null) {
|
||||
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
|
||||
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false);
|
||||
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false, semaphore);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1311,7 +1365,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
}
|
||||
|
||||
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward) {
|
||||
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward, final Semaphore semaphore) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -1320,10 +1374,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
MessagesStorage.getInstance().putMessages(messagesRes, dialog_id);
|
||||
}
|
||||
if (lower_id != 0 && isCache && messagesRes.messages.size() == 0 && !isForward) {
|
||||
if (semaphore != null) {
|
||||
semaphore.release();
|
||||
}
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false);
|
||||
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false, null);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@ -1337,14 +1394,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
message.dialog_id = dialog_id;
|
||||
objects.add(new MessageObject(message, usersLocal, 2));
|
||||
}
|
||||
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);
|
||||
}
|
||||
});
|
||||
if (semaphore != null) {
|
||||
putUsers(messagesRes.users, isCache);
|
||||
putChats(messagesRes.chats, isCache);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDidLoaded, dialog_id, count, objects, isCache, first_unread, last_unread, unread_count, last_date, isForward);
|
||||
semaphore.release();
|
||||
} else {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
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);
|
||||
if (encChats != null) {
|
||||
for (TLRPC.EncryptedChat encryptedChat : encChats) {
|
||||
if (encryptedChat instanceof TLRPC.TL_encryptedChat && AndroidUtilities.getMyLayerVersion(encryptedChat.layer) < SendMessagesHelper.CURRENT_SECRET_CHAT_LAYER) {
|
||||
SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null);
|
||||
}
|
||||
putEncryptedChat(encryptedChat, true);
|
||||
}
|
||||
}
|
||||
@ -1643,6 +1710,26 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
});
|
||||
}
|
||||
|
||||
public void markMessageAsRead(final long dialog_id, final long random_id, int ttl) {
|
||||
if (random_id == 0 || dialog_id == 0 || ttl <= 0) {
|
||||
return;
|
||||
}
|
||||
int lower_part = (int)dialog_id;
|
||||
int high_id = (int)(dialog_id >> 32);
|
||||
if (lower_part != 0) {
|
||||
return;
|
||||
}
|
||||
TLRPC.EncryptedChat chat = getEncryptedChat(high_id);
|
||||
if (chat == null) {
|
||||
return;
|
||||
}
|
||||
ArrayList<Long> random_ids = new ArrayList<Long>();
|
||||
random_ids.add(random_id);
|
||||
SendMessagesHelper.getInstance().sendMessagesReadMessage(chat, random_ids, null);
|
||||
int time = ConnectionsManager.getInstance().getCurrentTime();
|
||||
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, time, time, 0, random_ids);
|
||||
}
|
||||
|
||||
public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int offset, final int max_date, final boolean was, final boolean popup) {
|
||||
int lower_part = (int)dialog_id;
|
||||
int high_id = (int)(dialog_id >> 32);
|
||||
@ -1756,18 +1843,17 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
|
||||
if (chat.ttl > 0 && was) {
|
||||
int serverTime = Math.max(ConnectionsManager.getInstance().getCurrentTime(), max_date);
|
||||
MessagesStorage.getInstance().createTaskForDate(chat.id, serverTime, serverTime, 0);
|
||||
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, serverTime, serverTime, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processPendingEncMessages() {
|
||||
if (pendingEncMessagesToDelete.isEmpty()) {
|
||||
return;
|
||||
if (!pendingEncMessagesToDelete.isEmpty()) {
|
||||
ArrayList<Long> arr = new ArrayList<Long>(pendingEncMessagesToDelete);
|
||||
MessagesStorage.getInstance().markMessagesAsDeletedByRandoms(arr);
|
||||
pendingEncMessagesToDelete.clear();
|
||||
}
|
||||
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) {
|
||||
@ -1803,11 +1889,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMsg.action = new TLRPC.TL_messageActionCreatedBroadcastList();
|
||||
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
|
||||
newMsg.from_id = UserConfig.getClientUserId();
|
||||
newMsg.unread = false;
|
||||
newMsg.dialog_id = AndroidUtilities.makeBroadcastId(chat.id);
|
||||
newMsg.to_id = new TLRPC.TL_peerChat();
|
||||
newMsg.to_id.chat_id = chat.id;
|
||||
newMsg.out = false;
|
||||
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
|
||||
newMsg.random_id = 0;
|
||||
UserConfig.saveConfig(false);
|
||||
@ -2570,7 +2654,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
message.message = updates.message;
|
||||
message.date = updates.date;
|
||||
message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
message.unread = true;
|
||||
message.media = new TLRPC.TL_messageMediaEmpty();
|
||||
MessagesStorage.lastSeqValue = updates.seq;
|
||||
MessagesStorage.lastPtsValue = updates.pts;
|
||||
@ -2635,7 +2718,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
message.to_id.user_id = updates.from_id;
|
||||
message.message = updates.message;
|
||||
message.date = updates.date;
|
||||
message.unread = true;
|
||||
message.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
message.media = new TLRPC.TL_messageMediaEmpty();
|
||||
MessagesStorage.lastSeqValue = updates.seq;
|
||||
@ -2914,13 +2996,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.action = new TLRPC.TL_messageActionUserJoined();
|
||||
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
|
||||
UserConfig.saveConfig(false);
|
||||
newMessage.unread = true;
|
||||
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
newMessage.date = update.date;
|
||||
newMessage.from_id = update.user_id;
|
||||
newMessage.to_id = new TLRPC.TL_peerUser();
|
||||
newMessage.to_id.user_id = UserConfig.getClientUserId();
|
||||
newMessage.out = false;
|
||||
newMessage.dialog_id = update.user_id;
|
||||
|
||||
messagesArr.add(newMessage);
|
||||
@ -2960,13 +3040,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.action.address = update.location;
|
||||
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
|
||||
UserConfig.saveConfig(false);
|
||||
newMessage.unread = true;
|
||||
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
newMessage.date = update.date;
|
||||
newMessage.from_id = 777000;
|
||||
newMessage.to_id = new TLRPC.TL_peerUser();
|
||||
newMessage.to_id.user_id = UserConfig.getClientUserId();
|
||||
newMessage.out = false;
|
||||
newMessage.dialog_id = 777000;
|
||||
|
||||
messagesArr.add(newMessage);
|
||||
@ -3099,6 +3177,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newChat.user_id = exist.user_id;
|
||||
newChat.auth_key = exist.auth_key;
|
||||
newChat.ttl = exist.ttl;
|
||||
newChat.seq_in = exist.seq_in;
|
||||
newChat.seq_out = exist.seq_out;
|
||||
putEncryptedChat(newChat, false);
|
||||
}
|
||||
MessagesStorage.getInstance().updateEncryptedChat(newChat);
|
||||
@ -3135,6 +3215,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
});
|
||||
} else if (update instanceof TLRPC.TL_updateNotifySettings) {
|
||||
updatesOnMainThread.add(update);
|
||||
} else if (update instanceof TLRPC.TL_updateServiceNotification) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
if (!messages.isEmpty()) {
|
||||
@ -3203,9 +3285,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
if (currentUser != null) {
|
||||
currentUser.first_name = update.first_name;
|
||||
currentUser.last_name = update.last_name;
|
||||
currentUser.username = update.username;
|
||||
}
|
||||
toDbUser.first_name = update.first_name;
|
||||
toDbUser.last_name = update.last_name;
|
||||
toDbUser.username = update.username;
|
||||
dbUsers.add(toDbUser);
|
||||
} else if (update instanceof TLRPC.TL_updateUserPhoto) {
|
||||
if (currentUser != null) {
|
||||
@ -3295,7 +3379,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
for (Integer id : markAsReadMessages) {
|
||||
MessageObject obj = dialogMessage.get(id);
|
||||
if (obj != null) {
|
||||
obj.messageOwner.unread = false;
|
||||
obj.setIsRead();
|
||||
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
|
||||
}
|
||||
}
|
||||
@ -3308,7 +3392,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
if (dialog != null) {
|
||||
MessageObject message = dialogMessage.get(dialog.top_message);
|
||||
if (message != null && message.messageOwner.date <= entry.getValue()) {
|
||||
message.messageOwner.unread = false;
|
||||
message.setIsRead();
|
||||
updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE;
|
||||
}
|
||||
}
|
||||
@ -3345,7 +3429,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
if (!tasks.isEmpty()) {
|
||||
for (TLRPC.TL_updateEncryptedMessagesRead update : tasks) {
|
||||
MessagesStorage.getInstance().createTaskForDate(update.chat_id, update.max_date, update.date, 1);
|
||||
MessagesStorage.getInstance().createTaskForSecretChat(update.chat_id, update.max_date, update.date, 1, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3473,8 +3557,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
|
||||
public TLRPC.Message decryptMessage(TLRPC.EncryptedMessage message) {
|
||||
TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id);
|
||||
if (chat == null) {
|
||||
final TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id);
|
||||
if (chat == null || chat instanceof TLRPC.TL_encryptedChatDiscarded) {
|
||||
return null;
|
||||
}
|
||||
ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length);
|
||||
@ -3496,9 +3580,53 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
from_id = chat.participant_id;
|
||||
}
|
||||
|
||||
if (object instanceof TLRPC.TL_decryptedMessageLayer) {
|
||||
final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer)object;
|
||||
if (chat.seq_in == 0 && chat.seq_out == 0) {
|
||||
if (chat.admin_id == UserConfig.getClientUserId()) {
|
||||
chat.seq_out = 1;
|
||||
} else {
|
||||
chat.seq_in = 1;
|
||||
}
|
||||
}
|
||||
if (chat.seq_in != layer.out_seq_no && chat.seq_in != layer.out_seq_no - 2) {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded();
|
||||
newChat.id = chat.id;
|
||||
newChat.user_id = chat.user_id;
|
||||
newChat.auth_key = chat.auth_key;
|
||||
newChat.seq_in = chat.seq_in;
|
||||
newChat.seq_out = chat.seq_out;
|
||||
MessagesStorage.getInstance().updateEncryptedChat(newChat);
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
putEncryptedChat(newChat, false);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
|
||||
}
|
||||
});
|
||||
declineSecretChat(chat.id);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
chat.seq_in = layer.out_seq_no;
|
||||
MessagesStorage.getInstance().updateEncryptedChatSeq(chat);
|
||||
object = layer.message;
|
||||
}
|
||||
|
||||
if (object instanceof TLRPC.TL_decryptedMessage) {
|
||||
TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object;
|
||||
TLRPC.TL_message newMessage = new TLRPC.TL_message();
|
||||
TLRPC.TL_message newMessage = null;
|
||||
if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) {
|
||||
newMessage = new TLRPC.TL_message_secret();
|
||||
newMessage.ttl = decryptedMessage.ttl;
|
||||
} else {
|
||||
newMessage = new TLRPC.TL_message();
|
||||
newMessage.ttl = chat.ttl;
|
||||
}
|
||||
newMessage.message = decryptedMessage.message;
|
||||
newMessage.date = message.date;
|
||||
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
|
||||
@ -3508,10 +3636,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.random_id = message.random_id;
|
||||
newMessage.to_id.user_id = UserConfig.getClientUserId();
|
||||
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
newMessage.out = false;
|
||||
newMessage.unread = true;
|
||||
newMessage.dialog_id = ((long)chat.id) << 32;
|
||||
newMessage.ttl = chat.ttl;
|
||||
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) {
|
||||
newMessage.media = new TLRPC.TL_messageMediaEmpty();
|
||||
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) {
|
||||
@ -3535,7 +3660,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.media.photo.date = newMessage.date;
|
||||
newMessage.media.photo.caption = "";
|
||||
newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty();
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
|
||||
TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize();
|
||||
small.w = decryptedMessage.media.thumb_w;
|
||||
small.h = decryptedMessage.media.thumb_h;
|
||||
@ -3564,7 +3689,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
newMessage.media = new TLRPC.TL_messageMediaVideo();
|
||||
newMessage.media.video = new TLRPC.TL_videoEncrypted();
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
|
||||
newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize();
|
||||
newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb;
|
||||
newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w;
|
||||
@ -3588,6 +3713,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.media.video.key = decryptedMessage.media.key;
|
||||
newMessage.media.video.iv = decryptedMessage.media.iv;
|
||||
newMessage.media.video.mime_type = decryptedMessage.media.mime_type;
|
||||
if (newMessage.ttl != 0) {
|
||||
newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl);
|
||||
}
|
||||
if (newMessage.media.video.mime_type == null) {
|
||||
newMessage.media.video.mime_type = "video/mp4";
|
||||
}
|
||||
@ -3606,7 +3734,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.media.document.size = message.file.size;
|
||||
newMessage.media.document.key = decryptedMessage.media.key;
|
||||
newMessage.media.document.iv = decryptedMessage.media.iv;
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) {
|
||||
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
|
||||
newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize();
|
||||
newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb;
|
||||
newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w;
|
||||
@ -3634,6 +3762,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newMessage.media.audio.dc_id = message.file.dc_id;
|
||||
newMessage.media.audio.duration = decryptedMessage.media.duration;
|
||||
newMessage.media.audio.mime_type = decryptedMessage.media.mime_type;
|
||||
if (newMessage.ttl != 0) {
|
||||
newMessage.ttl = Math.max(newMessage.media.audio.duration + 1, newMessage.ttl);
|
||||
}
|
||||
if (newMessage.media.audio.mime_type == null) {
|
||||
newMessage.media.audio.mime_type = "audio/ogg";
|
||||
}
|
||||
@ -3642,29 +3773,29 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
return newMessage;
|
||||
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
|
||||
TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object;
|
||||
final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object;
|
||||
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
|
||||
TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService();
|
||||
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
|
||||
newMessage.action = new TLRPC.TL_messageActionTTLChange();
|
||||
newMessage.action.ttl = chat.ttl = serviceMessage.action.ttl_seconds;
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
|
||||
newMessage.action = new TLRPC.TL_messageEcryptedAction();
|
||||
newMessage.action = new TLRPC.TL_messageEncryptedAction();
|
||||
if (serviceMessage.action.ttl_seconds < 0 || serviceMessage.action.ttl_seconds > 60 * 60 * 24 * 365) {
|
||||
serviceMessage.action.ttl_seconds = 60 * 60 * 24 * 365;
|
||||
}
|
||||
chat.ttl = serviceMessage.action.ttl_seconds;
|
||||
newMessage.action.encryptedAction = serviceMessage.action;
|
||||
MessagesStorage.getInstance().updateEncryptedChatTTL(chat);
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) {
|
||||
newMessage.action = new TLRPC.TL_messageEncryptedAction();
|
||||
newMessage.action.encryptedAction = serviceMessage.action;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
|
||||
UserConfig.saveConfig(false);
|
||||
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD;
|
||||
newMessage.unread = true;
|
||||
newMessage.date = message.date;
|
||||
newMessage.from_id = from_id;
|
||||
newMessage.to_id = new TLRPC.TL_peerUser();
|
||||
newMessage.to_id.user_id = UserConfig.getClientUserId();
|
||||
newMessage.out = false;
|
||||
newMessage.dialog_id = ((long)chat.id) << 32;
|
||||
MessagesStorage.getInstance().updateEncryptedChatTTL(chat);
|
||||
return newMessage;
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) {
|
||||
final long did = ((long)chat.id) << 32;
|
||||
@ -3701,6 +3832,25 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids);
|
||||
}
|
||||
return null;
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionReadMessages) {
|
||||
if (!serviceMessage.action.random_ids.isEmpty()) {
|
||||
MessagesStorage.getInstance().createTaskForSecretChat(chat.id, ConnectionsManager.getInstance().getCurrentTime(), ConnectionsManager.getInstance().getCurrentTime(), 1, serviceMessage.action.random_ids);
|
||||
}
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int currentPeerLayer = AndroidUtilities.getPeerLayerVersion(chat.layer);
|
||||
chat.layer = 0;
|
||||
chat.layer = AndroidUtilities.setPeerLayerVersion(chat.layer, serviceMessage.action.layer);
|
||||
MessagesStorage.getInstance().updateEncryptedChatLayer(chat);
|
||||
if (currentPeerLayer < 17) {
|
||||
SendMessagesHelper.getInstance().sendNotifyLayerMessage(chat, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionResend) {
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -3747,12 +3897,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
long fingerprint = Utilities.bytesToLong(authKeyId);
|
||||
if (encryptedChat.key_fingerprint == fingerprint) {
|
||||
encryptedChat.auth_key = authKey;
|
||||
encryptedChat.seq_in = 0;
|
||||
encryptedChat.seq_out = 1;
|
||||
MessagesStorage.getInstance().updateEncryptedChat(encryptedChat);
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
putEncryptedChat(encryptedChat, false);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat);
|
||||
SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@ -3760,6 +3913,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
newChat.id = encryptedChat.id;
|
||||
newChat.user_id = encryptedChat.user_id;
|
||||
newChat.auth_key = encryptedChat.auth_key;
|
||||
newChat.seq_in = encryptedChat.seq_in;
|
||||
newChat.seq_out = encryptedChat.seq_out;
|
||||
MessagesStorage.getInstance().updateEncryptedChat(newChat);
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
@ -3813,6 +3968,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]);
|
||||
}
|
||||
encryptedChat.a_or_b = salt;
|
||||
encryptedChat.seq_in = 1;
|
||||
encryptedChat.seq_out = 0;
|
||||
BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes);
|
||||
BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG);
|
||||
g_b = g_b.modPow(new BigInteger(1, salt), p);
|
||||
@ -3865,12 +4022,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat) response;
|
||||
newChat.auth_key = encryptedChat.auth_key;
|
||||
newChat.user_id = encryptedChat.user_id;
|
||||
newChat.seq_in = encryptedChat.seq_in;
|
||||
newChat.seq_out = encryptedChat.seq_out;
|
||||
MessagesStorage.getInstance().updateEncryptedChat(newChat);
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
putEncryptedChat(newChat, false);
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat);
|
||||
SendMessagesHelper.getInstance().sendNotifyLayerMessage(newChat, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -3956,8 +4116,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) response;
|
||||
chat.user_id = chat.participant_id;
|
||||
putEncryptedChat(chat, false);
|
||||
chat.seq_in = 0;
|
||||
chat.seq_out = 1;
|
||||
chat.a_or_b = salt;
|
||||
putEncryptedChat(chat, false);
|
||||
TLRPC.TL_dialog dialog = new TLRPC.TL_dialog();
|
||||
dialog.id = ((long) chat.id) << 32;
|
||||
dialog.unread_count = 0;
|
||||
@ -4012,7 +4174,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
builder.setMessage(LocaleController.formatString("CreateEncryptedChatOutdatedError", R.string.CreateEncryptedChatOutdatedError, user.first_name, user.first_name));
|
||||
builder.setMessage(LocaleController.getString("CreateEncryptedChatError", R.string.CreateEncryptedChatError));
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
builder.show().setCanceledOnTouchOutside(true);
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ import java.util.zip.ZipFile;
|
||||
public class NativeLoader {
|
||||
|
||||
private static final long sizes[] = new long[] {
|
||||
946908, //armeabi
|
||||
1028848, //armeabi-v7a
|
||||
1603780, //x86
|
||||
955148, //armeabi
|
||||
1041184, //armeabi-v7a
|
||||
1616116, //x86
|
||||
0, //mips
|
||||
};
|
||||
|
||||
|
@ -41,6 +41,7 @@ public class NotificationCenter {
|
||||
public static final int openedChatChanged = 29;
|
||||
public static final int hideEmojiKeyboard = 30;
|
||||
public static final int stopEncodingService = 31;
|
||||
public static final int didCreatedNewDeleteTask = 32;
|
||||
|
||||
public static final int wallpapersDidLoaded = 171;
|
||||
public static final int closeOtherAppActivities = 702;
|
||||
@ -67,6 +68,7 @@ public class NotificationCenter {
|
||||
public final static int screenshotTook = 50007;
|
||||
public final static int albumsDidLoaded = 50008;
|
||||
public final static int audioDidSent = 50009;
|
||||
public final static int audioDidStarted = 50010;
|
||||
|
||||
final private HashMap<Integer, ArrayList<Object>> observers = new HashMap<Integer, ArrayList<Object>>();
|
||||
|
||||
|
@ -21,7 +21,7 @@ public class PhotoObject {
|
||||
public TLRPC.PhotoSize photoOwner;
|
||||
public Bitmap image;
|
||||
|
||||
public PhotoObject(TLRPC.PhotoSize photo, int preview) {
|
||||
public PhotoObject(TLRPC.PhotoSize photo, int preview, boolean secret) {
|
||||
photoOwner = photo;
|
||||
|
||||
if (preview != 0 && photo instanceof TLRPC.TL_photoCachedSize) {
|
||||
@ -34,7 +34,13 @@ public class PhotoObject {
|
||||
image = BitmapFactory.decodeByteArray(photoOwner.bytes, 0, photoOwner.bytes.length, opts);
|
||||
if (image != null) {
|
||||
if (preview == 2) {
|
||||
Utilities.blurBitmap(image);
|
||||
if (secret) {
|
||||
Utilities.blurBitmap(image, 7);
|
||||
Utilities.blurBitmap(image, 7);
|
||||
Utilities.blurBitmap(image, 7);
|
||||
} else {
|
||||
Utilities.blurBitmap(image, 3);
|
||||
}
|
||||
}
|
||||
if (ImageLoader.getInstance().runtimeHack != null) {
|
||||
ImageLoader.getInstance().runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
|
||||
|
@ -45,7 +45,7 @@ public class VideoEncodingService extends Service implements NotificationCenter.
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileUploadProgressChanged) {
|
||||
String fileName = (String)args[0];
|
||||
if (path.equals(fileName)) {
|
||||
if (path != null && path.equals(fileName)) {
|
||||
Float progress = (Float) args[1];
|
||||
Boolean enc = (Boolean) args[2];
|
||||
currentProgress = (int)(progress * 100);
|
||||
|
@ -54,12 +54,13 @@ public class MP4Builder {
|
||||
|
||||
private InterleaveChunkMdat mdat = null;
|
||||
private Mp4Movie currentMp4Movie = null;
|
||||
FileOutputStream fos = null;
|
||||
private FileOutputStream fos = null;
|
||||
private FileChannel fc = null;
|
||||
private long dataOffset = 0;
|
||||
private long writedSinceLastMdat = 0;
|
||||
private boolean writeNewMdat = true;
|
||||
HashMap<Track, long[]> track2SampleSizes = new HashMap<Track, long[]>();
|
||||
private HashMap<Track, long[]> track2SampleSizes = new HashMap<Track, long[]>();
|
||||
private ByteBuffer sizeBuffer = null;
|
||||
|
||||
public MP4Builder createMovie(Mp4Movie mp4Movie) throws Exception {
|
||||
currentMp4Movie = mp4Movie;
|
||||
@ -74,6 +75,8 @@ public class MP4Builder {
|
||||
|
||||
mdat = new InterleaveChunkMdat();
|
||||
|
||||
sizeBuffer = ByteBuffer.allocateDirect(4);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -87,7 +90,7 @@ public class MP4Builder {
|
||||
fos.flush();
|
||||
}
|
||||
|
||||
public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) throws Exception {
|
||||
public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo, boolean isAudio) throws Exception {
|
||||
if (writeNewMdat) {
|
||||
mdat.setContentSize(0);
|
||||
mdat.getBox(fc);
|
||||
@ -109,9 +112,16 @@ public class MP4Builder {
|
||||
}
|
||||
|
||||
currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo);
|
||||
byteBuf.position(bufferInfo.offset);
|
||||
byteBuf.position(bufferInfo.offset + (isAudio ? 0 : 4));
|
||||
byteBuf.limit(bufferInfo.offset + bufferInfo.size);
|
||||
|
||||
if (!isAudio) {
|
||||
sizeBuffer.position(0);
|
||||
sizeBuffer.putInt(bufferInfo.size - 4);
|
||||
sizeBuffer.position(0);
|
||||
fc.write(sizeBuffer);
|
||||
}
|
||||
|
||||
fc.write(byteBuf);
|
||||
dataOffset += bufferInfo.size;
|
||||
|
||||
|
@ -833,7 +833,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
}
|
||||
object = invoke;
|
||||
}
|
||||
TLRPC.invokeWithLayer17 invoke = new TLRPC.invokeWithLayer17();
|
||||
TLRPC.invokeWithLayer18 invoke = new TLRPC.invokeWithLayer18();
|
||||
invoke.query = object;
|
||||
FileLog.d("wrap in layer", "" + object);
|
||||
return invoke;
|
||||
@ -997,6 +997,10 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
return (int)(System.currentTimeMillis() / 1000) + timeDifference;
|
||||
}
|
||||
|
||||
public int getTimeDifference() {
|
||||
return timeDifference;
|
||||
}
|
||||
|
||||
private void processRequestQueue(int requestClass, int _datacenterId) {
|
||||
boolean haveNetwork = true;//isNetworkOnline();
|
||||
|
||||
@ -1382,7 +1386,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
if (rawRequest != null && (rawRequest instanceof TLRPC.TL_messages_sendMessage ||
|
||||
rawRequest instanceof TLRPC.TL_messages_sendMedia ||
|
||||
rawRequest instanceof TLRPC.TL_messages_forwardMessages ||
|
||||
rawRequest instanceof TLRPC.TL_messages_sendEncrypted)) {
|
||||
rawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
|
||||
rawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
|
||||
rawRequest instanceof TLRPC.TL_messages_sendEncryptedService)) {
|
||||
|
||||
if (rawRequest instanceof TLRPC.TL_messages_sendMessage) {
|
||||
hasSendMessage = true;
|
||||
@ -1400,7 +1406,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
if (currentRawRequest instanceof TLRPC.TL_messages_sendMessage ||
|
||||
currentRawRequest instanceof TLRPC.TL_messages_sendMedia ||
|
||||
currentRawRequest instanceof TLRPC.TL_messages_forwardMessages ||
|
||||
currentRawRequest instanceof TLRPC.TL_messages_sendEncrypted) {
|
||||
currentRawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
|
||||
currentRawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
|
||||
currentRawRequest instanceof TLRPC.TL_messages_sendEncryptedService) {
|
||||
currentRequests.add(currentMessage.msg_id);
|
||||
}
|
||||
}
|
||||
@ -1410,7 +1418,9 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
if (request.rawRequest instanceof TLRPC.TL_messages_sendMessage ||
|
||||
request.rawRequest instanceof TLRPC.TL_messages_sendMedia ||
|
||||
request.rawRequest instanceof TLRPC.TL_messages_forwardMessages ||
|
||||
request.rawRequest instanceof TLRPC.TL_messages_sendEncrypted) {
|
||||
request.rawRequest instanceof TLRPC.TL_messages_sendEncrypted ||
|
||||
request.rawRequest instanceof TLRPC.TL_messages_sendEncryptedFile ||
|
||||
request.rawRequest instanceof TLRPC.TL_messages_sendEncryptedService) {
|
||||
if (!currentRequests.contains(request.runningMessageId)) {
|
||||
maxRequestId = Math.max(maxRequestId, request.runningMessageId);
|
||||
}
|
||||
@ -1604,12 +1614,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
TLRPC.TL_protoMessage message = networkMessage.protoMessage;
|
||||
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
if (message.body instanceof TLRPC.invokeWithLayer17) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)message.body).query);
|
||||
if (message.body instanceof TLRPC.invokeWithLayer18) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)message.body).query);
|
||||
} else if (message.body instanceof TLRPC.initConnection) {
|
||||
TLRPC.initConnection r = (TLRPC.initConnection)message.body;
|
||||
if (r.query instanceof TLRPC.invokeWithLayer17) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)r.query).query);
|
||||
if (r.query instanceof TLRPC.invokeWithLayer18) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)r.query).query);
|
||||
} else {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + r.query);
|
||||
}
|
||||
@ -1644,12 +1654,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
TLRPC.TL_protoMessage message = networkMessage.protoMessage;
|
||||
containerMessages.add(message);
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
if (message.body instanceof TLRPC.invokeWithLayer17) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)message.body).query);
|
||||
if (message.body instanceof TLRPC.invokeWithLayer18) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)message.body).query);
|
||||
} else if (message.body instanceof TLRPC.initConnection) {
|
||||
TLRPC.initConnection r = (TLRPC.initConnection)message.body;
|
||||
if (r.query instanceof TLRPC.invokeWithLayer17) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer17)r.query).query);
|
||||
if (r.query instanceof TLRPC.invokeWithLayer18) {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + ((TLRPC.invokeWithLayer18)r.query).query);
|
||||
} else {
|
||||
FileLog.d("tmessages", connection.getSissionId() + ":DC" + datacenter.datacenterId + "> Send message (" + message.seqno + ", " + message.msg_id + "): " + r.query);
|
||||
}
|
||||
@ -2066,12 +2076,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
int errorCode = ((TLRPC.RpcError) resultContainer.result).error_code;
|
||||
|
||||
if (errorCode == 500 || errorCode < 0) {
|
||||
if ((request.flags & RPCRequest.RPCRequestClassFailOnServerErrors) != 0) {
|
||||
if (request.serverFailureCount < 1) {
|
||||
discardResponse = true;
|
||||
request.runningMinStartTime = request.runningStartTime + 1;
|
||||
}
|
||||
} else {
|
||||
if ((request.flags & RPCRequest.RPCRequestClassFailOnServerErrors) == 0) {
|
||||
discardResponse = true;
|
||||
int delay = Math.min(1, request.serverFailureCount * 2);
|
||||
request.runningMinStartTime = request.runningStartTime + delay;
|
||||
@ -2433,6 +2438,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
|
||||
}
|
||||
});
|
||||
} else if ((connection.transportRequestClass & RPCRequest.RPCRequestClassPush) != 0) {
|
||||
FileLog.e("tmessages", "call connection closed");
|
||||
sendingPushPing = false;
|
||||
lastPushPingTime = System.currentTimeMillis() - 60000 * 3 + 4000;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class DispatchQueue extends Thread {
|
||||
postRunnable(runnable, 0);
|
||||
}
|
||||
|
||||
public void postRunnable(Runnable runnable, int delay) {
|
||||
public void postRunnable(Runnable runnable, long delay) {
|
||||
if (handler == null) {
|
||||
synchronized (handlerSyncObject) {
|
||||
if (handler == null) {
|
||||
|
@ -176,7 +176,7 @@ public class FileLoader {
|
||||
}
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 2) {
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
@ -185,7 +185,7 @@ public class FileLoader {
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 2) {
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
@ -227,7 +227,7 @@ public class FileLoader {
|
||||
});
|
||||
if (small) {
|
||||
currentUploadSmallOperationsCount--;
|
||||
if (currentUploadSmallOperationsCount < 2) {
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadSmallOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
@ -236,7 +236,7 @@ public class FileLoader {
|
||||
}
|
||||
} else {
|
||||
currentUploadOperationsCount--;
|
||||
if (currentUploadOperationsCount < 2) {
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
FileUploadOperation operation = uploadOperationQueue.poll();
|
||||
if (operation != null) {
|
||||
currentUploadOperationsCount++;
|
||||
@ -259,14 +259,14 @@ public class FileLoader {
|
||||
}
|
||||
};
|
||||
if (small) {
|
||||
if (currentUploadSmallOperationsCount < 2) {
|
||||
if (currentUploadSmallOperationsCount < 1) {
|
||||
currentUploadSmallOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
uploadSmallOperationQueue.add(operation);
|
||||
}
|
||||
} else {
|
||||
if (currentUploadOperationsCount < 2) {
|
||||
if (currentUploadOperationsCount < 1) {
|
||||
currentUploadOperationsCount++;
|
||||
operation.start();
|
||||
} else {
|
||||
@ -564,18 +564,30 @@ public class FileLoader {
|
||||
if (message == null) {
|
||||
return new File("");
|
||||
}
|
||||
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);
|
||||
if (message instanceof TLRPC.TL_messageService) {
|
||||
if (message.action.photo != null) {
|
||||
ArrayList<TLRPC.PhotoSize> sizes = message.action.photo.sizes;
|
||||
if (sizes.size() > 0) {
|
||||
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
|
||||
if (sizeFull != null) {
|
||||
return getPathToAttach(sizeFull);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaVideo) {
|
||||
return getPathToAttach(message.media.video);
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
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 "";
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ public class TLClassStore {
|
||||
classStore.put(TLRPC.TL_updateReadMessages.constructor, TLRPC.TL_updateReadMessages.class);
|
||||
classStore.put(TLRPC.TL_updateChatParticipantDelete.constructor, TLRPC.TL_updateChatParticipantDelete.class);
|
||||
classStore.put(TLRPC.TL_updateRestoreMessages.constructor, TLRPC.TL_updateRestoreMessages.class);
|
||||
classStore.put(TLRPC.TL_updateServiceNotification.constructor, TLRPC.TL_updateServiceNotification.class);
|
||||
classStore.put(TLRPC.TL_updateNotifySettings.constructor, TLRPC.TL_updateNotifySettings.class);
|
||||
classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class);
|
||||
classStore.put(TLRPC.TL_updateChatUserTyping.constructor, TLRPC.TL_updateChatUserTyping.class);
|
||||
@ -226,6 +227,7 @@ public class TLClassStore {
|
||||
classStore.put(TLRPC.TL_inputEncryptedFileEmpty.constructor, TLRPC.TL_inputEncryptedFileEmpty.class);
|
||||
classStore.put(TLRPC.TL_inputEncryptedFileUploaded.constructor, TLRPC.TL_inputEncryptedFileUploaded.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageActionFlushHistory.constructor, TLRPC.TL_decryptedMessageActionFlushHistory.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageActionResend.constructor, TLRPC.TL_decryptedMessageActionResend.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageActionNotifyLayer.constructor, TLRPC.TL_decryptedMessageActionNotifyLayer.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageActionSetMessageTTL.constructor, TLRPC.TL_decryptedMessageActionSetMessageTTL.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageActionDeleteMessages.constructor, TLRPC.TL_decryptedMessageActionDeleteMessages.class);
|
||||
@ -362,6 +364,13 @@ public class TLClassStore {
|
||||
classStore.put(TLRPC.TL_messageService_old.constructor, TLRPC.TL_messageService_old.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessageService_old.constructor, TLRPC.TL_decryptedMessageService_old.class);
|
||||
classStore.put(TLRPC.TL_decryptedMessage_old.constructor, TLRPC.TL_decryptedMessage_old.class);
|
||||
classStore.put(TLRPC.TL_message_secret.constructor, TLRPC.TL_message_secret.class);
|
||||
classStore.put(TLRPC.TL_userSelf_old.constructor, TLRPC.TL_userSelf_old.class);
|
||||
classStore.put(TLRPC.TL_userContact_old.constructor, TLRPC.TL_userContact_old.class);
|
||||
classStore.put(TLRPC.TL_userRequest_old.constructor, TLRPC.TL_userRequest_old.class);
|
||||
classStore.put(TLRPC.TL_userForeign_old.constructor, TLRPC.TL_userForeign_old.class);
|
||||
classStore.put(TLRPC.TL_userDeleted_old.constructor, TLRPC.TL_userDeleted_old.class);
|
||||
classStore.put(TLRPC.TL_messageEncryptedAction.constructor, TLRPC.TL_messageEncryptedAction.class);
|
||||
}
|
||||
|
||||
static TLClassStore store = null;
|
||||
|
@ -2084,13 +2084,14 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_userContact extends User {
|
||||
public static int constructor = 0xf2fb8319;
|
||||
public static int constructor = 0xcab35e18;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -2102,6 +2103,7 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
stream.writeInt64(access_hash);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
@ -2110,13 +2112,14 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_userRequest extends User {
|
||||
public static int constructor = 0x22e8ceb0;
|
||||
public static int constructor = 0xd9ccc4ef;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -2128,6 +2131,7 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
stream.writeInt64(access_hash);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
@ -2136,13 +2140,14 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_userForeign extends User {
|
||||
public static int constructor = 0x5214c89d;
|
||||
public static int constructor = 0x75cf7a8;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -2153,6 +2158,7 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
stream.writeInt64(access_hash);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
@ -2160,13 +2166,14 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_userDeleted extends User {
|
||||
public static int constructor = 0xb29ad7cc;
|
||||
public static int constructor = 0xd6016d7a;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
@ -2174,17 +2181,19 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_userSelf extends User {
|
||||
public static int constructor = 0x720535ec;
|
||||
public static int constructor = 0x7007b451;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -2196,6 +2205,7 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
@ -2557,8 +2567,6 @@ public class TLRPC {
|
||||
public static class DecryptedMessage extends TLObject {
|
||||
public long random_id;
|
||||
public byte[] random_bytes;
|
||||
public int in_seq_no;
|
||||
public int out_seq_no;
|
||||
public DecryptedMessageAction action;
|
||||
public int ttl;
|
||||
public String message;
|
||||
@ -2566,36 +2574,27 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessageService extends DecryptedMessage {
|
||||
public static int constructor = 0xda431693;
|
||||
public static int constructor = 0x73164160;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
random_id = stream.readInt64();
|
||||
random_bytes = stream.readByteArray();
|
||||
in_seq_no = stream.readInt32();
|
||||
out_seq_no = stream.readInt32();
|
||||
action = (DecryptedMessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt64(random_id);
|
||||
stream.writeByteArray(random_bytes);
|
||||
stream.writeInt32(in_seq_no);
|
||||
stream.writeInt32(out_seq_no);
|
||||
action.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessage extends DecryptedMessage {
|
||||
public static int constructor = 0x4e748938;
|
||||
public static int constructor = 0x204d3878;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
random_id = stream.readInt64();
|
||||
random_bytes = stream.readByteArray();
|
||||
in_seq_no = stream.readInt32();
|
||||
out_seq_no = stream.readInt32();
|
||||
ttl = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (DecryptedMessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -2604,9 +2603,6 @@ public class TLRPC {
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt64(random_id);
|
||||
stream.writeByteArray(random_bytes);
|
||||
stream.writeInt32(in_seq_no);
|
||||
stream.writeInt32(out_seq_no);
|
||||
stream.writeInt32(ttl);
|
||||
stream.writeString(message);
|
||||
media.serializeToStream(stream);
|
||||
@ -3439,11 +3435,15 @@ public class TLRPC {
|
||||
public ArrayList<Integer> messages = new ArrayList<Integer>();
|
||||
public int pts;
|
||||
public int version;
|
||||
public String type;
|
||||
public MessageMedia media;
|
||||
public boolean popup;
|
||||
public NotifyPeer peer;
|
||||
public PeerNotifySettings notify_settings;
|
||||
public SendMessageAction action;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public String username;
|
||||
public int qts;
|
||||
public int id;
|
||||
public long random_id;
|
||||
@ -3564,6 +3564,27 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_updateServiceNotification extends Update {
|
||||
public static int constructor = 0x382dd3e4;
|
||||
|
||||
public String message;
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
type = stream.readString();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
popup = stream.readBool();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeString(type);
|
||||
stream.writeString(message);
|
||||
media.serializeToStream(stream);
|
||||
stream.writeBool(popup);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_updateNotifySettings extends Update {
|
||||
public static int constructor = 0xbec268ef;
|
||||
|
||||
@ -3615,13 +3636,14 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_updateUserName extends Update {
|
||||
public static int constructor = 0xda22d9ad;
|
||||
public static int constructor = 0xa7332b73;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
user_id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
username = stream.readString();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
@ -3629,6 +3651,7 @@ public class TLRPC {
|
||||
stream.writeInt32(user_id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4051,6 +4074,8 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class DecryptedMessageAction extends TLObject {
|
||||
public int start_seq_no;
|
||||
public int end_seq_no;
|
||||
public int layer;
|
||||
public int ttl_seconds;
|
||||
public ArrayList<Long> random_ids = new ArrayList<Long>();
|
||||
@ -4078,6 +4103,22 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessageActionResend extends DecryptedMessageAction {
|
||||
public static int constructor = 0x511110b0;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
start_seq_no = stream.readInt32();
|
||||
end_seq_no = stream.readInt32();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(start_seq_no);
|
||||
stream.writeInt32(end_seq_no);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessageActionNotifyLayer extends DecryptedMessageAction {
|
||||
public static int constructor = 0xf3048883;
|
||||
|
||||
@ -4586,6 +4627,44 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_account_checkUsername extends TLObject {
|
||||
public static int constructor = 0x2714d86c;
|
||||
|
||||
public String username;
|
||||
|
||||
public Class responseClass () {
|
||||
return Bool.class;
|
||||
}
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
username = stream.readString();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeString(username);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_account_updateUsername extends TLObject {
|
||||
public static int constructor = 0x3e0bdd7c;
|
||||
|
||||
public String username;
|
||||
|
||||
public Class responseClass () {
|
||||
return User.class;
|
||||
}
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
username = stream.readString();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeString(username);
|
||||
}
|
||||
}
|
||||
|
||||
public static class InputAudio extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
@ -6281,19 +6360,28 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessageLayer extends TLObject {
|
||||
public static int constructor = 0x99a438cf;
|
||||
public static int constructor = 0x1be31789;
|
||||
|
||||
public byte[] random_bytes;
|
||||
public int layer;
|
||||
public int in_seq_no;
|
||||
public int out_seq_no;
|
||||
public DecryptedMessage message;
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
random_bytes = stream.readByteArray();
|
||||
layer = stream.readInt32();
|
||||
in_seq_no = stream.readInt32();
|
||||
out_seq_no = stream.readInt32();
|
||||
message = (DecryptedMessage)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeByteArray(random_bytes);
|
||||
stream.writeInt32(layer);
|
||||
stream.writeInt32(in_seq_no);
|
||||
stream.writeInt32(out_seq_no);
|
||||
message.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
@ -8341,32 +8429,157 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
//manually created
|
||||
|
||||
public static class TL_messages_sendEncryptedService extends TLObject {
|
||||
public static int constructor = 0x32d439a4;
|
||||
|
||||
public TL_inputEncryptedChat peer;
|
||||
public long random_id;
|
||||
public byte[] data;
|
||||
public ByteBufferDesc data;
|
||||
|
||||
public Class responseClass () {
|
||||
return messages_SentEncryptedMessage.class;
|
||||
}
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
peer = (TL_inputEncryptedChat)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
random_id = stream.readInt64();
|
||||
data = stream.readByteArray();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
peer.serializeToStream(stream);
|
||||
stream.writeInt64(random_id);
|
||||
stream.writeByteArray(data);
|
||||
stream.writeByteBuffer(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeResources() {
|
||||
if (disableFree) {
|
||||
return;
|
||||
}
|
||||
if (data != null) {
|
||||
BuffersStorage.getInstance().reuseFreeBuffer(data);
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//manually created
|
||||
public static class TL_userDeleted_old extends TL_userDeleted {
|
||||
public static int constructor = 0xb29ad7cc;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_userForeign_old extends TL_userForeign {
|
||||
public static int constructor = 0x5214c89d;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeInt64(access_hash);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_userRequest_old extends TL_userRequest {
|
||||
public static int constructor = 0x22e8ceb0;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeInt64(access_hash);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_userContact_old extends TL_userContact {
|
||||
public static int constructor = 0xf2fb8319;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
access_hash = stream.readInt64();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeInt64(access_hash);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_userSelf_old extends TL_userSelf {
|
||||
public static int constructor = 0x720535ec;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
id = stream.readInt32();
|
||||
first_name = stream.readString();
|
||||
last_name = stream.readString();
|
||||
phone = stream.readString();
|
||||
photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
inactive = stream.readBool();
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(id);
|
||||
stream.writeString(first_name);
|
||||
stream.writeString(last_name);
|
||||
stream.writeString(phone);
|
||||
photo.serializeToStream(stream);
|
||||
status.serializeToStream(stream);
|
||||
stream.writeBool(inactive);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_set_client_DH_params extends TLObject {
|
||||
public static int constructor = 0xf5045f1f;
|
||||
@ -8769,8 +8982,6 @@ public class TLRPC {
|
||||
public int fwd_date;
|
||||
public int from_id;
|
||||
public Peer to_id;
|
||||
public boolean out;
|
||||
public boolean unread;
|
||||
public int date;
|
||||
public String message;
|
||||
public MessageMedia media;
|
||||
@ -8782,6 +8993,10 @@ public class TLRPC {
|
||||
public int local_id = 0;
|
||||
public long dialog_id;
|
||||
public int ttl;
|
||||
public int destroyTime;
|
||||
public int layer;
|
||||
public int seq_in;
|
||||
public int seq_out;
|
||||
public VideoEditedInfo videoEditedInfo = null;
|
||||
}
|
||||
|
||||
@ -8799,8 +9014,6 @@ public class TLRPC {
|
||||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = (flags & MESSAGE_FLAG_OUT) != 0;
|
||||
unread = (flags & MESSAGE_FLAG_UNREAD) != 0;
|
||||
if (id < 0) {
|
||||
fwd_msg_id = stream.readInt32();
|
||||
}
|
||||
@ -8843,8 +9056,6 @@ public class TLRPC {
|
||||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = (flags & 2) != 0;
|
||||
unread = (flags & 1) != 0;
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
|
||||
attachPath = stream.readString();
|
||||
}
|
||||
@ -8878,8 +9089,6 @@ public class TLRPC {
|
||||
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
date = stream.readInt32();
|
||||
action = (MessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = (flags & 2) != 0;
|
||||
unread = (flags & 1) != 0;
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
@ -8901,8 +9110,8 @@ public class TLRPC {
|
||||
id = stream.readInt32();
|
||||
from_id = stream.readInt32();
|
||||
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = stream.readBool();
|
||||
unread = stream.readBool();
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
|
||||
date = stream.readInt32();
|
||||
action = (MessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
@ -8912,8 +9121,8 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeInt32(from_id);
|
||||
to_id.serializeToStream(stream);
|
||||
stream.writeBool(out);
|
||||
stream.writeBool(unread);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
|
||||
stream.writeInt32(date);
|
||||
action.serializeToStream(stream);
|
||||
}
|
||||
@ -8929,8 +9138,8 @@ public class TLRPC {
|
||||
fwd_date = stream.readInt32();
|
||||
from_id = stream.readInt32();
|
||||
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = stream.readBool();
|
||||
unread = stream.readBool();
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
|
||||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -8953,8 +9162,8 @@ public class TLRPC {
|
||||
stream.writeInt32(fwd_date);
|
||||
stream.writeInt32(from_id);
|
||||
to_id.serializeToStream(stream);
|
||||
stream.writeBool(out);
|
||||
stream.writeBool(unread);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
|
||||
stream.writeInt32(date);
|
||||
stream.writeString(message);
|
||||
media.serializeToStream(stream);
|
||||
@ -8972,8 +9181,8 @@ public class TLRPC {
|
||||
id = stream.readInt32();
|
||||
from_id = stream.readInt32();
|
||||
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
out = stream.readBool();
|
||||
unread = stream.readBool();
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0;
|
||||
flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0;
|
||||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
@ -8991,8 +9200,43 @@ public class TLRPC {
|
||||
stream.writeInt32(id);
|
||||
stream.writeInt32(from_id);
|
||||
to_id.serializeToStream(stream);
|
||||
stream.writeBool(out);
|
||||
stream.writeBool(unread);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_OUT) != 0);
|
||||
stream.writeBool((flags & MESSAGE_FLAG_UNREAD) != 0);
|
||||
stream.writeInt32(date);
|
||||
stream.writeString(message);
|
||||
media.serializeToStream(stream);
|
||||
stream.writeString(attachPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_message_secret extends TL_message {
|
||||
public static int constructor = 0x555555F8;
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
flags = stream.readInt32();
|
||||
id = stream.readInt32();
|
||||
ttl = stream.readInt32();
|
||||
from_id = stream.readInt32();
|
||||
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
|
||||
attachPath = stream.readString();
|
||||
}
|
||||
if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) {
|
||||
videoEditedInfo = new VideoEditedInfo();
|
||||
videoEditedInfo.parseString(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(flags);
|
||||
stream.writeInt32(id);
|
||||
stream.writeInt32(ttl);
|
||||
stream.writeInt32(from_id);
|
||||
to_id.serializeToStream(stream);
|
||||
stream.writeInt32(date);
|
||||
stream.writeString(message);
|
||||
media.serializeToStream(stream);
|
||||
@ -9105,6 +9349,7 @@ public class TLRPC {
|
||||
public int id;
|
||||
public String first_name;
|
||||
public String last_name;
|
||||
public String username;
|
||||
public long access_hash;
|
||||
public String phone;
|
||||
public UserProfilePhoto photo;
|
||||
@ -9305,6 +9550,9 @@ public class TLRPC {
|
||||
public byte[] auth_key;
|
||||
public int user_id;
|
||||
public int ttl;
|
||||
public int layer;
|
||||
public int seq_in;
|
||||
public int seq_out;
|
||||
}
|
||||
|
||||
public static class FileLocation extends TLObject {
|
||||
@ -9602,8 +9850,8 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class invokeWithLayer17 extends TLObject {
|
||||
public static int constructor = 0x50858a19;
|
||||
public static class invokeWithLayer18 extends TLObject {
|
||||
public static int constructor = 0x1c900537;
|
||||
|
||||
public TLObject query;
|
||||
|
||||
@ -9634,24 +9882,6 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class decryptedMessageLayer extends TLObject {
|
||||
public static int constructor = 0x99a438cf;
|
||||
|
||||
public int layer;
|
||||
public TLObject message;
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
layer = stream.readInt32();
|
||||
message = TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
stream.writeInt32(constructor);
|
||||
stream.writeInt32(layer);
|
||||
message.serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_encryptedChat_old extends TL_encryptedChat {
|
||||
public static int constructor = 0x6601d14f;
|
||||
|
||||
@ -9738,7 +9968,7 @@ public class TLRPC {
|
||||
}
|
||||
|
||||
public static class TL_decryptedMessageActionScreenshotMessages extends DecryptedMessageAction {
|
||||
public static int constructor = 0x954bd30;
|
||||
public static int constructor = 0x8ac1f475;
|
||||
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
@ -9770,7 +10000,7 @@ public class TLRPC {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TL_messageEcryptedAction extends MessageAction {
|
||||
public static class TL_messageEncryptedAction extends MessageAction {
|
||||
public static int constructor = 0x555555F7;
|
||||
|
||||
public void readParams(AbsSerializedData stream) {
|
||||
|
@ -9,7 +9,6 @@
|
||||
package org.telegram.messenger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -28,7 +27,6 @@ import net.hockeyapp.android.CrashManager;
|
||||
import net.hockeyapp.android.CrashManagerListener;
|
||||
import net.hockeyapp.android.UpdateManager;
|
||||
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.ui.ApplicationLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -74,8 +72,6 @@ public class Utilities {
|
||||
|
||||
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
public static ProgressDialog progressDialog;
|
||||
|
||||
static {
|
||||
try {
|
||||
File URANDOM_FILE = new File("/dev/urandom");
|
||||
@ -112,7 +108,7 @@ public class Utilities {
|
||||
|
||||
public native static long doPQNative(long _what);
|
||||
public native static void loadBitmap(String path, int[] bitmap, int scale, int format, int width, int height);
|
||||
public native static void blurBitmap(Object bitmap);
|
||||
public native static void blurBitmap(Object bitmap, int radius);
|
||||
public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap);
|
||||
private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length);
|
||||
|
||||
@ -427,34 +423,6 @@ public class Utilities {
|
||||
return packedData;
|
||||
}
|
||||
|
||||
public static void ShowProgressDialog(final Activity activity, final String message) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(!activity.isFinishing()) {
|
||||
progressDialog = new ProgressDialog(activity);
|
||||
if (message != null) {
|
||||
progressDialog.setMessage(message);
|
||||
}
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void HideProgressDialog(Activity activity) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (progressDialog != null) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException {
|
||||
OutputStream out = new FileOutputStream(destFile);
|
||||
byte[] buf = new byte[4096];
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
|
||||
public class BaseFragmentAdapter extends BaseAdapter {
|
||||
|
||||
public void onFragmentCreate() {
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import org.telegram.android.MessagesController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.Cells.ChatOrUserCell;
|
||||
import org.telegram.ui.Views.SectionedBaseAdapter;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -202,12 +203,10 @@ public class ContactsActivityAdapter extends SectionedBaseAdapter {
|
||||
if (usersAsSections) {
|
||||
if (section < ContactsController.getInstance().sortedUsersSectionsArray.size()) {
|
||||
if (convertView == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
|
||||
convertView = new SettingsSectionLayout(mContext);
|
||||
convertView.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
|
||||
textView.setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
|
||||
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
|
||||
return convertView;
|
||||
}
|
||||
} else {
|
||||
@ -221,12 +220,10 @@ public class ContactsActivityAdapter extends SectionedBaseAdapter {
|
||||
}
|
||||
|
||||
if (convertView == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
|
||||
convertView = new SettingsSectionLayout(mContext);
|
||||
convertView.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
|
||||
textView.setText(ContactsController.getInstance().sortedContactsSectionsArray.get(section - 1));
|
||||
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedContactsSectionsArray.get(section - 1));
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,13 @@
|
||||
package org.telegram.ui.Adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Html;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.android.ContactsController;
|
||||
import org.telegram.messenger.FileLog;
|
||||
@ -20,28 +23,34 @@ import org.telegram.android.MessagesController;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Cells.ChatOrUserCell;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
public class ContactsActivitySearchAdapter extends BaseContactsSearchAdapter {
|
||||
private Context mContext;
|
||||
private HashMap<Integer, TLRPC.User> ignoreUsers;
|
||||
private ArrayList<TLRPC.User> searchResult;
|
||||
private ArrayList<CharSequence> searchResultNames;
|
||||
private Timer searchTimer;
|
||||
private boolean allowUsernameSearch;
|
||||
|
||||
public ContactsActivitySearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1) {
|
||||
public ContactsActivitySearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1, boolean usernameSearch) {
|
||||
mContext = context;
|
||||
ignoreUsers = arg1;
|
||||
allowUsernameSearch = usernameSearch;
|
||||
}
|
||||
|
||||
public void searchDialogs(final String query) {
|
||||
if (query == null) {
|
||||
searchResult = null;
|
||||
searchResultNames = null;
|
||||
searchResult.clear();
|
||||
searchResultNames.clear();
|
||||
if (allowUsernameSearch) {
|
||||
queryServerSearch(null);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
} else {
|
||||
try {
|
||||
@ -63,7 +72,7 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
}
|
||||
processSearch(query);
|
||||
}
|
||||
}, 100, 300);
|
||||
}, 200, 300);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,6 +80,9 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (allowUsernameSearch) {
|
||||
queryServerSearch(query);
|
||||
}
|
||||
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<TLRPC.TL_contact>();
|
||||
contactsCopy.addAll(ContactsController.getInstance().contacts);
|
||||
Utilities.searchQueue.postRunnable(new Runnable() {
|
||||
@ -87,12 +99,25 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
|
||||
for (TLRPC.TL_contact contact : contactsCopy) {
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id);
|
||||
if (user.id == UserConfig.getClientUserId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
|
||||
|
||||
int found = 0;
|
||||
if (name.startsWith(q) || name.contains(" " + q)) {
|
||||
if (user.id == UserConfig.getClientUserId()) {
|
||||
continue;
|
||||
found = 1;
|
||||
} else if (user.username != null && user.username.startsWith(q)) {
|
||||
found = 2;
|
||||
}
|
||||
|
||||
if (found != 0) {
|
||||
if (found == 1) {
|
||||
resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q));
|
||||
} else {
|
||||
resultArrayNames.add(Utilities.generateSearchName("@" + user.username, null, "@" + q));
|
||||
}
|
||||
resultArrayNames.add(Utilities.generateSearchName(user.first_name, user.last_name, q));
|
||||
resultArray.add(user);
|
||||
}
|
||||
}
|
||||
@ -117,28 +142,43 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int i) {
|
||||
return true;
|
||||
return i != searchResult.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (searchResult == null) {
|
||||
return 0;
|
||||
int count = searchResult.size();
|
||||
int globalCount = globalSearch.size();
|
||||
if (globalCount != 0) {
|
||||
count += globalCount + 1;
|
||||
}
|
||||
return searchResult.size();
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean isGlobalSearch(int i) {
|
||||
int localCount = searchResult.size();
|
||||
int globalCount = globalSearch.size();
|
||||
if (i >= 0 && i < localCount) {
|
||||
return false;
|
||||
} else if (i > localCount && i <= globalCount + localCount) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TLRPC.User getItem(int i) {
|
||||
if (searchResult != null) {
|
||||
if (i >= 0 && i < searchResult.size()) {
|
||||
return searchResult.get(i);
|
||||
}
|
||||
int localCount = searchResult.size();
|
||||
int globalCount = globalSearch.size();
|
||||
if (i >= 0 && i < localCount) {
|
||||
return searchResult.get(i);
|
||||
} else if (i > localCount && i <= globalCount + localCount) {
|
||||
return globalSearch.get(i - localCount - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -155,24 +195,47 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
|
||||
@Override
|
||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||
if (view == null) {
|
||||
view = new ChatOrUserCell(mContext);
|
||||
((ChatOrUserCell)view).usePadding = false;
|
||||
}
|
||||
if (i == searchResult.size()) {
|
||||
if (view == null) {
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
|
||||
}
|
||||
} else {
|
||||
if (view == null) {
|
||||
view = new ChatOrUserCell(mContext);
|
||||
((ChatOrUserCell) view).usePadding = false;
|
||||
}
|
||||
|
||||
((ChatOrUserCell) view).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);
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(((TLRPC.User)obj).id);
|
||||
((ChatOrUserCell) view).setData(user, null, null, name, username);
|
||||
|
||||
if (user != null) {
|
||||
((ChatOrUserCell)view).setData(user, null, null, searchResultNames.get(i), null);
|
||||
|
||||
if (ignoreUsers != null) {
|
||||
if (ignoreUsers.containsKey(user.id)) {
|
||||
((ChatOrUserCell)view).drawAlpha = 0.5f;
|
||||
} else {
|
||||
((ChatOrUserCell)view).drawAlpha = 1.0f;
|
||||
if (ignoreUsers != null) {
|
||||
if (ignoreUsers.containsKey(user.id)) {
|
||||
((ChatOrUserCell) view).drawAlpha = 0.5f;
|
||||
} else {
|
||||
((ChatOrUserCell) view).drawAlpha = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,16 +244,19 @@ public class ContactsActivitySearchAdapter extends BaseFragmentAdapter {
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int i) {
|
||||
if (i == searchResult.size()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return searchResult == null || searchResult.size() == 0;
|
||||
return searchResult.isEmpty() && globalSearch.isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,43 @@ package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
public class BaseCell extends View {
|
||||
|
||||
private final class CheckForTap implements Runnable {
|
||||
public void run() {
|
||||
if (pendingCheckForLongPress == null) {
|
||||
pendingCheckForLongPress = new CheckForLongPress();
|
||||
}
|
||||
pendingCheckForLongPress.currentPressCount = ++pressCount;
|
||||
postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
class CheckForLongPress implements Runnable {
|
||||
public int currentPressCount;
|
||||
|
||||
public void run() {
|
||||
if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) {
|
||||
checkingForLongPress = false;
|
||||
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
||||
onTouchEvent(event);
|
||||
event.recycle();
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
onLongPress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkingForLongPress = false;
|
||||
private CheckForLongPress pendingCheckForLongPress = null;
|
||||
private int pressCount = 0;
|
||||
private CheckForTap pendingCheckForTap = null;
|
||||
|
||||
public BaseCell(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@ -25,4 +58,29 @@ public class BaseCell extends View {
|
||||
protected void setDrawableBounds(Drawable drawable, int x, int y, int w, int h) {
|
||||
drawable.setBounds(x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
protected void startCheckLongPress() {
|
||||
if (checkingForLongPress) {
|
||||
return;
|
||||
}
|
||||
checkingForLongPress = true;
|
||||
if (pendingCheckForTap == null) {
|
||||
pendingCheckForTap = new CheckForTap();
|
||||
}
|
||||
postDelayed(pendingCheckForTap, ViewConfiguration.getTapTimeout());
|
||||
}
|
||||
|
||||
protected void cancelCheckLongPress() {
|
||||
checkingForLongPress = false;
|
||||
if (pendingCheckForLongPress != null) {
|
||||
removeCallbacks(pendingCheckForLongPress);
|
||||
}
|
||||
if (pendingCheckForTap != null) {
|
||||
removeCallbacks(pendingCheckForTap);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onLongPress() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
private static TextPaint timePaint;
|
||||
|
||||
private ImageReceiver avatarImage;
|
||||
private boolean needAvatarImage = false;
|
||||
private SeekBar seekBar;
|
||||
private ProgressView progressView;
|
||||
private int seekBarX;
|
||||
@ -44,9 +45,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
private int buttonState = 0;
|
||||
private int buttonX;
|
||||
private int buttonY;
|
||||
private int buttonPressed = 0;
|
||||
private boolean buttonPressed = false;
|
||||
|
||||
private int avatarPressed = 0;
|
||||
private boolean avatarPressed = false;
|
||||
|
||||
private StaticLayout timeLayout;
|
||||
private int timeX;
|
||||
@ -56,7 +57,6 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
|
||||
public TLRPC.User audioUser;
|
||||
private TLRPC.FileLocation currentPhoto;
|
||||
private String currentNameString;
|
||||
|
||||
public ChatAudioCell(Context context) {
|
||||
super(context);
|
||||
@ -115,40 +115,40 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
int side = AndroidUtilities.dp(36);
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
|
||||
buttonPressed = 1;
|
||||
buttonPressed = true;
|
||||
invalidate();
|
||||
result = true;
|
||||
} else if (avatarImage.isInsideImage(x, y)) {
|
||||
avatarPressed = 1;
|
||||
} else if (needAvatarImage && avatarImage.isInsideImage(x, y)) {
|
||||
avatarPressed = true;
|
||||
result = true;
|
||||
}
|
||||
} else if (buttonPressed == 1) {
|
||||
} else if (buttonPressed) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
buttonPressed = 0;
|
||||
buttonPressed = false;
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
didPressedButton();
|
||||
invalidate();
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
buttonPressed = 0;
|
||||
buttonPressed = false;
|
||||
invalidate();
|
||||
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) {
|
||||
buttonPressed = 0;
|
||||
buttonPressed = false;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
} else if (avatarPressed == 1) {
|
||||
} else if (avatarPressed) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
avatarPressed = 0;
|
||||
avatarPressed = false;
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
if (delegate != null) {
|
||||
delegate.didPressedUserAvatar(this, audioUser);
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
avatarPressed = 0;
|
||||
avatarPressed = false;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (!avatarImage.isInsideImage(x, y)) {
|
||||
avatarPressed = 0;
|
||||
avatarPressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -301,7 +301,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
int x;
|
||||
|
||||
if (currentMessageObject.isOut()) {
|
||||
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(9);
|
||||
x = layoutWidth - backgroundWidth + AndroidUtilities.dp(8);
|
||||
seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(97);
|
||||
buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67);
|
||||
timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(71);
|
||||
@ -318,11 +318,19 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
timeX = AndroidUtilities.dp(80);
|
||||
}
|
||||
}
|
||||
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);
|
||||
progressView.width = backgroundWidth - AndroidUtilities.dp(136);
|
||||
progressView.width = backgroundWidth - AndroidUtilities.dp(136) + diff;
|
||||
progressView.height = AndroidUtilities.dp(30);
|
||||
seekBarY = AndroidUtilities.dp(13);
|
||||
buttonY = AndroidUtilities.dp(10);
|
||||
@ -349,14 +357,18 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
if (uid == 0) {
|
||||
uid = messageObject.messageOwner.from_id;
|
||||
}
|
||||
needAvatarImage = !(messageObject.messageOwner.to_id != null && messageObject.messageOwner.to_id.chat_id != 0 && !messageObject.isOut() && messageObject.messageOwner.media.audio.user_id == messageObject.messageOwner.from_id);
|
||||
audioUser = MessagesController.getInstance().getUser(uid);
|
||||
if (audioUser != null) {
|
||||
if (audioUser.photo != null) {
|
||||
currentPhoto = audioUser.photo.photo_small;
|
||||
|
||||
if (needAvatarImage) {
|
||||
if (audioUser != null) {
|
||||
if (audioUser.photo != null) {
|
||||
currentPhoto = audioUser.photo.photo_small;
|
||||
}
|
||||
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)), false);
|
||||
} else {
|
||||
avatarImage.setImage(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()) {
|
||||
@ -380,7 +392,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
return;
|
||||
}
|
||||
|
||||
avatarImage.draw(canvas, avatarImage.getImageX(), avatarImage.getImageY(), AndroidUtilities.dp(50), AndroidUtilities.dp(50));
|
||||
if (needAvatarImage) {
|
||||
avatarImage.draw(canvas);
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
if (buttonState == 0 || buttonState == 1) {
|
||||
@ -399,7 +413,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
|
||||
} else {
|
||||
timePaint.setColor(0xff70b15c);
|
||||
}
|
||||
Drawable buttonDrawable = statesDrawable[state][buttonPressed];
|
||||
Drawable buttonDrawable = statesDrawable[state][buttonPressed ? 1 : 0];
|
||||
int side = AndroidUtilities.dp(36);
|
||||
int x = (side - buttonDrawable.getIntrinsicWidth()) / 2;
|
||||
int y = (side - buttonDrawable.getIntrinsicHeight()) / 2;
|
||||
|
@ -17,10 +17,8 @@ import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.ContactsController;
|
||||
@ -96,7 +94,7 @@ public class ChatBaseCell extends BaseCell {
|
||||
|
||||
private StaticLayout timeLayout;
|
||||
protected int timeWidth;
|
||||
protected int timeX;
|
||||
private int timeX;
|
||||
private TextPaint currentTimePaint;
|
||||
private String currentTimeString;
|
||||
protected boolean drawTime = true;
|
||||
@ -108,58 +106,15 @@ public class ChatBaseCell extends BaseCell {
|
||||
private TLRPC.User currentForwardUser;
|
||||
private String currentForwardNameString;
|
||||
|
||||
public ChatBaseCellDelegate delegate;
|
||||
protected ChatBaseCellDelegate delegate;
|
||||
|
||||
protected int namesOffset = 0;
|
||||
|
||||
private boolean checkingForLongPress = false;
|
||||
private int pressCount = 0;
|
||||
private CheckForLongPress pendingCheckForLongPress = null;
|
||||
private CheckForTap pendingCheckForTap = null;
|
||||
|
||||
private int last_send_state = 0;
|
||||
|
||||
private final class CheckForTap implements Runnable {
|
||||
public void run() {
|
||||
if (pendingCheckForLongPress == null) {
|
||||
pendingCheckForLongPress = new CheckForLongPress();
|
||||
}
|
||||
pendingCheckForLongPress.currentPressCount = ++pressCount;
|
||||
postDelayed(pendingCheckForLongPress, ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
class CheckForLongPress implements Runnable {
|
||||
public int currentPressCount;
|
||||
|
||||
public void run() {
|
||||
if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) {
|
||||
if (delegate != null) {
|
||||
checkingForLongPress = false;
|
||||
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
||||
onTouchEvent(event);
|
||||
event.recycle();
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
delegate.didLongPressed(ChatBaseCell.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private int last_delete_date = 0;
|
||||
|
||||
public ChatBaseCell(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
avatarImage = new ImageReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
avatarImage.clearImage();
|
||||
currentPhoto = null;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (backgroundDrawableIn == null) {
|
||||
backgroundDrawableIn = getResources().getDrawable(R.drawable.msg_in);
|
||||
backgroundDrawableInSelected = getResources().getDrawable(R.drawable.msg_in_selected);
|
||||
@ -198,6 +153,14 @@ public class ChatBaseCell extends BaseCell {
|
||||
forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
forwardNamePaint.setTextSize(AndroidUtilities.dp(14));
|
||||
}
|
||||
avatarImage = new ImageReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
avatarImage.clearImage();
|
||||
currentPhoto = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -206,6 +169,10 @@ public class ChatBaseCell extends BaseCell {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setDelegate(ChatBaseCellDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public void setCheckPressed(boolean value, boolean pressed) {
|
||||
isCheckPressed = value;
|
||||
isPressed = pressed;
|
||||
@ -219,6 +186,9 @@ public class ChatBaseCell extends BaseCell {
|
||||
if (last_send_state != currentMessageObject.messageOwner.send_state) {
|
||||
return true;
|
||||
}
|
||||
if (last_delete_date != currentMessageObject.messageOwner.destroyTime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TLRPC.User newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id);
|
||||
TLRPC.FileLocation newPhoto = null;
|
||||
@ -251,6 +221,7 @@ public class ChatBaseCell extends BaseCell {
|
||||
public void setMessageObject(MessageObject messageObject) {
|
||||
currentMessageObject = messageObject;
|
||||
last_send_state = messageObject.messageOwner.send_state;
|
||||
last_delete_date = messageObject.messageOwner.destroyTime;
|
||||
isPressed = false;
|
||||
isCheckPressed = true;
|
||||
isAvatarVisible = false;
|
||||
@ -344,27 +315,6 @@ public class ChatBaseCell extends BaseCell {
|
||||
return backgroundWidth - AndroidUtilities.dp(8);
|
||||
}
|
||||
|
||||
protected void startCheckLongPress() {
|
||||
if (checkingForLongPress) {
|
||||
return;
|
||||
}
|
||||
checkingForLongPress = true;
|
||||
if (pendingCheckForTap == null) {
|
||||
pendingCheckForTap = new CheckForTap();
|
||||
}
|
||||
postDelayed(pendingCheckForTap, ViewConfiguration.getTapTimeout());
|
||||
}
|
||||
|
||||
protected void cancelCheckLongPress() {
|
||||
checkingForLongPress = false;
|
||||
if (pendingCheckForLongPress != null) {
|
||||
removeCallbacks(pendingCheckForLongPress);
|
||||
}
|
||||
if (pendingCheckForTap != null) {
|
||||
removeCallbacks(pendingCheckForTap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean result = false;
|
||||
@ -461,6 +411,12 @@ public class ChatBaseCell extends BaseCell {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLongPress() {
|
||||
if (delegate != null) {
|
||||
delegate.didLongPressed(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
@ -474,7 +430,7 @@ public class ChatBaseCell extends BaseCell {
|
||||
}
|
||||
|
||||
if (isAvatarVisible) {
|
||||
avatarImage.draw(canvas, AndroidUtilities.dp(6), layoutHeight - AndroidUtilities.dp(45), AndroidUtilities.dp(42), AndroidUtilities.dp(42));
|
||||
avatarImage.draw(canvas);
|
||||
}
|
||||
|
||||
Drawable currentBackgroundDrawable = null;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import android.view.animation.DecelerateInterpolator;
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.ImageLoader;
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.messenger.ConnectionsManager;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.android.MediaController;
|
||||
import org.telegram.messenger.R;
|
||||
@ -41,7 +42,7 @@ import java.util.Locale;
|
||||
public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener {
|
||||
|
||||
public static interface ChatMediaCellDelegate {
|
||||
public abstract void didPressedImage(ChatMediaCell cell);
|
||||
public abstract void didClickedImage(ChatMediaCell cell);
|
||||
public abstract void didPressedOther(ChatMediaCell cell);
|
||||
}
|
||||
|
||||
@ -52,13 +53,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
private static Drawable videoIconDrawable;
|
||||
private static Drawable docMenuInDrawable;
|
||||
private static Drawable docMenuOutDrawable;
|
||||
private static Drawable[] buttonStatesDrawables = new Drawable[5];
|
||||
private static Drawable[] buttonStatesDrawables = new Drawable[8];
|
||||
private static Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][2];
|
||||
private static TextPaint infoPaint;
|
||||
private static MessageObject lastDownloadedGifMessage = null;
|
||||
private static TextPaint namePaint;
|
||||
private static Paint docBackPaint;
|
||||
private static Paint progressPaint;
|
||||
private static Paint deleteProgressPaint;
|
||||
private static DecelerateInterpolator decelerateInterpolator;
|
||||
|
||||
private GifDrawable gifDrawable = null;
|
||||
@ -91,7 +93,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
private int nameWidth = 0;
|
||||
private String currentNameString;
|
||||
|
||||
public ChatMediaCellDelegate mediaDelegate = null;
|
||||
private ChatMediaCellDelegate mediaDelegate = null;
|
||||
|
||||
private float currentProgress = 0;
|
||||
private RectF progressRect = new RectF();
|
||||
@ -101,6 +103,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
private float animatedProgressValue = 0;
|
||||
private long currentProgressTime = 0;
|
||||
private float animationProgressStart = 0;
|
||||
private RectF deleteProgressRect = new RectF();
|
||||
private int lastSecretSecondsLeft = 0;
|
||||
|
||||
public ChatMediaCell(Context context) {
|
||||
super(context);
|
||||
@ -115,6 +119,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
buttonStatesDrawables[2] = getResources().getDrawable(R.drawable.photogif);
|
||||
buttonStatesDrawables[3] = getResources().getDrawable(R.drawable.playvideo);
|
||||
buttonStatesDrawables[4] = getResources().getDrawable(R.drawable.photopause);
|
||||
buttonStatesDrawables[5] = getResources().getDrawable(R.drawable.burn);
|
||||
buttonStatesDrawables[6] = getResources().getDrawable(R.drawable.circle);
|
||||
buttonStatesDrawables[7] = getResources().getDrawable(R.drawable.photocheck);
|
||||
buttonStatesDrawablesDoc[0][0] = getResources().getDrawable(R.drawable.docload_b);
|
||||
buttonStatesDrawablesDoc[1][0] = getResources().getDrawable(R.drawable.doccancel_b);
|
||||
buttonStatesDrawablesDoc[2][0] = getResources().getDrawable(R.drawable.docpause_b);
|
||||
@ -139,6 +146,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
progressPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
|
||||
|
||||
deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
deleteProgressPaint.setColor(0xffe4e2e0);
|
||||
|
||||
decelerateInterpolator = new DecelerateInterpolator();
|
||||
}
|
||||
|
||||
@ -155,6 +165,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
}
|
||||
}
|
||||
|
||||
public void setMediaDelegate(ChatMediaCellDelegate delegate) {
|
||||
this.mediaDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
@ -199,7 +213,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result) {
|
||||
if (imagePressed && currentMessageObject.isSecretPhoto()) {
|
||||
imagePressed = false;
|
||||
} else if (result) {
|
||||
startCheckLongPress();
|
||||
}
|
||||
}
|
||||
@ -225,8 +241,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
} else if (imagePressed) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
imagePressed = false;
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
didPressedImage();
|
||||
if (buttonState == -1 || buttonState == 2 || buttonState == 3) {
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
didClickedImage();
|
||||
}
|
||||
invalidate();
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
imagePressed = false;
|
||||
@ -269,11 +287,11 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
return result;
|
||||
}
|
||||
|
||||
private void didPressedImage() {
|
||||
private void didClickedImage() {
|
||||
if (currentMessageObject.type == 1) {
|
||||
if (buttonState == -1) {
|
||||
if (mediaDelegate != null) {
|
||||
mediaDelegate.didPressedImage(this);
|
||||
mediaDelegate.didClickedImage(this);
|
||||
}
|
||||
} else if (buttonState == 0) {
|
||||
didPressedButton();
|
||||
@ -294,12 +312,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
}
|
||||
} else if (currentMessageObject.type == 4) {
|
||||
if (mediaDelegate != null) {
|
||||
mediaDelegate.didPressedImage(this);
|
||||
mediaDelegate.didClickedImage(this);
|
||||
}
|
||||
} else if (currentMessageObject.type == 9) {
|
||||
if (buttonState == -1) {
|
||||
if (mediaDelegate != null) {
|
||||
mediaDelegate.didPressedImage(this);
|
||||
mediaDelegate.didClickedImage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,7 +376,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
}
|
||||
} else if (buttonState == 3) {
|
||||
if (mediaDelegate != null) {
|
||||
mediaDelegate.didPressedImage(this);
|
||||
mediaDelegate.didClickedImage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -467,6 +485,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
currentNameString = null;
|
||||
infoLayout = null;
|
||||
nameLayout = null;
|
||||
updateSecretTimeText();
|
||||
}
|
||||
|
||||
if (messageObject.type == 9) {
|
||||
@ -549,6 +568,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
w = timeWidthTotal;
|
||||
}
|
||||
|
||||
if (currentMessageObject.isSecretPhoto()) {
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
w = h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f);
|
||||
} else {
|
||||
w = h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
photoWidth = w;
|
||||
photoHeight = h;
|
||||
backgroundWidth = w + AndroidUtilities.dp(12);
|
||||
@ -589,6 +616,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
photoImage.setImageBitmap(messageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable);
|
||||
}
|
||||
}
|
||||
photoImage.setForcePreview(messageObject.isSecretPhoto());
|
||||
|
||||
invalidate();
|
||||
}
|
||||
@ -754,6 +782,25 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
buttonX = (int)(x + (photoWidth - size) / 2.0f);
|
||||
buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f);
|
||||
progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(47), buttonY + AndroidUtilities.dp(47));
|
||||
deleteProgressRect.set(buttonX + AndroidUtilities.dp(3), buttonY + AndroidUtilities.dp(3), buttonX + AndroidUtilities.dp(45), buttonY + AndroidUtilities.dp(45));
|
||||
}
|
||||
|
||||
private void updateSecretTimeText() {
|
||||
if (currentMessageObject == null || currentMessageObject.isOut()) {
|
||||
return;
|
||||
}
|
||||
String str = currentMessageObject.getSecretTimeString();
|
||||
if (str == null) {
|
||||
return;
|
||||
}
|
||||
if (currentInfoString == null || !currentInfoString.equals(str)) {
|
||||
currentInfoString = str;
|
||||
infoOffset = 0;
|
||||
infoWidth = (int)Math.ceil(infoPaint.measureText(currentInfoString));
|
||||
CharSequence str2 = TextUtils.ellipsize(currentInfoString, infoPaint, infoWidth, TextUtils.TruncateAt.END);
|
||||
infoLayout = new StaticLayout(str2, infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -766,7 +813,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
canvas.restore();
|
||||
} else {
|
||||
photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false);
|
||||
imageDrawn = photoImage.draw(canvas, photoImage.getImageX(), photoImage.getImageY(), photoWidth, photoHeight);
|
||||
imageDrawn = photoImage.draw(canvas);
|
||||
drawTime = photoImage.getVisible();
|
||||
}
|
||||
|
||||
@ -826,6 +873,29 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
currentButtonDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
if (buttonState == -1 && currentMessageObject.isSecretPhoto()) {
|
||||
int drawable = 5;
|
||||
if (currentMessageObject.messageOwner.destroyTime != 0) {
|
||||
if (currentMessageObject.isOut()) {
|
||||
drawable = 7;
|
||||
} else {
|
||||
drawable = 6;
|
||||
}
|
||||
}
|
||||
setDrawableBounds(buttonStatesDrawables[drawable], buttonX, buttonY);
|
||||
buttonStatesDrawables[drawable].draw(canvas);
|
||||
if (!currentMessageObject.isOut() && currentMessageObject.messageOwner.destroyTime != 0) {
|
||||
long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance().getTimeDifference() * 1000;
|
||||
float progress = Math.max(0, (long)currentMessageObject.messageOwner.destroyTime * 1000 - msTime) / (currentMessageObject.messageOwner.ttl * 1000.0f);
|
||||
canvas.drawArc(deleteProgressRect, -90, -360 * progress, true, deleteProgressPaint);
|
||||
if (progress != 0) {
|
||||
int offset = AndroidUtilities.dp(2);
|
||||
invalidate((int)deleteProgressRect.left - offset, (int)deleteProgressRect.top - offset, (int)deleteProgressRect.right + offset * 2, (int)deleteProgressRect.bottom + offset * 2);
|
||||
}
|
||||
updateSecretTimeText();
|
||||
}
|
||||
}
|
||||
|
||||
if (progressVisible) {
|
||||
canvas.drawArc(progressRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint);
|
||||
}
|
||||
@ -842,7 +912,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
||||
infoLayout.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
} else if (infoLayout != null && (buttonState == 1 || buttonState == 0 || buttonState == 3)) {
|
||||
} else if (infoLayout != null && (buttonState == 1 || buttonState == 0 || buttonState == 3 || currentMessageObject.isSecretPhoto())) {
|
||||
infoPaint.setColor(0xffffffff);
|
||||
setDrawableBounds(mediaBackgroundDrawable, photoImage.getImageX() + AndroidUtilities.dp(4), photoImage.getImageY() + AndroidUtilities.dp(4), infoWidth + AndroidUtilities.dp(8) + infoOffset, AndroidUtilities.dpf(16.5f));
|
||||
mediaBackgroundDrawable.draw(canvas);
|
||||
|
@ -43,36 +43,41 @@ public class ChatMessageCell extends ChatBaseCell {
|
||||
y -= textY;
|
||||
int blockNum = Math.max(0, y / currentMessageObject.blockHeight);
|
||||
if (blockNum < currentMessageObject.textLayoutBlocks.size()) {
|
||||
MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
|
||||
x -= textX - (int)Math.ceil(block.textXOffset);
|
||||
y -= block.textYOffset;
|
||||
final int line = block.textLayout.getLineForVertical(y);
|
||||
final int off = block.textLayout.getOffsetForHorizontal(line, x) + block.charactersOffset;
|
||||
try {
|
||||
MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
|
||||
x -= textX - (int)Math.ceil(block.textXOffset);
|
||||
y -= block.textYOffset;
|
||||
final int line = block.textLayout.getLineForVertical(y);
|
||||
final int off = block.textLayout.getOffsetForHorizontal(line, x) + block.charactersOffset;
|
||||
|
||||
final float left = block.textLayout.getLineLeft(line);
|
||||
if (left <= x && left + block.textLayout.getLineWidth(line) >= x) {
|
||||
Spannable buffer = (Spannable)currentMessageObject.messageText;
|
||||
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
|
||||
final float left = block.textLayout.getLineLeft(line);
|
||||
if (left <= x && left + block.textLayout.getLineWidth(line) >= x) {
|
||||
Spannable buffer = (Spannable)currentMessageObject.messageText;
|
||||
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
|
||||
|
||||
if (link.length != 0) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
pressedLink = link[0];
|
||||
return true;
|
||||
} else {
|
||||
if (link[0] == pressedLink) {
|
||||
try {
|
||||
pressedLink.onClick(this);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
if (link.length != 0) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
pressedLink = link[0];
|
||||
return true;
|
||||
} else {
|
||||
if (link[0] == pressedLink) {
|
||||
try {
|
||||
pressedLink.onClick(this);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pressedLink = null;
|
||||
}
|
||||
} else {
|
||||
pressedLink = null;
|
||||
}
|
||||
} else {
|
||||
} catch (Exception e) {
|
||||
pressedLink = null;
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
} else {
|
||||
pressedLink = null;
|
||||
|
@ -41,7 +41,7 @@ public class ChatOrUserCell extends BaseCell {
|
||||
|
||||
private CharSequence currentName;
|
||||
private ImageReceiver avatarImage;
|
||||
private String subLabel;
|
||||
private CharSequence subLabel;
|
||||
|
||||
private ChatOrUserCellLayout cellLayout;
|
||||
private TLRPC.User user = null;
|
||||
@ -112,7 +112,7 @@ public class ChatOrUserCell extends BaseCell {
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(TLRPC.User u, TLRPC.Chat c, TLRPC.EncryptedChat ec, CharSequence n, String s) {
|
||||
public void setData(TLRPC.User u, TLRPC.Chat c, TLRPC.EncryptedChat ec, CharSequence n, CharSequence s) {
|
||||
currentName = n;
|
||||
user = u;
|
||||
chat = c;
|
||||
@ -236,6 +236,15 @@ public class ChatOrUserCell extends BaseCell {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useSeparator) {
|
||||
int h = getMeasuredHeight();
|
||||
if (!usePadding) {
|
||||
canvas.drawLine(0, h - 1, getMeasuredWidth(), h - 1, linePaint);
|
||||
} else {
|
||||
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h - 1, linePaint);
|
||||
}
|
||||
}
|
||||
|
||||
if (drawAlpha != 1) {
|
||||
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int)(255 * drawAlpha), Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
|
||||
}
|
||||
@ -263,16 +272,7 @@ public class ChatOrUserCell extends BaseCell {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
avatarImage.draw(canvas, cellLayout.avatarLeft, cellLayout.avatarTop, AndroidUtilities.dp(50), AndroidUtilities.dp(50));
|
||||
|
||||
if (useSeparator) {
|
||||
int h = getMeasuredHeight();
|
||||
if (!usePadding) {
|
||||
canvas.drawLine(0, h - 1, getMeasuredWidth(), h, linePaint);
|
||||
} else {
|
||||
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h, linePaint);
|
||||
}
|
||||
}
|
||||
avatarImage.draw(canvas);
|
||||
}
|
||||
|
||||
private class ChatOrUserCellLayout {
|
||||
@ -381,7 +381,7 @@ public class ChatOrUserCell extends BaseCell {
|
||||
onlineLeft = usePadding ? AndroidUtilities.dp(11) : 0;
|
||||
}
|
||||
|
||||
String onlineString = "";
|
||||
CharSequence onlineString = "";
|
||||
TextPaint currentOnlinePaint = offlinePaint;
|
||||
|
||||
if (subLabel != null) {
|
||||
|
@ -10,6 +10,7 @@ package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Html;
|
||||
import android.text.Layout;
|
||||
@ -48,6 +49,8 @@ public class DialogCell extends BaseCell {
|
||||
private static Drawable groupDrawable;
|
||||
private static Drawable broadcastDrawable;
|
||||
|
||||
private static Paint linePaint;
|
||||
|
||||
private TLRPC.TL_dialog currentDialog;
|
||||
private ImageReceiver avatarImage;
|
||||
|
||||
@ -57,6 +60,8 @@ public class DialogCell extends BaseCell {
|
||||
private TLRPC.EncryptedChat encryptedChat = null;
|
||||
private CharSequence lastPrintString = null;
|
||||
|
||||
public boolean useSeparator = false;
|
||||
|
||||
private void init() {
|
||||
if (namePaint == null) {
|
||||
namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
@ -85,6 +90,11 @@ public class DialogCell extends BaseCell {
|
||||
messagePaint.setColor(0xff808080);
|
||||
}
|
||||
|
||||
if (linePaint == null) {
|
||||
linePaint = new Paint();
|
||||
linePaint.setColor(0xffdcdcdc);
|
||||
}
|
||||
|
||||
if (messagePrintingPaint == null) {
|
||||
messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||
messagePrintingPaint.setTextSize(AndroidUtilities.dp(16));
|
||||
@ -340,7 +350,16 @@ public class DialogCell extends BaseCell {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
avatarImage.draw(canvas, cellLayout.avatarLeft, cellLayout.avatarTop, AndroidUtilities.dp(54), AndroidUtilities.dp(54));
|
||||
avatarImage.draw(canvas);
|
||||
|
||||
if (useSeparator) {
|
||||
int h = getMeasuredHeight();
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
canvas.drawLine(0, h - 1, getMeasuredWidth(), h - 1, linePaint);
|
||||
} else {
|
||||
canvas.drawLine(AndroidUtilities.dp(11), h - 1, getMeasuredWidth() - AndroidUtilities.dp(11), h - 1, linePaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DialogCellLayout {
|
||||
|
@ -42,6 +42,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.Views.AvatarUpdater;
|
||||
import org.telegram.ui.Views.BackupImageView;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -476,6 +477,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
|
||||
args.putBoolean("destroyAfterSelect", true);
|
||||
args.putBoolean("usersAsSections", true);
|
||||
args.putBoolean("returnAsResult", true);
|
||||
//args.putBoolean("allowUsernameSearch", false);
|
||||
if (chat_id > 0) {
|
||||
args.putString("selectAlertString", LocaleController.getString("AddToTheGroup", R.string.AddToTheGroup));
|
||||
}
|
||||
@ -646,21 +648,19 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
|
||||
return view;
|
||||
} else if (type == 1) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
}
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
|
||||
if (i == settingsSectionRow) {
|
||||
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
} else if (i == sharedMediaSectionRow) {
|
||||
textView.setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
|
||||
} else if (i == membersSectionRow) {
|
||||
TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id);
|
||||
int count = chat.participants_count;
|
||||
if (info != null) {
|
||||
count = info.participants.size();
|
||||
}
|
||||
textView.setText(LocaleController.formatPluralString("Members", count).toUpperCase());
|
||||
((SettingsSectionLayout) view).setText(LocaleController.formatPluralString("Members", count).toUpperCase());
|
||||
}
|
||||
} else if (type == 2) {
|
||||
if (view == null) {
|
||||
|
@ -11,6 +11,9 @@ package org.telegram.ui;
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -18,6 +21,7 @@ import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
@ -26,6 +30,7 @@ import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.android.MessagesController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
public class ChatProfileChangeNameActivity extends BaseFragment {
|
||||
private EditText firstNameField;
|
||||
@ -71,16 +76,27 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
|
||||
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
|
||||
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
|
||||
|
||||
fragmentView = inflater.inflate(R.layout.chat_profile_change_name_layout, container, false);
|
||||
|
||||
TLRPC.Chat currentChat = MessagesController.getInstance().getChat(chat_id);
|
||||
|
||||
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field);
|
||||
if (chat_id > 0) {
|
||||
firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName));
|
||||
} else {
|
||||
firstNameField.setHint(LocaleController.getString("EnterListName", R.string.EnterListName));
|
||||
}
|
||||
fragmentView = new LinearLayout(inflater.getContext());
|
||||
fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
|
||||
((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
SettingsSectionLayout settingsSectionLayout = new SettingsSectionLayout(inflater.getContext());
|
||||
((LinearLayout) fragmentView).addView(settingsSectionLayout);
|
||||
|
||||
firstNameField = new EditText(inflater.getContext());
|
||||
firstNameField.setText(currentChat.title);
|
||||
firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
|
||||
firstNameField.setHintTextColor(0xffa3a3a3);
|
||||
firstNameField.setTextColor(0xff000000);
|
||||
firstNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
|
||||
firstNameField.setMaxLines(3);
|
||||
firstNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
|
||||
firstNameField.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
AndroidUtilities.clearCursorDrawable(firstNameField);
|
||||
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
|
||||
@ -91,15 +107,25 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
firstNameField.setText(currentChat.title);
|
||||
firstNameField.setSelection(firstNameField.length());
|
||||
|
||||
TextView headerLabel = (TextView)fragmentView.findViewById(R.id.settings_section_text);
|
||||
if (chat_id > 0) {
|
||||
headerLabel.setText(LocaleController.getString("EnterGroupNameTitle", R.string.EnterGroupNameTitle));
|
||||
} else {
|
||||
headerLabel.setText(LocaleController.getString("EnterListName", R.string.EnterListName).toUpperCase());
|
||||
if (LocaleController.isRTL) {
|
||||
firstNameField.setGravity(Gravity.RIGHT);
|
||||
}
|
||||
|
||||
((LinearLayout) fragmentView).addView(firstNameField);
|
||||
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)firstNameField.getLayoutParams();
|
||||
layoutParams.topMargin = AndroidUtilities.dp(15);
|
||||
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
firstNameField.setLayoutParams(layoutParams);
|
||||
|
||||
if (chat_id > 0) {
|
||||
settingsSectionLayout.setText(LocaleController.getString("EnterGroupNameTitle", R.string.EnterGroupNameTitle));
|
||||
firstNameField.setHint(LocaleController.getString("GroupName", R.string.GroupName));
|
||||
} else {
|
||||
settingsSectionLayout.setText(LocaleController.getString("EnterListName", R.string.EnterListName).toUpperCase());
|
||||
firstNameField.setHint(LocaleController.getString("EnterListName", R.string.EnterListName));
|
||||
}
|
||||
firstNameField.setSelection(firstNameField.length());
|
||||
} else {
|
||||
ViewGroup parent = (ViewGroup)fragmentView.getParent();
|
||||
if (parent != null) {
|
||||
|
@ -30,6 +30,7 @@ import android.widget.TextView;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.android.MessagesStorage;
|
||||
import org.telegram.messenger.TLObject;
|
||||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.messenger.ConnectionsManager;
|
||||
@ -72,6 +73,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
private String inviteText;
|
||||
private boolean updatingInviteText = false;
|
||||
private boolean allowUsernameSearch = true;
|
||||
private ContactsActivityDelegate delegate;
|
||||
|
||||
public static interface ContactsActivityDelegate {
|
||||
@ -91,11 +93,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatCreated);
|
||||
if (arguments != null) {
|
||||
onlyUsers = getArguments().getBoolean("onlyUsers", false);
|
||||
destroyAfterSelect = getArguments().getBoolean("destroyAfterSelect", false);
|
||||
usersAsSections = getArguments().getBoolean("usersAsSections", false);
|
||||
returnAsResult = getArguments().getBoolean("returnAsResult", false);
|
||||
createSecretChat = getArguments().getBoolean("createSecretChat", false);
|
||||
destroyAfterSelect = arguments.getBoolean("destroyAfterSelect", false);
|
||||
usersAsSections = arguments.getBoolean("usersAsSections", false);
|
||||
returnAsResult = arguments.getBoolean("returnAsResult", false);
|
||||
createSecretChat = arguments.getBoolean("createSecretChat", false);
|
||||
selectAlertString = arguments.getString("selectAlertString");
|
||||
allowUsernameSearch = arguments.getBoolean("allowUsernameSearch", true);
|
||||
}
|
||||
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
@ -199,7 +202,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
emptyTextView = (TextView)fragmentView.findViewById(R.id.searchEmptyView);
|
||||
emptyTextView.setText(LocaleController.getString("NoContacts", R.string.NoContacts));
|
||||
searchListViewAdapter = new ContactsActivitySearchAdapter(getParentActivity(), ignoreUsers);
|
||||
searchListViewAdapter = new ContactsActivitySearchAdapter(getParentActivity(), ignoreUsers, allowUsernameSearch);
|
||||
|
||||
listView = (PinnedHeaderListView)fragmentView.findViewById(R.id.listView);
|
||||
listView.setEmptyView(emptyTextView);
|
||||
@ -221,6 +224,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
|
||||
if (user == null || user.id == UserConfig.getClientUserId()) {
|
||||
return;
|
||||
}
|
||||
if (searchListViewAdapter.isGlobalSearch(i)) {
|
||||
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
|
||||
users.add(user);
|
||||
MessagesController.getInstance().putUsers(users, false);
|
||||
MessagesStorage.getInstance().putUsersAndChats(users, null, false, true);
|
||||
}
|
||||
if (returnAsResult) {
|
||||
if (ignoreUsers != null && ignoreUsers.containsKey(user.id)) {
|
||||
return;
|
||||
|
@ -31,6 +31,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.PinnedHeaderListView;
|
||||
import org.telegram.ui.Views.SectionedBaseAdapter;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
@ -484,12 +485,10 @@ public class CountrySelectActivity extends BaseFragment {
|
||||
@Override
|
||||
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
|
||||
convertView = new SettingsSectionLayout(mContext);
|
||||
convertView.setBackgroundColor(0xfffafafa);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
|
||||
textView.setText(sortedCountries.get(section).toUpperCase());
|
||||
((SettingsSectionLayout) convertView).setText(sortedCountries.get(section).toUpperCase());
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import org.telegram.ui.Views.BackupImageView;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.PinnedHeaderListView;
|
||||
import org.telegram.ui.Views.SectionedBaseAdapter;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -597,15 +598,13 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
|
||||
@Override
|
||||
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
|
||||
convertView = new SettingsSectionLayout(mContext);
|
||||
convertView.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
|
||||
if (searching && searchWas) {
|
||||
textView.setText(LocaleController.getString("AllContacts", R.string.AllContacts));
|
||||
((SettingsSectionLayout) convertView).setText(LocaleController.getString("AllContacts", R.string.AllContacts));
|
||||
} else {
|
||||
textView.setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
|
||||
((SettingsSectionLayout) convertView).setText(ContactsController.getInstance().sortedUsersSectionsArray.get(section));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import org.telegram.ui.Views.BackupImageView;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.PinnedHeaderListView;
|
||||
import org.telegram.ui.Views.SectionedBaseAdapter;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Semaphore;
|
||||
@ -81,11 +82,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
|
||||
if (!usersToLoad.isEmpty()) {
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
|
||||
final boolean[] error = new boolean[1];
|
||||
MessagesStorage.getInstance().storageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad, error));
|
||||
users.addAll(MessagesStorage.getInstance().getUsers(usersToLoad));
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
@ -94,7 +94,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
if (error[0]) {
|
||||
if (usersToLoad.size() != users.size()) {
|
||||
return false;
|
||||
}
|
||||
if (!users.isEmpty()) {
|
||||
@ -420,12 +420,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
|
||||
@Override
|
||||
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
|
||||
convertView = new SettingsSectionLayout(mContext);
|
||||
convertView.setBackgroundColor(0xffffffff);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
|
||||
textView.setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
|
||||
((SettingsSectionLayout) convertView).setText(LocaleController.formatPluralString("Members", selectedContacts.size()).toUpperCase());
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
@ -661,17 +661,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
||||
actionBarLayout.presentFragment(fragment, false, true, true);
|
||||
}
|
||||
|
||||
Bundle args2 = new Bundle();
|
||||
args2.putString("videoPath", videoPath);
|
||||
VideoEditorActivity fragment2 = new VideoEditorActivity(args2);
|
||||
fragment2.setDelegate(fragment);
|
||||
presentFragment(fragment2, true, true);
|
||||
if (!AndroidUtilities.isTablet()) {
|
||||
actionBarLayout.addFragmentToStack(fragment, actionBarLayout.fragmentsStack.size() - 1);
|
||||
}
|
||||
|
||||
if (!fragment.openVideoEditor(videoPath, true)) {
|
||||
if (!AndroidUtilities.isTablet()) {
|
||||
messageFragment.finishFragment(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actionBarLayout.presentFragment(fragment, true);
|
||||
fragment.processSendingVideo(videoPath, 0, 0, 0, 0, null);
|
||||
SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id);
|
||||
}
|
||||
} else {
|
||||
actionBarLayout.presentFragment(fragment, true);
|
||||
@ -679,10 +680,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
||||
fragment.processSendingText(sendingText);
|
||||
}
|
||||
if (photoPathsArray != null) {
|
||||
fragment.processSendingPhotos(null, photoPathsArray);
|
||||
SendMessagesHelper.prepareSendingPhotos(null, photoPathsArray, dialog_id);
|
||||
}
|
||||
if (documentsPathsArray != null) {
|
||||
fragment.processSendingDocuments(documentsPathsArray, documentsOriginalPathsArray);
|
||||
SendMessagesHelper.prepareSendingDocuments(documentsPathsArray, documentsOriginalPathsArray, dialog_id);
|
||||
}
|
||||
if (contactsToSend != null && !contactsToSend.isEmpty()) {
|
||||
for (TLRPC.User user : contactsToSend) {
|
||||
@ -786,6 +787,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
||||
|
||||
public void fixLayout() {
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
if (actionBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
actionBarLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
@ -836,6 +840,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
PhotoViewer.getInstance().destroyPhotoViewer();
|
||||
SecretPhotoViewer.getInstance().destroyPhotoViewer();
|
||||
super.onDestroy();
|
||||
onFinish();
|
||||
}
|
||||
@ -1190,7 +1195,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
||||
buttonLayoutTablet.setVisibility(View.VISIBLE);
|
||||
backgroundTablet.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (layout == layersActionBarLayout && actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
} else if (layout == layersActionBarLayout && actionBarLayout.fragmentsStack.isEmpty() && layersActionBarLayout.fragmentsStack.size() == 1) {
|
||||
onFinish();
|
||||
finish();
|
||||
return false;
|
||||
|
@ -26,7 +26,6 @@ import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
@ -55,7 +54,14 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
|
||||
v.onDestroyActivity();
|
||||
}
|
||||
}
|
||||
Utilities.HideProgressDialog(getParentActivity());
|
||||
if (progressDialog != null) {
|
||||
try {
|
||||
progressDialog.dismiss();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
progressDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -255,6 +261,7 @@ public class LoginActivity extends BaseFragment implements SlideView.SlideViewDe
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
progressDialog = null;
|
||||
}
|
||||
|
||||
public void setPage(int page, boolean animated, Bundle params, boolean back) {
|
||||
|
@ -94,7 +94,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
|
||||
@Override
|
||||
public void onItemClick(int id) {
|
||||
if (id == -1) {
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
if (Build.VERSION.SDK_INT < 11 && listView != null) {
|
||||
listView.setAdapter(null);
|
||||
listView = null;
|
||||
listAdapter = null;
|
||||
|
@ -12,6 +12,7 @@ import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@ -35,13 +36,14 @@ import org.telegram.android.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Adapters.BaseFragmentAdapter;
|
||||
import org.telegram.ui.Adapters.BaseContactsSearchAdapter;
|
||||
import org.telegram.ui.Cells.ChatOrUserCell;
|
||||
import org.telegram.ui.Cells.DialogCell;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Timer;
|
||||
@ -64,10 +66,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
private int activityToken = (int)(Utilities.random.nextDouble() * Integer.MAX_VALUE);
|
||||
private long selectedDialog;
|
||||
|
||||
private Timer searchTimer;
|
||||
public ArrayList<TLObject> searchResult;
|
||||
public ArrayList<CharSequence> searchResultNames;
|
||||
|
||||
private MessagesActivityDelegate delegate;
|
||||
|
||||
private long openedDialogId = 0;
|
||||
@ -144,7 +142,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
@Override
|
||||
public void onSearchCollapse() {
|
||||
searchDialogs(null);
|
||||
searching = false;
|
||||
searchWas = false;
|
||||
if (messagesListView != null) {
|
||||
@ -152,14 +149,16 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
searchEmptyView.setVisibility(View.GONE);
|
||||
}
|
||||
if (messagesListViewAdapter != null) {
|
||||
messagesListViewAdapter.notifyDataSetChanged();
|
||||
messagesListViewAdapter.searchDialogs(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(EditText editText) {
|
||||
String text = editText.getText().toString();
|
||||
searchDialogs(text);
|
||||
if (messagesListViewAdapter != null) {
|
||||
messagesListViewAdapter.searchDialogs(text);
|
||||
}
|
||||
if (text.length() != 0) {
|
||||
searchWas = true;
|
||||
if (messagesListViewAdapter != null) {
|
||||
@ -231,10 +230,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view);
|
||||
messagesListView.setAdapter(messagesListViewAdapter);
|
||||
if (delegate == null && AndroidUtilities.isTablet()) {
|
||||
messagesListView.setDivider(inflater.getContext().getResources().getDrawable(R.drawable.messages_list_divider2));
|
||||
messagesListView.setDividerHeight(1);
|
||||
}
|
||||
|
||||
progressView = fragmentView.findViewById(R.id.progressLayout);
|
||||
messagesListViewAdapter.notifyDataSetChanged();
|
||||
@ -277,38 +272,34 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
messagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
long dialog_id = 0;
|
||||
if (searching && searchWas) {
|
||||
if (i >= searchResult.size()) {
|
||||
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;
|
||||
}
|
||||
if (messagesListViewAdapter == null) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
didSelectResult(dialog_id, true, false);
|
||||
} else {
|
||||
@ -497,7 +488,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
} else if (id == NotificationCenter.reloadSearchResults) {
|
||||
int token = (Integer)args[0];
|
||||
if (token == activityToken) {
|
||||
updateSearchResults((ArrayList<TLObject>)args[1], (ArrayList<CharSequence>)args[2], (ArrayList<TLRPC.User>)args[3]);
|
||||
messagesListViewAdapter.updateSearchResults((ArrayList<TLObject>) args[1], (ArrayList<CharSequence>) args[2], (ArrayList<TLRPC.User>) args[3]);
|
||||
}
|
||||
} else if (id == NotificationCenter.appDidLogout) {
|
||||
dialogsLoaded = false;
|
||||
@ -624,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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
private class MessagesAdapter extends BaseContactsSearchAdapter {
|
||||
|
||||
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 Timer searchTimer;
|
||||
private ArrayList<TLObject> searchResult = new ArrayList<TLObject>();
|
||||
private ArrayList<CharSequence> searchResultNames = new ArrayList<CharSequence>();
|
||||
|
||||
public MessagesAdapter(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void updateSearchResults(final ArrayList<TLObject> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> encUsers) {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
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
|
||||
public boolean areAllItemsEnabled() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int i) {
|
||||
return true;
|
||||
return !(searching && searchWas) || i != searchResult.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (searching && searchWas) {
|
||||
if (searchResult == null) {
|
||||
return 0;
|
||||
int count = searchResult.size();
|
||||
int globalCount = globalSearch.size();
|
||||
if (globalCount != 0) {
|
||||
count += globalCount + 1;
|
||||
}
|
||||
return searchResult.size();
|
||||
return count;
|
||||
}
|
||||
int count;
|
||||
if (serverOnly) {
|
||||
@ -721,8 +739,28 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
return null;
|
||||
public TLObject getItem(int i) {
|
||||
if (searching && searchWas) {
|
||||
int localCount = searchResult.size();
|
||||
int globalCount = globalSearch.size();
|
||||
if (i >= 0 && i < localCount) {
|
||||
return searchResult.get(i);
|
||||
} else if (i > localCount && i <= globalCount + localCount) {
|
||||
return globalSearch.get(i - localCount - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (serverOnly) {
|
||||
if (i < 0 || i >= MessagesController.getInstance().dialogsServerOnly.size()) {
|
||||
return null;
|
||||
}
|
||||
return MessagesController.getInstance().dialogsServerOnly.get(i);
|
||||
} else {
|
||||
if (i < 0 || i >= MessagesController.getInstance().dialogs.size()) {
|
||||
return null;
|
||||
}
|
||||
return MessagesController.getInstance().dialogs.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -732,57 +770,86 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||
if (searching && searchWas) {
|
||||
int type = getItemViewType(i);
|
||||
|
||||
if (type == 3) {
|
||||
if (view == null) {
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
|
||||
view.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), 0);
|
||||
}
|
||||
} else if (type == 2) {
|
||||
if (view == null) {
|
||||
view = new ChatOrUserCell(mContext);
|
||||
}
|
||||
TLRPC.User user = null;
|
||||
TLRPC.Chat chat = null;
|
||||
TLRPC.EncryptedChat encryptedChat = null;
|
||||
if (searching && searchWas) {
|
||||
TLRPC.User user = null;
|
||||
TLRPC.Chat chat = null;
|
||||
TLRPC.EncryptedChat encryptedChat = null;
|
||||
|
||||
TLObject obj = searchResult.get(i);
|
||||
if (obj instanceof TLRPC.User) {
|
||||
user = MessagesController.getInstance().getUser(((TLRPC.User)obj).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);
|
||||
((ChatOrUserCell) view).useSeparator = (i != getCount() - 1 && i != searchResult.size() - 1);
|
||||
TLObject obj = getItem(i);
|
||||
if (obj instanceof TLRPC.User) {
|
||||
user = MessagesController.getInstance().getUser(((TLRPC.User) obj).id);
|
||||
if (user == null) {
|
||||
user = (TLRPC.User) obj;
|
||||
}
|
||||
} else if (obj instanceof TLRPC.Chat) {
|
||||
chat = MessagesController.getInstance().getChat(((TLRPC.Chat) obj).id);
|
||||
} else if (obj instanceof TLRPC.EncryptedChat) {
|
||||
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);
|
||||
}
|
||||
|
||||
((ChatOrUserCell)view).setData(user, chat, encryptedChat, searchResultNames.get(i), null);
|
||||
|
||||
return view;
|
||||
}
|
||||
int type = getItemViewType(i);
|
||||
if (type == 1) {
|
||||
} else if (type == 1) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
view = li.inflate(R.layout.loading_more_layout, viewGroup, false);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
if (view == null) {
|
||||
view = new DialogCell(mContext);
|
||||
}
|
||||
if (serverOnly) {
|
||||
((DialogCell)view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
|
||||
} else {
|
||||
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
if (dialog.id == openedDialogId) {
|
||||
view.setBackgroundColor(0x0f000000);
|
||||
} else {
|
||||
view.setBackgroundColor(0);
|
||||
}
|
||||
} else if (type == 0) {
|
||||
if (view == null) {
|
||||
view = new DialogCell(mContext);
|
||||
}
|
||||
((DialogCell) view).useSeparator = (i != getCount() - 1);
|
||||
if (serverOnly) {
|
||||
((DialogCell) view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
|
||||
} else {
|
||||
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
if (dialog.id == openedDialogId) {
|
||||
view.setBackgroundColor(0x0f000000);
|
||||
} else {
|
||||
view.setBackgroundColor(0);
|
||||
}
|
||||
}
|
||||
((DialogCell) view).setDialog(dialog);
|
||||
}
|
||||
((DialogCell)view).setDialog(dialog);
|
||||
}
|
||||
|
||||
return view;
|
||||
@ -791,12 +858,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
@Override
|
||||
public int getItemViewType(int i) {
|
||||
if (searching && searchWas) {
|
||||
TLObject obj = searchResult.get(i);
|
||||
if (obj instanceof TLRPC.User || obj instanceof TLRPC.EncryptedChat) {
|
||||
return 2;
|
||||
} else {
|
||||
if (i == searchResult.size()) {
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (serverOnly && i == MessagesController.getInstance().dialogsServerOnly.size() || !serverOnly && i == MessagesController.getInstance().dialogs.size()) {
|
||||
return 1;
|
||||
@ -812,7 +877,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (searching && searchWas) {
|
||||
return searchResult == null || searchResult.size() == 0;
|
||||
return searchResult.size() == 0 && globalSearch.isEmpty();
|
||||
}
|
||||
if (MessagesController.getInstance().loadingDialogs && MessagesController.getInstance().dialogs.isEmpty()) {
|
||||
return false;
|
||||
|
@ -279,6 +279,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
|
||||
int count = listView.getChildCount();
|
||||
for (int a = 0; a < count; a++) {
|
||||
View view = listView.getChildAt(a);
|
||||
if (view.getTag() == null) {
|
||||
continue;
|
||||
}
|
||||
int num = (Integer)view.getTag();
|
||||
if (num < 0 || num >= selectedAlbum.photos.size()) {
|
||||
continue;
|
||||
@ -341,7 +344,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
|
||||
@Override
|
||||
public void sendButtonPressed(int index) {
|
||||
if (selectedPhotos.isEmpty()) {
|
||||
if (index < 0 || index >= selectedAlbum.photos.size()) {
|
||||
if (selectedAlbum == null || index < 0 || index >= selectedAlbum.photos.size()) {
|
||||
return;
|
||||
}
|
||||
MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index);
|
||||
|
@ -101,6 +101,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
private View pickerView;
|
||||
private TextView doneButtonTextView;
|
||||
private TextView doneButtonBadgeTextView;
|
||||
private ImageView shareButton;
|
||||
private boolean canShowBottom = true;
|
||||
private boolean overlayViewVisible = true;
|
||||
|
||||
@ -234,7 +235,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
public int getSelectedCount();
|
||||
}
|
||||
|
||||
private static class FrameLayoutTouchListener extends FrameLayout {
|
||||
private class FrameLayoutTouchListener extends FrameLayout {
|
||||
public FrameLayoutTouchListener(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@ -251,7 +252,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
}
|
||||
}
|
||||
|
||||
private static class FrameLayoutDrawer extends FrameLayout {
|
||||
private class FrameLayoutDrawer extends FrameLayout {
|
||||
public FrameLayoutDrawer(Context context) {
|
||||
super(context);
|
||||
setWillNotDraw(false);
|
||||
@ -595,7 +596,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
bottomLayout.setLayoutParams(layoutParams);
|
||||
bottomLayout.setBackgroundColor(0x7F000000);
|
||||
|
||||
ImageView shareButton = new ImageView(containerView.getContext());
|
||||
shareButton = new ImageView(containerView.getContext());
|
||||
shareButton.setImageResource(R.drawable.ic_ab_share_white);
|
||||
shareButton.setScaleType(ImageView.ScaleType.CENTER);
|
||||
shareButton.setBackgroundResource(R.drawable.bar_selector_white);
|
||||
@ -611,12 +612,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int size[] = new int[1];
|
||||
TLRPC.FileLocation fileLocation = getFileLocation(currentIndex, size);
|
||||
if (fileLocation == null) {
|
||||
return;
|
||||
File f = null;
|
||||
|
||||
if (currentMessageObject != null) {
|
||||
f = FileLoader.getPathToMessage(currentMessageObject.messageOwner);
|
||||
} else if (currentFileLocation != null) {
|
||||
f = FileLoader.getPathToAttach(currentFileLocation, avatarsUserId != 0);
|
||||
}
|
||||
File f = FileLoader.getPathToAttach(fileLocation, avatarsUserId != 0);
|
||||
|
||||
if (f.exists()) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
if (f.toString().endsWith("mp4")) {
|
||||
@ -654,7 +657,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
if (obj.isSent()) {
|
||||
ArrayList<Integer> arr = new ArrayList<Integer>();
|
||||
arr.add(obj.messageOwner.id);
|
||||
MessagesController.getInstance().deleteMessages(arr, null, null);
|
||||
|
||||
ArrayList<Long> random_ids = null;
|
||||
TLRPC.EncryptedChat encryptedChat = null;
|
||||
if ((int)obj.getDialogId() == 0 && obj.messageOwner.random_id != 0) {
|
||||
random_ids = new ArrayList<Long>();
|
||||
random_ids.add(obj.messageOwner.random_id);
|
||||
encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(obj.getDialogId() >> 32));
|
||||
}
|
||||
|
||||
MessagesController.getInstance().deleteMessages(arr, random_ids, encryptedChat);
|
||||
closePhoto(false);
|
||||
}
|
||||
} else if (!avatarsArr.isEmpty()) {
|
||||
@ -1157,6 +1169,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
} else {
|
||||
menuItem.hideSubItem(gallery_menu_showall);
|
||||
}
|
||||
if ((int) currentDialogId == 0) {
|
||||
menuItem.hideSubItem(gallery_menu_save);
|
||||
shareButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
menuItem.showSubItem(gallery_menu_save);
|
||||
shareButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
setImageIndex(0, true);
|
||||
} else if (fileLocation != null) {
|
||||
avatarsUserId = object.user_id;
|
||||
@ -1164,6 +1183,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
imagesArrLocationsSizes.add(object.size);
|
||||
avatarsArr.add(new TLRPC.TL_photoEmpty());
|
||||
bottomLayout.setVisibility(View.GONE);
|
||||
shareButton.setVisibility(View.VISIBLE);
|
||||
menuItem.hideSubItem(gallery_menu_showall);
|
||||
setImageIndex(0, true);
|
||||
currentUserAvatarLocation = fileLocation;
|
||||
@ -1192,6 +1212,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((int) currentDialogId == 0) {
|
||||
menuItem.hideSubItem(gallery_menu_save);
|
||||
shareButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
menuItem.showSubItem(gallery_menu_save);
|
||||
shareButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
opennedFromMedia = true;
|
||||
setImageIndex(index, true);
|
||||
} else if (photos != null) {
|
||||
@ -1201,6 +1228,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
setImageIndex(index, true);
|
||||
pickerView.setVisibility(View.VISIBLE);
|
||||
bottomLayout.setVisibility(View.GONE);
|
||||
shareButton.setVisibility(View.VISIBLE);
|
||||
canShowBottom = false;
|
||||
updateSelectedCount();
|
||||
}
|
||||
@ -2138,7 +2166,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
float ai = -1;
|
||||
if (System.currentTimeMillis() - animationStartTime < animationDuration) {
|
||||
ai = interpolator.getInterpolation((float)(System.currentTimeMillis() - animationStartTime) / animationDuration);
|
||||
if (ai >= 0.95) {
|
||||
if (ai >= 0.95f) {
|
||||
ai = -1;
|
||||
}
|
||||
}
|
||||
@ -2219,7 +2247,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
int height = (int) (bitmapHeight * scale);
|
||||
|
||||
centerImage.setImageCoords(-width / 2, -height / 2, width, height);
|
||||
centerImage.draw(canvas, -width / 2, -height / 2, width, height);
|
||||
centerImage.draw(canvas);
|
||||
}
|
||||
|
||||
if (scale >= 1.0f) {
|
||||
@ -2250,7 +2278,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
||||
int height = (int) (bitmapHeight * scale);
|
||||
|
||||
sideImage.setImageCoords(-width / 2, -height / 2, width, height);
|
||||
sideImage.draw(canvas, -width / 2, -height / 2, width, height);
|
||||
sideImage.draw(canvas);
|
||||
}
|
||||
} else {
|
||||
changingPage = false;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -59,6 +59,8 @@ import org.telegram.ui.Views.ActionBar.ActionBarLayer;
|
||||
import org.telegram.ui.Views.AvatarUpdater;
|
||||
import org.telegram.ui.Views.BackupImageView;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.NumberPicker;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@ -72,6 +74,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
private int profileRow;
|
||||
private int numberSectionRow;
|
||||
private int numberRow;
|
||||
private int usernameRow;
|
||||
private int settingsSectionRow;
|
||||
private int textSizeRow;
|
||||
private int enableAnimationsRow;
|
||||
@ -178,6 +181,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
profileRow = rowCount++;
|
||||
numberSectionRow = rowCount++;
|
||||
numberRow = rowCount++;
|
||||
usernameRow = rowCount++;
|
||||
settingsSectionRow = rowCount++;
|
||||
enableAnimationsRow = rowCount++;
|
||||
languageRow = rowCount++;
|
||||
@ -207,12 +211,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
logoutRow = rowCount++;
|
||||
versionRow = rowCount++;
|
||||
|
||||
MessagesController.getInstance().loadFullUser(UserConfig.getCurrentUser(), classGuid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentDestroy() {
|
||||
super.onFragmentDestroy();
|
||||
MessagesController.getInstance().cancelLoadFullUser(UserConfig.getClientUserId());
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces);
|
||||
avatarUpdater.clear();
|
||||
}
|
||||
@ -245,39 +252,24 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setTitle(LocaleController.getString("TextSize", R.string.TextSize));
|
||||
builder.setItems(new CharSequence[] {
|
||||
String.format("%d", 12),
|
||||
String.format("%d", 13),
|
||||
String.format("%d", 14),
|
||||
String.format("%d", 15),
|
||||
String.format("%d", 16),
|
||||
String.format("%d", 17),
|
||||
String.format("%d", 18),
|
||||
String.format("%d", 19),
|
||||
String.format("%d", 20),
|
||||
String.format("%d", 21),
|
||||
String.format("%d", 22),
|
||||
String.format("%d", 23),
|
||||
String.format("%d", 24),
|
||||
String.format("%d", 25),
|
||||
String.format("%d", 26),
|
||||
String.format("%d", 27),
|
||||
String.format("%d", 28),
|
||||
String.format("%d", 29),
|
||||
String.format("%d", 30)}, new DialogInterface.OnClickListener() {
|
||||
final NumberPicker numberPicker = new NumberPicker(getParentActivity());
|
||||
numberPicker.setMinValue(12);
|
||||
numberPicker.setMaxValue(30);
|
||||
numberPicker.setValue(MessagesController.getInstance().fontSize);
|
||||
builder.setView(numberPicker);
|
||||
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("fons_size", 12 + which);
|
||||
MessagesController.getInstance().fontSize = 12 + which;
|
||||
editor.putInt("fons_size", numberPicker.getValue());
|
||||
MessagesController.getInstance().fontSize = numberPicker.getValue();
|
||||
editor.commit();
|
||||
if (listView != null) {
|
||||
listView.invalidateViews();
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||
showAlertDialog(builder);
|
||||
} else if (i == enableAnimationsRow) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
@ -491,6 +483,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
showAlertDialog(builder);
|
||||
} else if (i == usernameRow) {
|
||||
presentFragment(new SettingsChangeUsernameActivity());
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -723,7 +717,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
public boolean isEnabled(int i) {
|
||||
return i == textSizeRow || i == enableAnimationsRow || i == blockedRow || i == notificationRow || i == backgroundRow ||
|
||||
i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == terminateSessionsRow || i == wifiDownloadRow ||
|
||||
i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow ||
|
||||
i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow || i == usernameRow ||
|
||||
i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow;
|
||||
}
|
||||
|
||||
@ -838,22 +832,20 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
return view;
|
||||
} else if (type == 1) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
}
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
|
||||
if (i == numberSectionRow) {
|
||||
textView.setText(LocaleController.getString("YourPhoneNumber", R.string.YourPhoneNumber));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Info", R.string.Info));
|
||||
} else if (i == settingsSectionRow) {
|
||||
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
} else if (i == supportSectionRow) {
|
||||
textView.setText(LocaleController.getString("Support", R.string.Support));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Support", R.string.Support));
|
||||
} else if (i == messagesSectionRow) {
|
||||
textView.setText(LocaleController.getString("MessagesSettings", R.string.MessagesSettings));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("MessagesSettings", R.string.MessagesSettings));
|
||||
} else if (i == mediaDownloadSection) {
|
||||
textView.setText(LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload));
|
||||
} else if (i == contactsSectionRow) {
|
||||
textView.setText(LocaleController.getString("Contacts", R.string.Contacts).toUpperCase());
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Contacts", R.string.Contacts).toUpperCase());
|
||||
}
|
||||
} else if (type == 2) {
|
||||
if (view == null) {
|
||||
@ -862,15 +854,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
}
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
|
||||
View divider = view.findViewById(R.id.settings_row_divider);
|
||||
if (i == numberRow) {
|
||||
TLRPC.User user = UserConfig.getCurrentUser();
|
||||
if (user != null && user.phone != null && user.phone.length() != 0) {
|
||||
textView.setText(PhoneFormat.getInstance().format("+" + user.phone));
|
||||
} else {
|
||||
textView.setText("Unknown");
|
||||
}
|
||||
divider.setVisibility(View.INVISIBLE);
|
||||
} else if (i == notificationRow) {
|
||||
if (i == notificationRow) {
|
||||
textView.setText(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds));
|
||||
divider.setVisibility(View.VISIBLE);
|
||||
} else if (i == blockedRow) {
|
||||
@ -980,7 +964,16 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
|
||||
TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail);
|
||||
View divider = view.findViewById(R.id.settings_row_divider);
|
||||
if (i == textSizeRow) {
|
||||
if (i == numberRow) {
|
||||
TLRPC.User user = UserConfig.getCurrentUser();
|
||||
textView.setText(LocaleController.getString("Phone", R.string.Phone));
|
||||
if (user != null && user.phone != null && user.phone.length() != 0) {
|
||||
detailTextView.setText(PhoneFormat.getInstance().format("+" + user.phone));
|
||||
} else {
|
||||
detailTextView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
|
||||
}
|
||||
divider.setVisibility(View.VISIBLE);
|
||||
} else if (i == textSizeRow) {
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
||||
detailTextView.setText(String.format("%d", size));
|
||||
@ -1002,6 +995,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
} else if (sort == 2) {
|
||||
detailTextView.setText(LocaleController.getString("LastName", R.string.SortLastName));
|
||||
}
|
||||
} else if (i == usernameRow) {
|
||||
TLRPC.User user = UserConfig.getCurrentUser();
|
||||
textView.setText(LocaleController.getString("Username", R.string.Username));
|
||||
if (user != null && user.username != null && user.username.length() != 0) {
|
||||
detailTextView.setText("@" + user.username);
|
||||
} else {
|
||||
detailTextView.setText(LocaleController.getString("UsernameEmpty", R.string.UsernameEmpty));
|
||||
}
|
||||
divider.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else if (type == 6) {
|
||||
if (view == null) {
|
||||
@ -1075,11 +1077,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
||||
return 0;
|
||||
} else if (i == numberSectionRow || i == settingsSectionRow || i == supportSectionRow || i == messagesSectionRow || i == mediaDownloadSection || i == contactsSectionRow) {
|
||||
return 1;
|
||||
} else if (i == textSizeRow || i == languageRow || i == contactsSortRow) {
|
||||
} else if (i == textSizeRow || i == languageRow || i == contactsSortRow || i == numberRow || i == usernameRow) {
|
||||
return 5;
|
||||
} else if (i == enableAnimationsRow || i == sendByEnterRow || i == saveToGalleryRow) {
|
||||
return 3;
|
||||
} else if (i == numberRow || i == notificationRow || i == blockedRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == terminateSessionsRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow) {
|
||||
} else if (i == notificationRow || i == blockedRow || i == backgroundRow || i == askQuestionRow || i == sendLogsRow || i == terminateSessionsRow || i == clearLogsRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsReimportRow) {
|
||||
return 2;
|
||||
} else if (i == logoutRow) {
|
||||
return 4;
|
||||
|
@ -249,7 +249,7 @@ public class SettingsBlockedUsersActivity extends BaseFragment implements Notifi
|
||||
((ChatOrUserCell)view).useSeparator = true;
|
||||
}
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(MessagesController.getInstance().blockedUsers.get(i));
|
||||
((ChatOrUserCell)view).setData(user, null, null, null, user.phone != null && user.phone.length() != 0 ? PhoneFormat.getInstance().format("+" + user.phone) : "Unknown");
|
||||
((ChatOrUserCell)view).setData(user, null, null, null, user.phone != null && user.phone.length() != 0 ? PhoneFormat.getInstance().format("+" + user.phone) : LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
|
||||
} else if (type == 1) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
@ -10,6 +10,9 @@ package org.telegram.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.InputType;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -17,6 +20,7 @@ import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
@ -30,6 +34,7 @@ import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.RPCRequest;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
public class SettingsChangeNameActivity extends BaseFragment {
|
||||
private EditText firstNameField;
|
||||
@ -63,14 +68,31 @@ public class SettingsChangeNameActivity extends BaseFragment {
|
||||
TextView textView = (TextView)doneButton.findViewById(R.id.done_button_text);
|
||||
textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
|
||||
|
||||
fragmentView = inflater.inflate(R.layout.settings_change_name_layout, container, false);
|
||||
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
|
||||
if (user == null) {
|
||||
user = UserConfig.getCurrentUser();
|
||||
}
|
||||
|
||||
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field);
|
||||
fragmentView = new LinearLayout(inflater.getContext());
|
||||
fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
fragmentView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), 0);
|
||||
((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
SettingsSectionLayout settingsSectionLayout = new SettingsSectionLayout(inflater.getContext());
|
||||
((LinearLayout) fragmentView).addView(settingsSectionLayout);
|
||||
settingsSectionLayout.setText(LocaleController.getString("YourFirstNameAndLastName", R.string.YourFirstNameAndLastName).toUpperCase());
|
||||
|
||||
firstNameField = new EditText(inflater.getContext());
|
||||
firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
|
||||
firstNameField.setHintTextColor(0xffa3a3a3);
|
||||
firstNameField.setTextColor(0xff000000);
|
||||
firstNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
|
||||
firstNameField.setMaxLines(1);
|
||||
firstNameField.setLines(1);
|
||||
firstNameField.setSingleLine(true);
|
||||
firstNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
|
||||
firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName));
|
||||
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
@ -83,7 +105,25 @@ public class SettingsChangeNameActivity extends BaseFragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
lastNameField = (EditText)fragmentView.findViewById(R.id.last_name_field);
|
||||
AndroidUtilities.clearCursorDrawable(firstNameField);
|
||||
((LinearLayout) fragmentView).addView(firstNameField);
|
||||
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)firstNameField.getLayoutParams();
|
||||
layoutParams.topMargin = AndroidUtilities.dp(15);
|
||||
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
firstNameField.setLayoutParams(layoutParams);
|
||||
|
||||
lastNameField = new EditText(inflater.getContext());
|
||||
lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 19);
|
||||
lastNameField.setHintTextColor(0xffa3a3a3);
|
||||
lastNameField.setTextColor(0xff000000);
|
||||
lastNameField.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15));
|
||||
lastNameField.setMaxLines(1);
|
||||
lastNameField.setLines(1);
|
||||
lastNameField.setSingleLine(true);
|
||||
lastNameField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
lastNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
|
||||
lastNameField.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
lastNameField.setHint(LocaleController.getString("LastName", R.string.LastName));
|
||||
lastNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
@ -95,15 +135,19 @@ public class SettingsChangeNameActivity extends BaseFragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
AndroidUtilities.clearCursorDrawable(lastNameField);
|
||||
((LinearLayout) fragmentView).addView(lastNameField);
|
||||
layoutParams = (LinearLayout.LayoutParams)lastNameField.getLayoutParams();
|
||||
layoutParams.topMargin = AndroidUtilities.dp(10);
|
||||
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
lastNameField.setLayoutParams(layoutParams);
|
||||
|
||||
if (user != null) {
|
||||
firstNameField.setText(user.first_name);
|
||||
firstNameField.setSelection(firstNameField.length());
|
||||
lastNameField.setText(user.last_name);
|
||||
}
|
||||
|
||||
TextView headerLabel = (TextView)fragmentView.findViewById(R.id.settings_section_text);
|
||||
headerLabel.setText(LocaleController.getString("YourFirstNameAndLastName", R.string.YourFirstNameAndLastName));
|
||||
} else {
|
||||
ViewGroup parent = (ViewGroup)fragmentView.getParent();
|
||||
if (parent != null) {
|
||||
@ -125,12 +169,18 @@ public class SettingsChangeNameActivity extends BaseFragment {
|
||||
}
|
||||
|
||||
private void saveName() {
|
||||
TLRPC.TL_account_updateProfile req = new TLRPC.TL_account_updateProfile();
|
||||
if (UserConfig.getCurrentUser() == null || lastNameField.getText() == null || firstNameField.getText() == null) {
|
||||
TLRPC.User currentUser = UserConfig.getCurrentUser();
|
||||
if (currentUser == null || lastNameField.getText() == null || firstNameField.getText() == null) {
|
||||
return;
|
||||
}
|
||||
UserConfig.getCurrentUser().first_name = req.first_name = firstNameField.getText().toString();
|
||||
UserConfig.getCurrentUser().last_name = req.last_name = lastNameField.getText().toString();
|
||||
String newFirst = firstNameField.getText().toString();
|
||||
String newLast = lastNameField.getText().toString();
|
||||
if (currentUser.first_name != null && currentUser.first_name.equals(newFirst) && currentUser.last_name != null && currentUser.last_name.equals(newLast)) {
|
||||
return;
|
||||
}
|
||||
TLRPC.TL_account_updateProfile req = new TLRPC.TL_account_updateProfile();
|
||||
currentUser.first_name = req.first_name = newFirst;
|
||||
currentUser.last_name = req.last_name = newLast;
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId());
|
||||
if (user != null) {
|
||||
user.first_name = req.first_name;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@ import org.telegram.ui.Adapters.BaseFragmentAdapter;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.ColorPickerView;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
public class SettingsNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
private ListView listView;
|
||||
@ -541,22 +542,20 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
|
||||
int type = getItemViewType(i);
|
||||
if (type == 0) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
}
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
|
||||
if (i == messageSectionRow) {
|
||||
textView.setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("MessageNotifications", R.string.MessageNotifications));
|
||||
} else if (i == groupSectionRow) {
|
||||
textView.setText(LocaleController.getString("GroupNotifications", R.string.GroupNotifications));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("GroupNotifications", R.string.GroupNotifications));
|
||||
} else if (i == inappSectionRow) {
|
||||
textView.setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications));
|
||||
} else if (i == eventsSectionRow) {
|
||||
textView.setText(LocaleController.getString("Events", R.string.Events));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Events", R.string.Events));
|
||||
} else if (i == otherSectionRow) {
|
||||
textView.setText(LocaleController.getString("PhoneOther", R.string.PhoneOther));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("PhoneOther", R.string.PhoneOther));
|
||||
} else if (i == resetSectionRow) {
|
||||
textView.setText(LocaleController.getString("Reset", R.string.Reset));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Reset", R.string.Reset));
|
||||
}
|
||||
} if (type == 1) {
|
||||
if (view == null) {
|
||||
|
@ -31,7 +31,6 @@ import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.android.ContactsController;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.android.MessagesController;
|
||||
import org.telegram.android.MessagesStorage;
|
||||
import org.telegram.android.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.android.MessageObject;
|
||||
@ -42,6 +41,7 @@ import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.Views.BackupImageView;
|
||||
import org.telegram.ui.Views.ActionBar.BaseFragment;
|
||||
import org.telegram.ui.Views.IdenticonView;
|
||||
import org.telegram.ui.Views.SettingsSectionLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -64,6 +64,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
private int avatarRow;
|
||||
private int phoneSectionRow;
|
||||
private int phoneRow;
|
||||
private int usernameRow;
|
||||
private int settingsSectionRow;
|
||||
private int settingsTimerRow;
|
||||
private int settingsKeyRow;
|
||||
@ -94,6 +95,9 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded);
|
||||
userBlocked = MessagesController.getInstance().blockedUsers.contains(user_id);
|
||||
|
||||
MessagesController.getInstance().loadFullUser(MessagesController.getInstance().getUser(user_id), classGuid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -106,6 +110,8 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatCreated);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatUpdated);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.blockedUsersDidLoaded);
|
||||
|
||||
MessagesController.getInstance().cancelLoadFullUser(user_id);
|
||||
}
|
||||
|
||||
private void updateRowsIds() {
|
||||
@ -113,6 +119,12 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
avatarRow = rowCount++;
|
||||
phoneSectionRow = rowCount++;
|
||||
phoneRow = rowCount++;
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(user_id);
|
||||
if (user != null && user.username != null && user.username.length() > 0) {
|
||||
usernameRow = rowCount++;
|
||||
} else {
|
||||
usernameRow = -1;
|
||||
}
|
||||
settingsSectionRow = rowCount++;
|
||||
if (currentEncryptedChat instanceof TLRPC.TL_encryptedChat) {
|
||||
settingsTimerRow = rowCount++;
|
||||
@ -256,47 +268,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
|
||||
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
|
||||
builder.setItems(new CharSequence[]{
|
||||
LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever),
|
||||
LocaleController.getString("ShortMessageLifetime2s", R.string.ShortMessageLifetime2s),
|
||||
LocaleController.getString("ShortMessageLifetime5s", R.string.ShortMessageLifetime5s),
|
||||
LocaleController.getString("ShortMessageLifetime1m", R.string.ShortMessageLifetime1m),
|
||||
LocaleController.getString("ShortMessageLifetime1h", R.string.ShortMessageLifetime1h),
|
||||
LocaleController.getString("ShortMessageLifetime1d", R.string.ShortMessageLifetime1d),
|
||||
LocaleController.getString("ShortMessageLifetime1w", R.string.ShortMessageLifetime1w)
|
||||
|
||||
}, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int oldValue = currentEncryptedChat.ttl;
|
||||
if (which == 0) {
|
||||
currentEncryptedChat.ttl = 0;
|
||||
} else if (which == 1) {
|
||||
currentEncryptedChat.ttl = 2;
|
||||
} else if (which == 2) {
|
||||
currentEncryptedChat.ttl = 5;
|
||||
} else if (which == 3) {
|
||||
currentEncryptedChat.ttl = 60;
|
||||
} else if (which == 4) {
|
||||
currentEncryptedChat.ttl = 60 * 60;
|
||||
} else if (which == 5) {
|
||||
currentEncryptedChat.ttl = 60 * 60 * 24;
|
||||
} else if (which == 6) {
|
||||
currentEncryptedChat.ttl = 60 * 60 * 24 * 7;
|
||||
}
|
||||
if (oldValue != currentEncryptedChat.ttl) {
|
||||
if (listView != null) {
|
||||
listView.invalidateViews();
|
||||
}
|
||||
SendMessagesHelper.getInstance().sendTTLMessage(currentEncryptedChat);
|
||||
MessagesStorage.getInstance().updateEncryptedChat(currentEncryptedChat);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||
showAlertDialog(builder);
|
||||
showAlertDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat));
|
||||
} else if (i == settingsNotificationsRow) {
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("dialog_id", dialog_id == 0 ? user_id : dialog_id);
|
||||
@ -318,10 +290,11 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
return fragmentView;
|
||||
}
|
||||
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
public void didReceivedNotification(int id, final Object... args) {
|
||||
if (id == NotificationCenter.updateInterfaces) {
|
||||
int mask = (Integer)args[0];
|
||||
if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_NAME) != 0) {
|
||||
updateRowsIds();
|
||||
if (listView != null) {
|
||||
listView.invalidateViews();
|
||||
}
|
||||
@ -338,11 +311,16 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
}
|
||||
} else if (id == NotificationCenter.encryptedChatCreated) {
|
||||
if (creatingChat) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
|
||||
TLRPC.EncryptedChat encryptedChat = (TLRPC.EncryptedChat)args[0];
|
||||
Bundle args2 = new Bundle();
|
||||
args2.putInt("enc_id", encryptedChat.id);
|
||||
presentFragment(new ChatActivity(args2), true);
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
|
||||
TLRPC.EncryptedChat encryptedChat = (TLRPC.EncryptedChat)args[0];
|
||||
Bundle args2 = new Bundle();
|
||||
args2.putInt("enc_id", encryptedChat.id);
|
||||
presentFragment(new ChatActivity(args2), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (id == NotificationCenter.encryptedChatUpdated) {
|
||||
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat)args[0];
|
||||
@ -449,6 +427,13 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogDismiss() {
|
||||
if (listView != null) {
|
||||
listView.invalidateViews();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) {
|
||||
if (dialog_id != 0) {
|
||||
@ -555,16 +540,14 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
return view;
|
||||
} else if (type == 1) {
|
||||
if (view == null) {
|
||||
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
view = li.inflate(R.layout.settings_section_layout, viewGroup, false);
|
||||
view = new SettingsSectionLayout(mContext);
|
||||
}
|
||||
TextView textView = (TextView)view.findViewById(R.id.settings_section_text);
|
||||
if (i == phoneSectionRow) {
|
||||
textView.setText(LocaleController.getString("PHONE", R.string.PHONE));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("Info", R.string.Info));
|
||||
} else if (i == settingsSectionRow) {
|
||||
textView.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("SETTINGS", R.string.SETTINGS));
|
||||
} else if (i == sharedMediaSectionRow) {
|
||||
textView.setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
|
||||
((SettingsSectionLayout) view).setText(LocaleController.getString("SHAREDMEDIA", R.string.SHAREDMEDIA));
|
||||
}
|
||||
} else if (type == 2) {
|
||||
final TLRPC.User user = MessagesController.getInstance().getUser(user_id);
|
||||
@ -637,9 +620,9 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
if (user.phone != null && user.phone.length() != 0) {
|
||||
textView.setText(PhoneFormat.getInstance().format("+" + user.phone));
|
||||
} else {
|
||||
textView.setText("Unknown");
|
||||
textView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
|
||||
}
|
||||
divider.setVisibility(View.INVISIBLE);
|
||||
divider.setVisibility(usernameRow != -1 ? View.VISIBLE : View.INVISIBLE);
|
||||
detailTextView.setText(LocaleController.getString("PhoneMobile", R.string.PhoneMobile));
|
||||
}
|
||||
} else if (type == 3) {
|
||||
@ -665,21 +648,18 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
divider.setVisibility(View.VISIBLE);
|
||||
if (encryptedChat.ttl == 0) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever));
|
||||
} else if (encryptedChat.ttl == 2) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime2s", R.string.ShortMessageLifetime2s));
|
||||
} else if (encryptedChat.ttl == 5) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime5s", R.string.ShortMessageLifetime5s));
|
||||
} else if (encryptedChat.ttl == 60) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1m", R.string.ShortMessageLifetime1m));
|
||||
} else if (encryptedChat.ttl == 60 * 60) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1h", R.string.ShortMessageLifetime1h));
|
||||
} else if (encryptedChat.ttl == 60 * 60 * 24) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1d", R.string.ShortMessageLifetime1d));
|
||||
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
|
||||
detailTextView.setText(LocaleController.getString("ShortMessageLifetime1w", R.string.ShortMessageLifetime1w));
|
||||
} else {
|
||||
detailTextView.setText(String.format("%d", encryptedChat.ttl));
|
||||
detailTextView.setText(AndroidUtilities.formatTTLString(encryptedChat.ttl));
|
||||
}
|
||||
} else if (i == usernameRow) {
|
||||
TLRPC.User user = MessagesController.getInstance().getUser(user_id);
|
||||
textView.setText(LocaleController.getString("Username", R.string.Username));
|
||||
if (user != null && user.username != null && user.username.length() != 0) {
|
||||
detailTextView.setText("@" + user.username);
|
||||
} else {
|
||||
detailTextView.setText("-");
|
||||
}
|
||||
divider.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else if (type == 4) {
|
||||
if (view == null) {
|
||||
@ -716,7 +696,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
|
||||
return 1;
|
||||
} else if (i == phoneRow) {
|
||||
return 2;
|
||||
} else if (i == sharedMediaRow || i == settingsTimerRow) {
|
||||
} else if (i == sharedMediaRow || i == settingsTimerRow || i == usernameRow) {
|
||||
return 3;
|
||||
} else if (i == settingsKeyRow) {
|
||||
return 4;
|
||||
|
@ -58,6 +58,7 @@ import java.util.List;
|
||||
@TargetApi(16)
|
||||
public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener {
|
||||
|
||||
private boolean created = false;
|
||||
private MediaPlayer videoPlayer = null;
|
||||
private VideoTimelineView videoTimelineView = null;
|
||||
private View videoContainerView = null;
|
||||
@ -161,6 +162,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
||||
|
||||
@Override
|
||||
public boolean onFragmentCreate() {
|
||||
if (created) {
|
||||
return true;
|
||||
}
|
||||
if (videoPath == null || !processOpenVideo()) {
|
||||
return false;
|
||||
}
|
||||
@ -191,6 +195,8 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
||||
return false;
|
||||
}
|
||||
|
||||
created = true;
|
||||
|
||||
return super.onFragmentCreate();
|
||||
}
|
||||
|
||||
@ -276,22 +282,27 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
MediaCodecInfo codecInfo = MediaController.selectCodec(MediaController.MIME_TYPE);
|
||||
if (codecInfo == null) {
|
||||
compressVideo.setVisibility(View.GONE);
|
||||
} 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")) {
|
||||
try {
|
||||
MediaCodecInfo codecInfo = MediaController.selectCodec(MediaController.MIME_TYPE);
|
||||
if (codecInfo == null) {
|
||||
compressVideo.setVisibility(View.GONE);
|
||||
} 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);
|
||||
} 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() {
|
||||
playButton.setImageResource(R.drawable.video_play);
|
||||
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
|
||||
if (playButton != null) {
|
||||
playButton.setImageResource(R.drawable.video_play);
|
||||
}
|
||||
if (videoSeekBarView != null && videoTimelineView != null) {
|
||||
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
|
||||
}
|
||||
try {
|
||||
if (videoPlayer != null) {
|
||||
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
|
||||
if (videoTimelineView != null) {
|
||||
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
|
@ -171,9 +171,9 @@ public class ActionBarLayer extends FrameLayout {
|
||||
x = AndroidUtilities.dp(16 + leftMargin);
|
||||
} else {
|
||||
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
x = AndroidUtilities.dp(22 + leftMargin) + (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f);
|
||||
x = AndroidUtilities.dp(22 + leftMargin) + (logoImageView.getDrawable() != null ? (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f) : 0);
|
||||
} else {
|
||||
x = AndroidUtilities.dp(22 + leftMargin) + logoImageView.getDrawable().getIntrinsicWidth();
|
||||
x = AndroidUtilities.dp(22 + leftMargin) + (logoImageView.getDrawable() != null ? logoImageView.getDrawable().getIntrinsicWidth() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,11 @@ public class BaseFragment {
|
||||
if (fragmentView != null) {
|
||||
ViewGroup parent = (ViewGroup) fragmentView.getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(fragmentView);
|
||||
try {
|
||||
parent.removeView(fragmentView);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
fragmentView = null;
|
||||
}
|
||||
|
@ -91,6 +91,6 @@ public class BackupImageView extends View {
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
imageReceiver.setImageCoords(0, 0, getWidth(), getHeight());
|
||||
imageReceiver.draw(canvas, 0, 0, getWidth(), getHeight());
|
||||
imageReceiver.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
@ -597,24 +597,22 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
|
||||
messsageEditText.dispatchKeyEvent(new KeyEvent(0, 67));
|
||||
}
|
||||
|
||||
public void onEmojiSelected(String paramAnonymousString) {
|
||||
public void onEmojiSelected(String symbol) {
|
||||
int i = messsageEditText.getSelectionEnd();
|
||||
CharSequence localCharSequence = Emoji.replaceEmoji(paramAnonymousString, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
|
||||
messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence));
|
||||
int j = i + localCharSequence.length();
|
||||
messsageEditText.setSelection(j, j);
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
try {
|
||||
CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
|
||||
messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence));
|
||||
int j = i + localCharSequence.length();
|
||||
messsageEditText.setSelection(j, j);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
emojiPopup = new PopupWindow(emojiView);
|
||||
|
||||
/*try {
|
||||
Method method = emojiPopup.getClass().getMethod("setWindowLayoutType", int.class);
|
||||
if (method != null) {
|
||||
method.invoke(emojiPopup, WindowManager.LayoutParams.LAST_SUB_WINDOW);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//don't promt
|
||||
}*/
|
||||
}
|
||||
|
||||
public void setDelegate(ChatActivityEnterViewDelegate delegate) {
|
||||
|
@ -23,8 +23,6 @@ import android.widget.AdapterView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import org.telegram.messenger.R;
|
||||
|
||||
public class HorizontalListView extends AdapterView<ListAdapter> {
|
||||
|
||||
public boolean mAlwaysOverrideTouch = true;
|
||||
@ -209,7 +207,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
|
||||
v = list.poll();
|
||||
}
|
||||
View child = mAdapter.getView(mRightViewIndex, v, this);
|
||||
child.setTag(R.string.CacheTag, type);
|
||||
child.setTag(type);
|
||||
|
||||
addAndMeasureChild(child, -1);
|
||||
rightEdge += child.getMeasuredWidth();
|
||||
@ -236,7 +234,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
|
||||
v = list.poll();
|
||||
}
|
||||
View child = mAdapter.getView(mLeftViewIndex, v, this);
|
||||
child.setTag(R.string.CacheTag, type);
|
||||
child.setTag(type);
|
||||
|
||||
addAndMeasureChild(child, 0);
|
||||
leftEdge -= child.getMeasuredWidth();
|
||||
@ -250,7 +248,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
|
||||
while (child != null && child.getRight() + dx <= 0) {
|
||||
mDisplayOffset += child.getMeasuredWidth();
|
||||
|
||||
int type = (Integer) child.getTag(R.string.CacheTag);
|
||||
int type = (Integer) child.getTag();
|
||||
LinkedList<View> list = mRemovedViewQueue.get(type);
|
||||
if (list == null) {
|
||||
list = new LinkedList<View>();
|
||||
@ -265,7 +263,7 @@ public class HorizontalListView extends AdapterView<ListAdapter> {
|
||||
|
||||
child = getChildAt(getChildCount() - 1);
|
||||
while (child != null && child.getLeft() + dx >= getWidth()) {
|
||||
int type = (Integer) child.getTag(R.string.CacheTag);
|
||||
int type = (Integer) child.getTag();
|
||||
LinkedList<View> list = mRemovedViewQueue.get(type);
|
||||
if (list == null) {
|
||||
list = new LinkedList<View>();
|
||||
|
@ -10,11 +10,17 @@ package org.telegram.ui.Views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class LayoutListView extends ListView {
|
||||
|
||||
public static interface OnInterceptTouchEventListener {
|
||||
public abstract boolean onInterceptTouchEvent(MotionEvent event);
|
||||
}
|
||||
|
||||
private OnInterceptTouchEventListener onInterceptTouchEventListener;
|
||||
private int height = -1;
|
||||
|
||||
public LayoutListView(Context context) {
|
||||
@ -29,6 +35,18 @@ public class LayoutListView extends ListView {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener listener) {
|
||||
onInterceptTouchEventListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (onInterceptTouchEventListener != null) {
|
||||
return onInterceptTouchEventListener.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
View v = getChildAt(getChildCount() - 1);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
1084
TMessagesProj/src/main/java/org/telegram/ui/Views/NumberPicker.java
Normal file
502
TMessagesProj/src/main/java/org/telegram/ui/Views/Scroller.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -65,20 +65,33 @@ public class TimerButton extends View {
|
||||
time = value;
|
||||
|
||||
String timeString = null;
|
||||
if (time == 2) {
|
||||
timeString = "2s";
|
||||
} else if (time == 5) {
|
||||
timeString = "5s";
|
||||
} else if (time == 60) {
|
||||
timeString = "1m";
|
||||
} else if (time == 60 * 60) {
|
||||
timeString = "1h";
|
||||
} else if (time == 60 * 60 * 24) {
|
||||
timeString = "1d";
|
||||
} else if (time == 60 * 60 * 24 * 7) {
|
||||
timeString = "1w";
|
||||
if (time >= 1 && time < 60) {
|
||||
timeString = "" + value;
|
||||
if (timeString.length() < 2) {
|
||||
timeString += "s";
|
||||
}
|
||||
} else if (time >= 60 && time < 60 * 60) {
|
||||
timeString = "" + value / 60;
|
||||
if (timeString.length() < 2) {
|
||||
timeString += "m";
|
||||
}
|
||||
} else if (time >= 60 * 60 && time < 60 * 60 * 24) {
|
||||
timeString = "" + value / 60 / 60;
|
||||
if (timeString.length() < 2) {
|
||||
timeString += "h";
|
||||
}
|
||||
} else if (time >= 60 * 60 * 24 && time < 60 * 60 * 24 * 7) {
|
||||
timeString = "" + value / 60 / 60 / 24;
|
||||
if (timeString.length() < 2) {
|
||||
timeString += "d";
|
||||
}
|
||||
} else {
|
||||
timeString = "c";
|
||||
timeString = "" + value / 60 / 60 / 24 / 7;
|
||||
if (timeString.length() < 2) {
|
||||
timeString += "w";
|
||||
} else if (timeString.length() > 2) {
|
||||
timeString = "c";
|
||||
}
|
||||
}
|
||||
|
||||
timeWidth = timePaint.measureText(timeString);
|
||||
@ -110,7 +123,7 @@ public class TimerButton extends View {
|
||||
drawable.draw(canvas);
|
||||
|
||||
if (time != 0 && timeLayout != null) {
|
||||
canvas.translate((width - timeWidth) / 2, (height - timeHeight) / 2 + AndroidUtilities.dp(1));
|
||||
canvas.translate((int)(width / 2 - Math.ceil(timeWidth / 2)), (height - timeHeight) / 2 + AndroidUtilities.dpf2(1.5f));
|
||||
timeLayout.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -153,9 +153,13 @@ public class VideoTimelineView extends View {
|
||||
|
||||
public void setVideoPath(String path) {
|
||||
mediaMetadataRetriever = new MediaMetadataRetriever();
|
||||
mediaMetadataRetriever.setDataSource(path);
|
||||
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||
videoLength = Long.parseLong(duration);
|
||||
try {
|
||||
mediaMetadataRetriever.setDataSource(path);
|
||||
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||
videoLength = Long.parseLong(duration);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDelegate(VideoTimelineViewDelegate delegate) {
|
||||
|
3
TMessagesProj/src/main/res/anim/decelerate_cubic.xml
Normal 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" />
|
@ -1,15 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<scale android:fromXScale="0.9"
|
||||
android:fromYScale="0.9"
|
||||
android:toXScale="1.0"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:duration="150"/>
|
||||
<!--<scale-->
|
||||
<!--android:fromXScale="0.9"-->
|
||||
<!--android:fromYScale="0.9"-->
|
||||
<!--android:toXScale="1.0"-->
|
||||
<!--android:toYScale="1.0"-->
|
||||
<!--android:pivotX="50%"-->
|
||||
<!--android:pivotY="50%"-->
|
||||
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
|
||||
<!--android:duration="220"/>-->
|
||||
|
||||
<!--<alpha android:fromAlpha="0.0"-->
|
||||
<!--android:toAlpha="1.0"-->
|
||||
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
|
||||
<!--android:duration="@android:integer/config_mediumAnimTime" />-->
|
||||
|
||||
|
||||
<alpha android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="150" />
|
||||
<alpha
|
||||
android:fromAlpha="0.0"
|
||||
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>
|
@ -1,16 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<scale android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:toXScale="0.9"
|
||||
android:toYScale="0.9"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
<!--<scale-->
|
||||
<!--android:fromXScale="1.0"-->
|
||||
<!--android:fromYScale="1.0"-->
|
||||
<!--android:toXScale="0.9"-->
|
||||
<!--android:toYScale="0.9"-->
|
||||
<!--android:pivotX="50%"-->
|
||||
<!--android:pivotY="50%"-->
|
||||
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
|
||||
<!--android:duration="220"/>-->
|
||||
|
||||
<!--<alpha-->
|
||||
<!--android:fromAlpha="1.0"-->
|
||||
<!--android:toAlpha="0.0"-->
|
||||
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
|
||||
<!--android:duration="220" />-->
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:interpolator="@anim/decelerate_cubic"
|
||||
android:duration="150"/>
|
||||
|
||||
<alpha android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||||
android:duration="150" />
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale=".8"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale=".8"
|
||||
android:pivotX="50%p"
|
||||
android:pivotY="50%p"
|
||||
android:interpolator="@anim/decelerate_cubic"
|
||||
android:duration="150"/>
|
||||
</set>
|
BIN
TMessagesProj/src/main/res/drawable-hdpi/addcontact_blue.png
Executable file
After Width: | Height: | Size: 966 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/addcontact_green.png
Executable file
After Width: | Height: | Size: 966 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/burn.png
Executable file
After Width: | Height: | Size: 2.9 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/circle.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/circle1.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/list_focused_holo.9.png
Normal file
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 159 B |
After Width: | Height: | Size: 189 B |
After Width: | Height: | Size: 141 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/photocheck.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 231 B After Width: | Height: | Size: 231 B |
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 164 B |
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/addcontact_blue.png
Executable file
After Width: | Height: | Size: 954 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/addcontact_green.png
Executable file
After Width: | Height: | Size: 972 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/burn.png
Executable file
After Width: | Height: | Size: 1.9 KiB |
BIN
TMessagesProj/src/main/res/drawable-ldpi/circle.png
Executable file
After Width: | Height: | Size: 1.3 KiB |