1
0
mirror of https://github.com/MGislv/NekoX.git synced 2024-06-30 22:22:57 +00:00

Update to 3.3.1

This commit is contained in:
DrKLO 2015-11-27 00:04:02 +03:00
parent 496c336d5f
commit 74def22213
160 changed files with 36825 additions and 8207 deletions

View File

@ -7,22 +7,16 @@ repositories {
dependencies {
compile 'com.android.support:support-v4:23.1.+'
compile 'com.google.android.gms:play-services:3.2.+'
compile 'net.hockeyapp.android:HockeySDK:3.5.+'
compile 'net.hockeyapp.android:HockeySDK:3.6.+'
compile 'com.googlecode.mp4parser:isoparser:1.0.+'
compile 'org.apache.httpcomponents:httpmime:4.2.1'
}
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
buildToolsVersion '23.0.2'
useLibrary 'org.apache.http.legacy'
packagingOptions {
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
@ -30,7 +24,10 @@ android {
signingConfigs {
debug {
storeFile file("config/debug.keystore")
storeFile file("config/release.keystore")
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
release {
@ -46,6 +43,7 @@ android {
debuggable true
jniDebuggable true
signingConfig signingConfigs.debug
applicationIdSuffix ".beta"
}
release {
@ -81,7 +79,7 @@ android {
defaultConfig {
minSdkVersion 8
targetSdkVersion 23
versionCode 654
versionName "3.2.6"
versionCode 685
versionName "3.3.1"
}
}

View File

@ -21,13 +21,13 @@
<application
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
android:label="@string/AppNameBeta"
android:theme="@style/Theme.TMessages.Start"
android:name=".ApplicationLoader"
android:hardwareAccelerated="@bool/useHardwareAcceleration"
android:largeHeap="true">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyCTNmNqbWovP9ETcAob98YlrfOQEAC0CJ4" />
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyA-t0jLPjUt2FxrA8VPK2EiYHcYcboIR6k" />
<activity android:name="net.hockeyapp.android.UpdateActivity" />

View File

@ -187,7 +187,7 @@ include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad
LOCAL_MODULE := tmessages.14
LOCAL_MODULE := tmessages.15
LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math

View File

@ -96,7 +96,7 @@ void sendRequest(JNIEnv *env, jclass c, jint object, jobject onComplete, jobject
if (onQuickAck != nullptr) {
jniEnv->CallVoidMethod(onQuickAck, jclass_QuickAckDelegate_run);
}
}), flags, datacenterId, (ConnectionType) connetionType, immediate, onComplete, onQuickAck);
}), flags, datacenterId, (ConnectionType) connetionType, immediate, token, onComplete, onQuickAck);
}
void cancelRequest(JNIEnv *env, jclass c, jint token, jboolean notifyServer) {

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@
** part of the build process.
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h> /* Needed for the definition of va_list */
/*
@ -111,9 +111,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.11.1"
#define SQLITE_VERSION_NUMBER 3008011
#define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f"
#define SQLITE_VERSION "3.9.2"
#define SQLITE_VERSION_NUMBER 3009002
#define SQLITE_SOURCE_ID "2015-11-02 18:31:45 bda77dda9697c463c3d0704014d51627fceee328"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -124,7 +124,7 @@ extern "C" {
** but are associated with the library instead of the header file. ^(Cautious
** programmers might include assert() statements in their application to
** verify that values returned by these interfaces match the macros in
** the header, and thus insure that the application is
** the header, and thus ensure that the application is
** compiled with matching library and header files.
**
** <blockquote><pre>
@ -374,7 +374,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** Restrictions:
**
** <ul>
** <li> The application must insure that the 1st parameter to sqlite3_exec()
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
** is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
@ -477,6 +477,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_exec(
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@ -1366,9 +1367,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void);
** applications and so this routine is usually not necessary. It is
** provided to support rare applications with unusual needs.
**
** The sqlite3_config() interface is not threadsafe. The application
** must insure that no other SQLite interfaces are invoked by other
** threads while sqlite3_config() is running. Furthermore, sqlite3_config()
** <b>The sqlite3_config() interface is not threadsafe. The application
** must ensure that no other SQLite interfaces are invoked by other
** threads while sqlite3_config() is running.</b>
**
** The sqlite3_config() interface
** may only be invoked prior to library initialization using
** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
@ -3373,7 +3376,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
** [sqlite3_step(S)] but has not run to completion and/or has not
** [sqlite3_step(S)] but has neither run to completion (returned
** [SQLITE_DONE] from [sqlite3_step(S)]) nor
** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
** interface returns false if S is a NULL pointer. If S is not a
** NULL pointer and is not a pointer to a valid [prepared statement]
@ -3626,7 +3630,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*,
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
** [sqlite3_bind_parameter_name()].
*/
SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
@ -4355,6 +4359,22 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V. The subtype
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
** SQLite makes no use of subtype itself. It merely passes the subtype
** from the result of one [application-defined SQL function] into the
** input of another.
*/
SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value*);
/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
@ -4654,6 +4674,21 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_va
SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
/*
** CAPI3REF: Setting The Subtype Of An SQL Function
** METHOD: sqlite3_context
**
** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T. Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
*/
SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context*,unsigned int);
/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
@ -5599,13 +5634,31 @@ struct sqlite3_module {
** ^The estimatedRows value is an estimate of the number of rows that
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
** assumes that the strategy may visit at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
** part of the same statement to delete or update a virtual table row and the
** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
** any database changes. In other words, if the xUpdate() returns
** SQLITE_CONSTRAINT, the database contents must be exactly as they were
** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
** the xUpdate method are automatically rolled back by SQLite.
**
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
** structure for SQLite version 3.8.2. If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
** to included crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002.
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for version 3.9.0. It may therefore only be used if
** sqlite3_libversion_number() returns a value greater than or equal to
** 3009000.
*/
struct sqlite3_index_info {
/* Inputs */
@ -5633,8 +5686,15 @@ struct sqlite3_index_info {
double estimatedCost; /* Estimated cost of using this index */
/* Fields below are only available in SQLite 3.8.2 and later */
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
/* Fields below are only available in SQLite 3.9.0 and later */
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
};
/*
** CAPI3REF: Virtual Table Scan Flags
*/
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
@ -6092,6 +6152,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
** <li> SQLITE_MUTEX_STATIC_APP1
** <li> SQLITE_MUTEX_STATIC_APP2
** <li> SQLITE_MUTEX_STATIC_APP3
** <li> SQLITE_MUTEX_STATIC_VFS1
** <li> SQLITE_MUTEX_STATIC_VFS2
** <li> SQLITE_MUTEX_STATIC_VFS3
** </ul>
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@ -7858,3 +7921,523 @@ struct sqlite3_rtree_query_info {
#endif /* ifndef _SQLITE3RTREE_H_ */
/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** Interfaces to extend FTS5. Using the interfaces defined in this file,
** FTS5 may be extended with:
**
** * custom tokenizers, and
** * custom auxiliary functions.
*/
#ifndef _FTS5_H
#define _FTS5_H
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
** CUSTOM AUXILIARY FUNCTIONS
**
** Virtual table implementations may overload SQL functions by implementing
** the sqlite3_module.xFindFunction() method.
*/
typedef struct Fts5ExtensionApi Fts5ExtensionApi;
typedef struct Fts5Context Fts5Context;
typedef struct Fts5PhraseIter Fts5PhraseIter;
typedef void (*fts5_extension_function)(
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
Fts5Context *pFts, /* First arg to pass to pApi functions */
sqlite3_context *pCtx, /* Context for returning result/error */
int nVal, /* Number of values in apVal[] array */
sqlite3_value **apVal /* Array of trailing arguments */
);
struct Fts5PhraseIter {
const unsigned char *a;
const unsigned char *b;
};
/*
** EXTENSION API FUNCTIONS
**
** xUserData(pFts):
** Return a copy of the context pointer the extension function was
** registered with.
**
** xColumnTotalSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
** to the total number of tokens in the FTS5 table. Or, if iCol is
** non-negative but less than the number of columns in the table, return
** the total number of tokens in column iCol, considering all rows in
** the FTS5 table.
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** xColumnCount(pFts):
** Return the number of columns in the table.
**
** xColumnSize(pFts, iCol, pnToken):
** If parameter iCol is less than zero, set output variable *pnToken
** to the total number of tokens in the current row. Or, if iCol is
** non-negative but less than the number of columns in the table, set
** *pnToken to the number of tokens in column iCol of the current row.
**
** If parameter iCol is greater than or equal to the number of columns
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
** an OOM condition or IO error), an appropriate SQLite error code is
** returned.
**
** xColumnText:
** This function attempts to retrieve the text of column iCol of the
** current document. If successful, (*pz) is set to point to a buffer
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
** if an error occurs, an SQLite error code is returned and the final values
** of (*pz) and (*pn) are undefined.
**
** xPhraseCount:
** Returns the number of phrases in the current query expression.
**
** xPhraseSize:
** Returns the number of tokens in phrase iPhrase of the query. Phrases
** are numbered starting from zero.
**
** xInstCount:
** Set *pnInst to the total number of occurrences of all phrases within
** the query within the current row. Return SQLITE_OK if successful, or
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
**
** xInst:
** Query for the details of phrase match iIdx within the current row.
** Phrase matches are numbered starting from zero, so the iIdx argument
** should be greater than or equal to zero and smaller than the value
** output by xInstCount().
**
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
** if an error occurs.
**
** xRowid:
** Returns the rowid of the current row.
**
** xTokenize:
** Tokenize text using the tokenizer belonging to the FTS5 table.
**
** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
** This API function is used to query the FTS table for phrase iPhrase
** of the current query. Specifically, a query equivalent to:
**
** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
**
** with $p set to a phrase equivalent to the phrase iPhrase of the
** current query is executed. For each row visited, the callback function
** passed as the fourth argument is invoked. The context and API objects
** passed to the callback function may be used to access the properties of
** each matched row. Invoking Api.xUserData() returns a copy of the pointer
** passed as the third argument to pUserData.
**
** If the callback function returns any value other than SQLITE_OK, the
** query is abandoned and the xQueryPhrase function returns immediately.
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
** Otherwise, the error code is propagated upwards.
**
** If the query runs to completion without incident, SQLITE_OK is returned.
** Or, if some error occurs before the query completes or is aborted by
** the callback, an SQLite error code is returned.
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
** Save the pointer passed as the second argument as the extension functions
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** of the same MATCH query using the xGetAuxdata() API.
**
** Each extension function is allocated a single auxiliary data slot for
** each FTS query (MATCH expression). If the extension function is invoked
** more than once for a single FTS query, then all invocations share a
** single auxiliary data context.
**
** If there is already an auxiliary data pointer when this function is
** invoked, then it is replaced by the new pointer. If an xDelete callback
** was specified along with the original pointer, it is invoked at this
** point.
**
** The xDelete callback, if one is specified, is also invoked on the
** auxiliary data pointer after the FTS5 query has finished.
**
** If an error (e.g. an OOM condition) occurs within this function, an
** the auxiliary data is set to NULL and an error code returned. If the
** xDelete parameter was not NULL, it is invoked on the auxiliary data
** pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
** Returns the current auxiliary data pointer for the fts5 extension
** function. See the xSetAuxdata() method for details.
**
** If the bClear argument is non-zero, then the auxiliary data is cleared
** (set to NULL) before this function returns. In this case the xDelete,
** if any, is not invoked.
**
**
** xRowCount(pFts5, pnRow)
**
** This function is used to retrieve the total number of rows in the table.
** In other words, the same value that would be returned by:
**
** SELECT count(*) FROM ftstable;
**
** xPhraseFirst()
** This function is used, along with type Fts5PhraseIter and the xPhraseNext
** method, to iterate through all instances of a single query phrase within
** the current row. This is the same information as is accessible via the
** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
** to use, this API may be faster under some circumstances. To iterate
** through instances of phrase iPhrase, use the following code:
**
** Fts5PhraseIter iter;
** int iCol, iOff;
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
** iOff>=0;
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
** ){
** // An instance of phrase iPhrase at offset iOff of column iCol
** }
**
** The Fts5PhraseIter structure is defined above. Applications should not
** modify this structure directly - it should only be used as shown above
** with the xPhraseFirst() and xPhraseNext() API methods.
**
** xPhraseNext()
** See xPhraseFirst above.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 1 */
void *(*xUserData)(Fts5Context*);
int (*xColumnCount)(Fts5Context*);
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
int (*xTokenize)(Fts5Context*,
const char *pText, int nText, /* Text to tokenize */
void *pCtx, /* Context passed to xToken() */
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
);
int (*xPhraseCount)(Fts5Context*);
int (*xPhraseSize)(Fts5Context*, int iPhrase);
int (*xInstCount)(Fts5Context*, int *pnInst);
int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
sqlite3_int64 (*xRowid)(Fts5Context*);
int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
);
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
void *(*xGetAuxdata)(Fts5Context*, int bClear);
void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
** CUSTOM TOKENIZERS
**
** Applications may also register custom tokenizer types. A tokenizer
** is registered by providing fts5 with a populated instance of the
** following structure. All structure methods must be defined, setting
** any member of the fts5_tokenizer struct to NULL leads to undefined
** behaviour. The structure methods are expected to function as follows:
**
** xCreate:
** This function is used to allocate and inititalize a tokenizer instance.
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
** pointer provided by the application when the fts5_tokenizer object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
** to create the FTS5 table.
**
** The final argument is an output variable. If successful, (*ppOut)
** should be set to point to the new tokenizer handle and SQLITE_OK
** returned. If an error occurs, some value other than SQLITE_OK should
** be returned. In this case, fts5 assumes that the final value of *ppOut
** is undefined.
**
** xDelete:
** This function is invoked to delete a tokenizer handle previously
** allocated using xCreate(). Fts5 guarantees that this function will
** be invoked exactly once for each successful call to xCreate().
**
** xTokenize:
** This function is expected to tokenize the nText byte string indicated
** by argument pText. pText may or may not be nul-terminated. The first
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
** The second argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
** or removed from the FTS table. The tokenizer is being invoked to
** determine the set of tokens to add to (or delete from) the
** FTS index.
**
** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
** against the FTS index. The tokenizer is being called to tokenize
** a bareword or quoted string specified as part of the query.
**
** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
** followed by a "*" character, indicating that the last token
** returned by the tokenizer will be treated as a token prefix.
**
** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
** satisfy an fts5_api.xTokenize() request made by an auxiliary
** function. Or an fts5_api.xColumnSize() request made by the same
** on a columnsize=0 database.
** </ul>
**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
** arguments are a pointer to a buffer containing the token text, and the
** size of the token in bytes. The 4th and 5th arguments are the byte offsets
** of the first byte of and first byte immediately following the text from
** which the token is derived within the input.
**
** The second argument passed to the xToken() callback ("tflags") should
** normally be set to 0. The exception is if the tokenizer supports
** synonyms. In this case see the discussion below for details.
**
** FTS5 assumes the xToken() callback is invoked for each token in the
** order that they occur within the input text.
**
** If an xToken() callback returns any value other than SQLITE_OK, then
** the tokenization should be abandoned and the xTokenize() method should
** immediately return a copy of the xToken() return value. Or, if the
** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
** if an error occurs with the xTokenize() implementation itself, it
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
** user wishes to query for a phrase such as "first place". Using the
** built-in tokenizers, the FTS5 query 'first + place' will match instances
** of "first place" within the document set, but not alternative forms
** such as "1st place". In some applications, it would be better to match
** all instances of "first place" or "1st place" regardless of which form
** the user specified in the MATCH query text.
**
** There are several ways to approach this in FTS5:
**
** <ol><li> By mapping all synonyms to a single token. In this case, the
** In the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
** "first" and "place". If the user then queries for '1st + place',
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
** <li> By adding multiple synonyms for a single term to the FTS index.
** In this case, when tokenizing query text, the tokenizer may
** provide multiple synonyms for a single term within the document.
** FTS5 then queries the index for each synonym individually. For
** example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
**
** the tokenizer offers both "1st" and "first" as synonyms for the
** first token in the MATCH query and FTS5 effectively runs a query
** similar to:
**
** <codeblock>
** ... MATCH '(first OR 1st) place'</codeblock>
**
** except that, for the purposes of auxiliary functions, the query
** still appears to contain just two phrases - "(first OR 1st)"
** being treated as a single phrase.
**
** <li> By adding multiple synonyms for a single term to the FTS index.
** Using this method, when tokenizing document text, the tokenizer
** provides multiple synonyms for each token. So that when a
** document such as "I won first place" is tokenized, entries are
** added to the FTS index for "i", "won", "first", "1st" and
** "place".
**
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entires in the
** FTS index corresponding to both forms of the first token.
** </ol>
**
** Whether it is parsing document or query text, any call to xToken that
** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
** is considered to supply a synonym for the previous token. For example,
** when parsing the document "I won first place", a tokenizer that supports
** synonyms would call xToken() 5 times, as follows:
**
** <codeblock>
** xToken(pCtx, 0, "i", 1, 0, 1);
** xToken(pCtx, 0, "won", 3, 2, 5);
** xToken(pCtx, 0, "first", 5, 6, 11);
** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
** xToken(pCtx, 0, "place", 5, 12, 17);
**</codeblock>
**
** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
** xToken() is called. Multiple synonyms may be specified for a single token
** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
** There is no limit to the number of synonyms that may be provided for a
** single token.
**
** In many cases, method (1) above is the best approach. It does not add
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
** token "first" is subsituted for "1st" by the tokenizer, then the query:
**
** <codeblock>
** ... MATCH '1s*'</codeblock>
**
** will not match documents that contain the token "1st" (as the tokenizer
** will probably not map "1s" to any prefix of "first").
**
** For full prefix support, method (3) may be preferred. In this case,
** because the index contains entries for both "first" and "1st", prefix
** queries such as 'fi*' or '1s*' will match correctly. However, because
** extra entries are added to the FTS index, this method uses more space
** within the database.
**
** Method (2) offers a midpoint between (1) and (3). Using this method,
** a query such as '1s*' will match documents that contain the literal
** token "1st", but not "first" (assuming the tokenizer is not able to
** provide synonyms for prefixes). However, a non-prefix query like '1st'
** will match against "1st" and "first". This method does not require
** extra disk space, as no extra entries are added to the FTS index.
** On the other hand, it may require more CPU cycles to run MATCH queries,
** as separate queries of the FTS index are required for each synonym.
**
** When using methods (2) or (3), it is important that the tokenizer only
** provide synonyms when tokenizing document text (method (2)) or query
** text (method (3)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
void (*xDelete)(Fts5Tokenizer*);
int (*xTokenize)(Fts5Tokenizer*,
void *pCtx,
int flags, /* Mask of FTS5_TOKENIZE_* flags */
const char *pText, int nText,
int (*xToken)(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iStart, /* Byte offset of token within input text */
int iEnd /* Byte offset of end of token within input text */
)
);
};
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
#define FTS5_TOKENIZE_DOCUMENT 0x0004
#define FTS5_TOKENIZE_AUX 0x0008
/* Flags that may be passed by the tokenizer implementation back to FTS5
** as the third argument to the supplied xToken callback. */
#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
/*
** END OF CUSTOM TOKENIZERS
*************************************************************************/
/*************************************************************************
** FTS5 EXTENSION REGISTRATION API
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
int iVersion; /* Currently always set to 2 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_tokenizer *pTokenizer,
void (*xDestroy)(void*)
);
/* Find an existing tokenizer */
int (*xFindTokenizer)(
fts5_api *pApi,
const char *zName,
void **ppContext,
fts5_tokenizer *pTokenizer
);
/* Create a new auxiliary function */
int (*xCreateFunction)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
};
/*
** END OF REGISTRATION API
*************************************************************************/
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* _FTS5_H */

View File

@ -6,6 +6,7 @@
* Copyright Nikolai Kudashov, 2015.
*/
#include <sys/stat.h>
#include "Config.h"
#include "ConnectionsManager.h"
#include "FileLog.h"
@ -16,9 +17,10 @@ Config::Config(std::string fileName) {
backupPath = configPath + ".bak";
FILE *backup = fopen(backupPath.c_str(), "rb");
if (backup != nullptr) {
DEBUG_D("Config(%p, %s) backup file found %s", this, configPath.c_str(), backupPath.c_str());
fclose(backup);
remove(configPath.c_str());
rename(backupPath.c_str(), configPath.c_str());
fclose(backup);
}
}
@ -28,10 +30,14 @@ NativeByteBuffer *Config::readConfig() {
if (file != nullptr) {
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
if (fseek(file, 0, SEEK_SET)) {
DEBUG_E("Config(%p, %s) failed fseek to begin, reopen it", this, configPath.c_str());
fclose(file);
file = fopen(configPath.c_str(), "rb");
}
uint32_t size = 0;
int bytesRead = fread(&size, sizeof(uint32_t), 1, file);
DEBUG_D("Config(%p, %s) load, size = %u", this, configPath.c_str(), size);
DEBUG_D("Config(%p, %s) load, size = %u, fileSize = %u", this, configPath.c_str(), size, (uint32_t) fileSize);
if (bytesRead > 0 && size > 0 && (int32_t) size < fileSize) {
buffer = BuffersStorage::getInstance().getFreeBuffer(size);
if (fread(buffer->bytes(), sizeof(uint8_t), size, file) != size) {
@ -45,6 +51,7 @@ NativeByteBuffer *Config::readConfig() {
}
void Config::writeConfig(NativeByteBuffer *buffer) {
DEBUG_D("Config(%p, %s) start write config", this, configPath.c_str());
FILE *file = fopen(configPath.c_str(), "rb");
FILE *backup = fopen(backupPath.c_str(), "rb");
bool error = false;
@ -65,21 +72,53 @@ void Config::writeConfig(NativeByteBuffer *buffer) {
return;
}
file = fopen(configPath.c_str(), "wb");
if (chmod(configPath.c_str(), 0660)) {
DEBUG_E("Config(%p, %s) chmod failed", this, configPath.c_str());
}
if (file == nullptr) {
DEBUG_E("Config(%p, %s) unable to open file for writing", this, configPath.c_str());
return;
}
uint32_t size = buffer->position();
if (fwrite(&size, sizeof(uint32_t), 1, file) == 1) {
if (fwrite(buffer->bytes(), sizeof(uint8_t), size, file) != size) {
DEBUG_E("Config(%p, %s) failed to write config data to file", this, configPath.c_str());
error = true;
}
} else {
DEBUG_E("Config(%p, %s) failed to write config size to file", this, configPath.c_str());
error = true;
}
fclose(file);
if (error) {
remove(configPath.c_str());
if (fflush(file)) {
DEBUG_E("Config(%p, %s) fflush failed", this, configPath.c_str());
error = true;
}
int fd = fileno(file);
if (fd == -1) {
DEBUG_E("Config(%p, %s) fileno failed", this, configPath.c_str());
error = true;
} else {
remove(backupPath.c_str());
DEBUG_D("Config(%p, %s) fileno = %d", this, configPath.c_str(), fd);
}
if (fd != -1 && fsync(fd) == -1) {
DEBUG_E("Config(%p, %s) fsync failed", this, configPath.c_str());
error = true;
}
if (fclose(file)) {
DEBUG_E("Config(%p, %s) fclose failed", this, configPath.c_str());
error = true;
}
if (error) {
DEBUG_E("Config(%p, %s) failed to write config", this, configPath.c_str());
if (remove(configPath.c_str())) {
DEBUG_E("Config(%p, %s) remove config failed", this, configPath.c_str());
}
} else {
if (remove(backupPath.c_str())) {
DEBUG_E("Config(%p, %s) remove backup failed failed", this, configPath.c_str());
}
}
if (!error) {
DEBUG_D("Config(%p, %s) config write ok", this, configPath.c_str());
}
}

View File

@ -220,7 +220,7 @@ void ConnectionsManager::select() {
return;
} else {
lastPauseTime = now;
DEBUG_D("don't sleep 10 seconds because of salt, upload or download request");
DEBUG_D("don't sleep 30 seconds because of salt, upload or download request");
}
}
if (networkPaused) {
@ -595,7 +595,7 @@ void ConnectionsManager::onConnectionConnected(Connection *connection) {
} else {
if (networkPaused && lastPauseTime != 0) {
lastPauseTime = getCurrentTimeMillis();
nextSleepTimeout = 10000;
nextSleepTimeout = 30000;
}
processRequestQueue(connection->getConnectionType(), datacenter->getDatacenterId());
}
@ -821,6 +821,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
Request *request = iter->get();
Datacenter *requestDatacenter = getDatacenterWithId(request->datacenterId);
if (request->messageId < response->first_msg_id && request->connectionType & connection->getConnectionType() && requestDatacenter != nullptr && requestDatacenter->getDatacenterId() == datacenter->getDatacenterId()) {
DEBUG_D("clear request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
request->clear(true);
}
}
@ -943,6 +944,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
for (requestsIter iter = runningRequests.begin(); iter != runningRequests.end(); iter++) {
Request *request = iter->get();
if (request->respondsToMessageId(resultMid)) {
DEBUG_D("got response for request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
bool discardResponse = false;
bool isError = false;
bool allowInitConnection = true;
@ -984,8 +986,16 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
}
discardResponse = true;
request->failedByFloodWait = true;
request->failedByFloodWait = waitTime;
request->startTime = 0;
request->minStartTime = (int32_t) (getCurrentTimeMillis() / 1000 + waitTime);
} else if (error->error_code == 400) {
static std::string waitFailed = "MSG_WAIT_FAILED";
if (error->error_message.find(waitFailed) != std::string::npos) {
discardResponse = true;
request->minStartTime = (int32_t) (getCurrentTimeMillis() / 1000 + 1);
request->startTime = 0;
}
}
}
if (!discardResponse) {
@ -1124,10 +1134,10 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
if ((request->connectionType & ConnectionTypeDownload) == 0) {
continue;
}
if (request->respondsToMessageId(resultMid)) {
Datacenter *requestDatacenter = getDatacenterWithId(request->datacenterId);
if (requestDatacenter != nullptr && requestDatacenter->getDatacenterId() == datacenter->getDatacenterId()) {
request->retryCount = 0;
request->failedBySalt = true;
break;
}
}
}
@ -1208,7 +1218,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
} else if (connection->connectionType == ConnectionTypePush && typeInfo == typeid(TL_updatesTooLong)) {
if (networkPaused) {
lastPauseTime = getCurrentTimeMillis();
nextSleepTimeout = 10000;
nextSleepTimeout = 30000;
DEBUG_D("received internal push: wakeup network in background");
} else if (lastPauseTime != 0) {
lastPauseTime = getCurrentTimeMillis();
@ -1364,12 +1374,6 @@ void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete
}
#ifdef ANDROID
int32_t ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate, jobject ptr1, jobject ptr2) {
int32_t requestToken = lastRequestToken++;
sendRequest(object, onComplete, onQuickAck, flags, datacenterId, connetionType, immediate, requestToken, ptr1, ptr2);
return requestToken;
}
void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate, int32_t requestToken, jobject ptr1, jobject ptr2) {
if (!currentUserId && !(flags & RequestFlagWithoutLogin)) {
DEBUG_D("can't do request without login %s", typeid(*object).name());
@ -1489,7 +1493,7 @@ void ConnectionsManager::cancelRequestInternal(int32_t token, bool notifyServer,
Request *request = iter->get();
if (request->requestToken == token) {
request->cancelled = true;
DEBUG_D("cancelled queued rpc request %s", typeid(*request->rawRequest).name());
DEBUG_D("cancelled queued rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
requestsQueue.erase(iter);
if (removeFromClass) {
removeRequestFromGuid(token);
@ -1507,7 +1511,7 @@ void ConnectionsManager::cancelRequestInternal(int32_t token, bool notifyServer,
sendRequest(dropAnswer, nullptr, nullptr, RequestFlagEnableUnauthorized | RequestFlagWithoutLogin | RequestFlagFailOnServerErrors, request->datacenterId, request->connectionType, true);
}
request->cancelled = true;
DEBUG_D("cancelled running rpc request %s", typeid(*request->rawRequest).name());
DEBUG_D("cancelled running rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
runningRequests.erase(iter);
if (removeFromClass) {
removeRequestFromGuid(token);
@ -1795,7 +1799,12 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
forceThisRequest = false;
}
if (forceThisRequest || (abs(currentTime - request->startTime) > maxTimeout && (currentTime > request->minStartTime || abs(currentTime - request->minStartTime) > 60))) {
if (forceThisRequest || (abs(currentTime - request->startTime) > maxTimeout &&
(currentTime >= request->minStartTime ||
(request->failedByFloodWait != 0 && (request->minStartTime - currentTime) > request->failedByFloodWait) ||
(request->failedByFloodWait == 0 && abs(currentTime - request->minStartTime) >= 60))
)
) {
if (!forceThisRequest && request->connectionToken > 0) {
if (request->connectionType & ConnectionTypeGeneric && request->connectionToken == connection->getConnectionToken()) {
DEBUG_D("request token is valid, not retrying %s", typeInfo.name());
@ -1816,25 +1825,29 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
request->retryCount++;
if (!request->failedBySalt && request->connectionType & ConnectionTypeDownload) {
uint32_t retryMax = 10;
if (!(request->requestFlags & RequestFlagForceDownload)) {
if (request->failedByFloodWait) {
retryMax = 1;
} else {
retryMax = 6;
if (!request->failedBySalt) {
if (request->connectionType & ConnectionTypeDownload) {
uint32_t retryMax = 10;
if (!(request->requestFlags & RequestFlagForceDownload)) {
if (request->failedByFloodWait) {
retryMax = 1;
} else {
retryMax = 6;
}
}
if (request->retryCount >= retryMax) {
DEBUG_E("timed out %s", typeInfo.name());
TL_error *error = new TL_error();
error->code = -123;
error->text = "RETRY_LIMIT";
request->onComplete(nullptr, error);
delete error;
iter = runningRequests.erase(iter);
continue;
}
}
if (request->retryCount >= retryMax) {
DEBUG_E("timed out %s", typeInfo.name());
TL_error *error = new TL_error();
error->code = -123;
error->text = "RETRY_LIMIT";
request->onComplete(nullptr, error);
delete error;
iter = runningRequests.erase(iter);
continue;
}
} else {
request->failedBySalt = false;
}
if (request->messageSeqNo == 0) {
@ -2103,9 +2116,11 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
TL_invokeAfterMsg *request = new TL_invokeAfterMsg();
request->msg_id = lastSentMessageRpcId;
if (message->outgoingBody != nullptr) {
DEBUG_D("wrap outgoingBody(%p, %s) to TL_invokeAfterMsg", message->outgoingBody, typeid(*message->outgoingBody).name());
request->outgoingQuery = message->outgoingBody;
message->outgoingBody = nullptr;
} else {
DEBUG_D("wrap body(%p, %s) to TL_invokeAfterMsg", message->body.get(), typeid(*message->body.get()).name());
request->query = std::move(message->body);
}
message->body = std::unique_ptr<TLObject>(request);
@ -2407,7 +2422,7 @@ void ConnectionsManager::resumeNetwork(bool partial) {
if (partial) {
if (networkPaused) {
lastPauseTime = getCurrentTimeMillis();
nextSleepTimeout = 10000;
nextSleepTimeout = 30000;
networkPaused = false;
DEBUG_D("wakeup network in background");
} else if (lastPauseTime != 0) {

View File

@ -14,6 +14,7 @@
#include <functional>
#include <sys/epoll.h>
#include <map>
#include <atomic>
#include <bits/unique_ptr.h>
#include "Defines.h"
@ -63,7 +64,6 @@ public:
void updateDcSettings(uint32_t datacenterId);
#ifdef ANDROID
int32_t sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate, jobject ptr1, jobject ptr2);
void sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate, int32_t requestToken, jobject ptr1, jobject ptr2);
static void useJavaVM(JavaVM *vm, bool useJavaByteBuffers);
#endif
@ -120,7 +120,7 @@ private:
std::map<int32_t, std::vector<std::int32_t>> quickAckIdToRequestIds;
int32_t pingTime;
bool testBackend = false;
volatile uint32_t lastRequestToken = 1;
std::atomic<uint32_t> lastRequestToken{1};
uint32_t currentDatacenterId = 0;
uint32_t movingToDatacenterId = DEFAULT_DATACENTER_ID;
int64_t pushSessionId = 0;

View File

@ -668,9 +668,7 @@ void Datacenter::onHandshakeConnectionConnected(Connection *connection) {
if (handshakeState == 0 || !needResendData) {
return;
}
if (handshakeRequest != nullptr) {
sendRequestData(handshakeRequest, true);
}
beginHandshake(false);
}
inline uint64_t gcd(uint64_t a, uint64_t b) {
@ -1383,6 +1381,7 @@ NativeByteBuffer *Datacenter::createRequestsData(std::vector<std::unique_ptr<Net
int64_t currentTime = ConnectionsManager::getInstance().getCurrentTimeMillis() + (int64_t) timeDifference * 1000;
if (messageTime < currentTime - 30000 || messageTime > currentTime + 25000) {
DEBUG_D("wrap message in container");
TL_msg_container *messageContainer = new TL_msg_container();
messageContainer->messages.push_back(std::move(networkMessage->message));
@ -1395,6 +1394,7 @@ NativeByteBuffer *Datacenter::createRequestsData(std::vector<std::unique_ptr<Net
messageSeqNo = networkMessage->message->seqno;
}
} else {
DEBUG_D("start write messages to container");
TL_msg_container *messageContainer = new TL_msg_container();
size_t count = requests.size();
for (uint32_t a = 0; a < count; a++) {

View File

@ -18,7 +18,9 @@
FILE *logFile = nullptr;
void FileLog::init(std::string path) {
logFile = fopen(path.c_str(), "w");
if (path.size() > 0) {
logFile = fopen(path.c_str(), "w");
}
}
void FileLog::e(const char *message, ...) {

View File

@ -931,7 +931,7 @@ void TL_config::readParams(NativeByteBuffer *stream, bool &error) {
dc_options.push_back(std::unique_ptr<TL_dcOption>(object));
}
chat_size_max = stream->readInt32(&error);
broadcast_size_max = stream->readInt32(&error);
megagroup_size_max = stream->readInt32(&error);
forwarded_count_max = stream->readInt32(&error);
online_update_period_ms = stream->readInt32(&error);
offline_blur_timeout_ms = stream->readInt32(&error);
@ -971,7 +971,7 @@ void TL_config::serializeToStream(NativeByteBuffer *stream) {
dc_options[a]->serializeToStream(stream);
}
stream->writeInt32(chat_size_max);
stream->writeInt32(broadcast_size_max);
stream->writeInt32(megagroup_size_max);
stream->writeInt32(forwarded_count_max);
stream->writeInt32(online_update_period_ms);
stream->writeInt32(offline_blur_timeout_ms);

View File

@ -657,7 +657,7 @@ public:
class TL_config : public TLObject {
public:
static const uint32_t constructor = 0x4e32b894;
static const uint32_t constructor = 0x6cb6e65e;
int32_t date;
int32_t expires;
@ -665,7 +665,7 @@ public:
int32_t this_dc;
std::vector<std::unique_ptr<TL_dcOption>> dc_options;
int32_t chat_size_max;
int32_t broadcast_size_max;
int32_t megagroup_size_max;
int32_t forwarded_count_max;
int32_t online_update_period_ms;
int32_t offline_blur_timeout_ms;

View File

@ -34,7 +34,7 @@ public:
int32_t requestToken;
uint32_t retryCount = 0;
bool failedBySalt = false;
bool failedByFloodWait = false;
int32_t failedByFloodWait = 0;
ConnectionType connectionType;
uint32_t requestFlags;
bool completed = false;

Binary file not shown.

View File

@ -43,7 +43,6 @@
android:allowBackup="false"
android:hardwareAccelerated="@bool/useHardwareAcceleration"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
android:largeHeap="true"
android:theme="@style/Theme.TMessages.Start">
@ -159,7 +158,7 @@
</service>
<service
android:name=".TgChooserTargetService"
android:name="org.telegram.messenger.TgChooserTargetService"
android:label="@string/AppName"
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
<intent-filter>

View File

@ -1,53 +1,53 @@
1876;JM;Jamaica
1869;KN;Saint Kitts & Nevis
1868;TT;Trinidad & Tobago
1784;VC;Saint Vincent & the Grenadines
1767;DM;Dominica
1758;LC;Saint Lucia
1721;SX;Sint Maarten
1684;AS;American Samoa
1671;GU;Guam
1670;MP;Northern Mariana Islands
1664;MS;Montserrat
1649;TC;Turks & Caicos Islands
1473;GD;Grenada
1441;BM;Bermuda
1345;KY;Cayman Islands
1340;VI;US Virgin Islands
1284;VG;British Virgin Islands
1268;AG;Antigua & Barbuda
1264;AI;Anguilla
1246;BB;Barbados
1242;BS;Bahamas
998;UZ;Uzbekistan
996;KG;Kyrgyzstan
995;GE;Georgia
994;AZ;Azerbaijan
993;TM;Turkmenistan
992;TJ;Tajikistan
977;NP;Nepal
976;MN;Mongolia
975;BT;Bhutan
974;QA;Qatar
973;BH;Bahrain
972;IL;Israel
971;AE;United Arab Emirates
970;PS;Palestine
968;OM;Oman
967;YE;Yemen
966;SA;Saudi Arabia
965;KW;Kuwait
964;IQ;Iraq
963;SY;Syrian Arab Republic
962;JO;Jordan
1876;JM;Jamaica;XXX XXXX
1869;KN;Saint Kitts & Nevis;XXX XXXX
1868;TT;Trinidad & Tobago;XXX XXXX
1784;VC;Saint Vincent & the Grenadines;XXX XXXX
1767;DM;Dominica;XXX XXXX
1758;LC;Saint Lucia;XXX XXXX
1721;SX;Sint Maarten;XXX XXXX
1684;AS;American Samoa;XXX XXXX
1671;GU;Guam;XXX XXXX
1670;MP;Northern Mariana Islands;XXX XXXX
1664;MS;Montserrat;XXX XXXX
1649;TC;Turks & Caicos Islands;XXX XXXX
1473;GD;Grenada;XXX XXXX
1441;BM;Bermuda;XXX XXXX
1345;KY;Cayman Islands;XXX XXXX
1340;VI;US Virgin Islands;XXX XXXX
1284;VG;British Virgin Islands;XXX XXXX
1268;AG;Antigua & Barbuda;XXX XXXX
1264;AI;Anguilla;XXX XXXX
1246;BB;Barbados;XXX XXXX
1242;BS;Bahamas;XXX XXXX
998;UZ;Uzbekistan;XX XXXXXXX
996;KG;Kyrgyzstan;XXX XXXXXX
995;GE;Georgia;XXX XXX XXX
994;AZ;Azerbaijan;XX XXX XXXX
993;TM;Turkmenistan;XX XXXXXX
992;TJ;Tajikistan;XX XXX XXXX
977;NP;Nepal;XX XXXX XXXX
976;MN;Mongolia;XX XX XXXX
975;BT;Bhutan;XX XXX XXX
974;QA;Qatar;XX XXX XXX
973;BH;Bahrain;XXXX XXXX
972;IL;Israel;XX XXX XXXX
971;AE;United Arab Emirates;XX XXX XXXX
970;PS;Palestine;XXX XX XXXX
968;OM;Oman;XXXX XXXX
967;YE;Yemen;XXX XXX XXX
966;SA;Saudi Arabia;XX XXX XXXX
965;KW;Kuwait;XXXX XXXX
964;IQ;Iraq;XXX XXX XXXX
963;SY;Syria;XXX XXX XXX
962;JO;Jordan;X XXXX XXXX
961;LB;Lebanon
960;MV;Maldives
886;TW;Taiwan
960;MV;Maldives;XXX XXXX
886;TW;Taiwan;XXX XXX XXX
880;BD;Bangladesh
856;LA;Laos
856;LA;Laos;XX XX XXX XXX
855;KH;Cambodia
853;MO;Macau
852;HK;Hong Kong
853;MO;Macau;XXXX XXXX
852;HK;Hong Kong;X XXX XXXX
850;KP;North Korea
692;MH;Marshall Islands
691;FM;Micronesia
@ -67,166 +67,166 @@
676;TO;Tonga
675;PG;Papua New Guinea
674;NR;Nauru
673;BN;Brunei Darussalam
673;BN;Brunei Darussalam;XXX XXXX
672;NF;Norfolk Island
670;TL;Timor-Leste
599;BQ;Bonaire, Sint Eustatius & Saba
599;CW;Curaçao
598;UY;Uruguay
597;SR;Suriname
598;UY;Uruguay;X XXX XXXX
597;SR;Suriname;XXX XXXX
596;MQ;Martinique
595;PY;Paraguay
595;PY;Paraguay;XXX XXX XXX
594;GF;French Guiana
593;EC;Ecuador
593;EC;Ecuador;XX XXX XXXX
592;GY;Guyana
591;BO;Bolivia
590;GP;Guadeloupe
591;BO;Bolivia;X XXX XXXX
590;GP;Guadeloupe;XXX XX XX XX
509;HT;Haiti
508;PM;Saint Pierre & Miquelon
507;PA;Panama
506;CR;Costa Rica
505;NI;Nicaragua
504;HN;Honduras
503;SV;El Salvador
502;GT;Guatemala
507;PA;Panama;XXXX XXXX
506;CR;Costa Rica;XXXX XXXX
505;NI;Nicaragua;XXXX XXXX
504;HN;Honduras;XXXX XXXX
503;SV;El Salvador;XXXX XXXX
502;GT;Guatemala;X XXX XXXX
501;BZ;Belize
500;FK;Falkland Islands
423;LI;Liechtenstein
421;SK;Slovakia
420;CZ;Czech Republic
389;MK;Macedonia
387;BA;Bosnia & Herzegovina
386;SI;Slovenia
421;SK;Slovakia;XXX XXX XXX
420;CZ;Czech Republic;XXX XXX XXX
389;MK;Macedonia;XX XXX XXX
387;BA;Bosnia & Herzegovina;XX XXX XXX
386;SI;Slovenia;XX XXX XXX
385;HR;Croatia
382;ME;Montenegro
381;RS;Serbia
380;UA;Ukraine
378;SM;San Marino
377;MC;Monaco
376;AD;Andorra
375;BY;Belarus
374;AM;Armenia
373;MD;Moldova
381;RS;Serbia;XX XXX XXXX
380;UA;Ukraine;XX XXX XX XX
378;SM;San Marino;XXX XXX XXXX
377;MC;Monaco;XXXX XXXX
376;AD;Andorra;XX XX XX
375;BY;Belarus;XX XXX XXXX
374;AM;Armenia;XX XXX XXX
373;MD;Moldova;XX XXX XXX
372;EE;Estonia
371;LV;Latvia
370;LT;Lithuania
371;LV;Latvia;XXX XXXXX
370;LT;Lithuania;XXX XXXXX
359;BG;Bulgaria
358;FI;Finland
357;CY;Cyprus
356;MT;Malta
355;AL;Albania
354;IS;Iceland
353;IE;Ireland
357;CY;Cyprus;XXXX XXXX
356;MT;Malta;XX XX XX XX
355;AL;Albania;XX XXX XXXX
354;IS;Iceland;XXX XXXX
353;IE;Ireland;XX XXX XXXX
352;LU;Luxembourg
351;PT;Portugal
350;GI;Gibraltar
299;GL;Greenland
298;FO;Faroe Islands
297;AW;Aruba
291;ER;Eritrea
290;SH;Saint Helena
269;KM;Comoros
268;SZ;Swaziland
267;BW;Botswana
266;LS;Lesotho
265;MW;Malawi
264;NA;Namibia
263;ZW;Zimbabwe
262;RE;Réunion
261;MG;Madagascar
260;ZM;Zambia
258;MZ;Mozambique
257;BI;Burundi
256;UG;Uganda
255;TZ;Tanzania
254;KE;Kenya
253;DJ;Djibouti
252;SO;Somalia
251;ET;Ethiopia
250;RW;Rwanda
249;SD;Sudan
248;SC;Seychelles
247;SH;Saint Helena
246;IO;Diego Garcia
245;GW;Guinea-Bissau
244;AO;Angola
243;CD;Congo (Dem. Rep.)
242;CG;Congo (Rep.)
241;GA;Gabon
240;GQ;Equatorial Guinea
239;ST;São Tomé & Príncipe
238;CV;Cape Verde
237;CM;Cameroon
236;CF;Central African Rep.
235;TD;Chad
351;PT;Portugal;X XXXX XXXX
350;GI;Gibraltar;XXXX XXXX
299;GL;Greenland;XXX XXX
298;FO;Faroe Islands;XXX XXX
297;AW;Aruba;XXX XXXX
291;ER;Eritrea;X XXX XXX
290;SH;Saint Helena;XX XXX
269;KM;Comoros;XXX XXXX
268;SZ;Swaziland;XXXX XXXX
267;BW;Botswana;XX XXX XXX
266;LS;Lesotho;XX XXX XXX
265;MW;Malawi;77 XXX XXXX
264;NA;Namibia;XX XXX XXXX
263;ZW;Zimbabwe;XX XXX XXXX
262;RE;Réunion;XXX XXX XXX
261;MG;Madagascar;XX XX XXX XX
260;ZM;Zambia;XX XXX XXXX
258;MZ;Mozambique;XX XXX XXXX
257;BI;Burundi;XX XX XXXX
256;UG;Uganda;XX XXX XXXX
255;TZ;Tanzania;XX XXX XXXX
254;KE;Kenya;XXX XXX XXX
253;DJ;Djibouti;XX XX XX XX
252;SO;Somalia;XX XXX XXX
251;ET;Ethiopia;XX XXX XXXX
250;RW;Rwanda;XXX XXX XXX
249;SD;Sudan;XX XXX XXXX
248;SC;Seychelles;X XX XX XX
247;SH;Saint Helena;XXXX
246;IO;Diego Garcia;XXX XXXX
245;GW;Guinea-Bissau;XXX XXXX
244;AO;Angola;XXX XXX XXX
243;CD;Congo (Dem. Rep.);XX XXX XXXX
242;CG;Congo (Rep.);XX XXX XXXX
241;GA;Gabon;X XX XX XX
240;GQ;Equatorial Guinea;XXX XXX XXX
239;ST;São Tomé & Príncipe;XX XXXXX
238;CV;Cape Verde;XXX XXXX
237;CM;Cameroon;XXXX XXXX
236;CF;Central African Rep.;XX XX XX XX
235;TD;Chad;XX XX XX XX
234;NG;Nigeria
233;GH;Ghana
232;SL;Sierra Leone
232;SL;Sierra Leone;XX XXX XXX
231;LR;Liberia
230;MU;Mauritius
229;BJ;Benin
228;TG;Togo
227;NE;Niger
226;BF;Burkina Faso
225;CI;Côte d`Ivoire
224;GN;Guinea
223;ML;Mali
222;MR;Mauritania
221;SN;Senegal
220;GM;Gambia
218;LY;Libya
216;TN;Tunisia
213;DZ;Algeria
212;MA;Morocco
211;SS;South Sudan
98;IR;Iran
229;BJ;Benin;XX XXX XXX
228;TG;Togo;XX XXX XXX
227;NE;Niger;XX XX XX XX
226;BF;Burkina Faso;XX XX XX XX
225;CI;Côte d`Ivoire;XX XXX XXX
224;GN;Guinea;XXX XXX XXX
223;ML;Mali;XXXX XXXX
222;MR;Mauritania;XXXX XXXX
221;SN;Senegal;XX XXX XXXX
220;GM;Gambia;XXX XXXX
218;LY;Libya;XX XXX XXXX
216;TN;Tunisia;XX XXX XXX
213;DZ;Algeria;XXX XX XX XX
212;MA;Morocco;XX XXX XXXX
211;SS;South Sudan;XX XXX XXXX
98;IR;Iran;XXX XXX XXXX
95;MM;Myanmar
94;LK;Sri Lanka
93;AF;Afghanistan
92;PK;Pakistan
91;IN;India
90;TR;Turkey
86;CN;China
94;LK;Sri Lanka;XX XXX XXXX
93;AF;Afghanistan;XXX XXX XXX
92;PK;Pakistan;XXX XXX XXXX
91;IN;India;XXXXX XXXXX
90;TR;Turkey;XXX XXX XXXX
86;CN;China;XXX XXXX XXXX
84;VN;Vietnam
82;KR;South Korea
81;JP;Japan
66;TH;Thailand
65;SG;Singapore
81;JP;Japan;XX XXXX XXXX
66;TH;Thailand;X XXXX XXXX
65;SG;Singapore;XXXX XXXX
64;NZ;New Zealand
63;PH;Philippines
63;PH;Philippines;XXX XXX XXXX
62;ID;Indonesia
61;AU;Australia
61;AU;Australia;XXX XXX XXX
60;MY;Malaysia
58;VE;Venezuela
57;CO;Colombia
56;CL;Chile
55;BR;Brazil
58;VE;Venezuela;XXX XXX XXXX
57;CO;Colombia;XXX XXX XXXX
56;CL;Chile;X XXXX XXXX
55;BR;Brazil;XX XXXXX XXXX
54;AR;Argentina
53;CU;Cuba
53;CU;Cuba;XXXX XXXX
52;MX;Mexico
51;PE;Peru
51;PE;Peru;XXX XXX XXX
49;DE;Germany
48;PL;Poland
47;NO;Norway
46;SE;Sweden
45;DK;Denmark
44;GB;United Kingdom
48;PL;Poland;XX XXX XXXX
47;NO;Norway;XXXX XXXX
46;SE;Sweden;XX XXX XXXX
45;DK;Denmark;XXXX XXXX
44;GB;United Kingdom;XXXX XXXXXX
43;AT;Austria
42;YL;Y-land
41;CH;Switzerland
40;RO;Romania
41;CH;Switzerland;XX XXX XXXX
40;RO;Romania;XXX XXX XXX
39;IT;Italy
36;HU;Hungary
34;ES;Spain
33;FR;France
32;BE;Belgium
31;NL;Netherlands
30;GR;Greece
27;ZA;South Africa
20;EG;Egypt
7;KZ;Kazakhstan
7;RU;Russian Federation
1;PR;Puerto Rico
1;DO;Dominican Rep.
1;CA;Canada
1;US;USA
36;HU;Hungary;XXX XXX XXX
34;ES;Spain;XXX XXX XXX
33;FR;France;X XX XX XX XX
32;BE;Belgium;XXX XX XX XX
31;NL;Netherlands;X XX XX XX XX
30;GR;Greece;XXX XXX XXXX
27;ZA;South Africa;XX XXX XXXX
20;EG;Egypt;XX XXXX XXXX
7;KZ;Kazakhstan;XXX XXX XX XX
7;RU;Russian Federation;XXX XXX XXXX
1;PR;Puerto Rico;XXX XXX XXXX
1;DO;Dominican Rep.;XXX XXX XXXX
1;CA;Canada;XXX XXX XXXX
1;US;USA;XXX XXX XXXX

View File

@ -75,6 +75,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import java.util.regex.Pattern;
public class AndroidUtilities {
@ -93,6 +94,36 @@ public class AndroidUtilities {
private static Boolean isTablet = null;
private static int adjustOwnerClassGuid = 0;
public static Pattern WEB_URL = null;
static {
try {
final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final Pattern IP_ADDRESS = Pattern.compile(
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9]))");
final String IRI = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
WEB_URL = Pattern.compile(
"((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "(?:" + DOMAIN_NAME + ")"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)");
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
static {
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
leftBaseline = isTablet() ? 80 : 72;
@ -735,7 +766,7 @@ public class AndroidUtilities {
}*/
public static void checkForCrashes(Activity context) {
CrashManager.register(context, BuildVars.HOCKEY_APP_HASH, new CrashManagerListener() {
CrashManager.register(context, BuildVars.DEBUG_VERSION ? BuildVars.HOCKEY_APP_HASH_DEBUG : BuildVars.HOCKEY_APP_HASH, new CrashManagerListener() {
@Override
public boolean includeDeviceData() {
return true;
@ -745,7 +776,7 @@ public class AndroidUtilities {
public static void checkForUpdates(Activity context) {
if (BuildVars.DEBUG_VERSION) {
UpdateManager.register(context, BuildVars.HOCKEY_APP_HASH);
UpdateManager.register(context, BuildVars.DEBUG_VERSION ? BuildVars.HOCKEY_APP_HASH_DEBUG : BuildVars.HOCKEY_APP_HASH);
}
}

View File

@ -327,18 +327,23 @@ public class ApplicationLoader extends Application {
}
private void initPlayServices() {
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId();
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(ApplicationLoader.this);
regid = getRegistrationId();
if (regid.length() == 0) {
registerInBackground();
} else {
sendRegistrationIdToBackend(false);
if (regid.length() == 0) {
registerInBackground();
} else {
sendRegistrationIdToBackend(false);
}
} else {
FileLog.d("tmessages", "No valid Google Play Services APK found.");
}
}
} else {
FileLog.d("tmessages", "No valid Google Play Services APK found.");
}
}, 1000);
}
private boolean checkPlayServices() {

View File

@ -21,6 +21,6 @@ public class AutoMessageHeardReceiver extends BroadcastReceiver {
if (dialog_id == 0 || max_id == 0) {
return;
}
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
}
}

View File

@ -32,6 +32,6 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver {
return;
}
SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, null, null, true, false);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
}
}

View File

@ -10,10 +10,11 @@ package org.telegram.messenger;
public class BuildVars {
public static boolean DEBUG_VERSION = false;
public static int BUILD_VERSION = 654;
public static int BUILD_VERSION = 685;
public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id
public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id
public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here";
public static String HOCKEY_APP_HASH_DEBUG = "your-hockeyapp-api-key-here";
public static String GCM_SENDER_ID = "760348033672";
public static String SEND_LOGS_EMAIL = "email@gmail.com";
public static String BING_SEARCH_KEY = ""; //obtain your own KEY at https://www.bing.com/dev/en-us/dev-center

View File

@ -16,17 +16,18 @@ public class ChatObject {
public static final int CHAT_TYPE_BROADCAST = 1;
public static final int CHAT_TYPE_CHANNEL = 2;
public static final int CHAT_TYPE_USER = 3;
public static final int CHAT_TYPE_MEGAGROUP = 4;
public static boolean isLeftFromChat(TLRPC.Chat chat) {
return chat == null || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || (chat.flags & TLRPC.CHAT_FLAG_USER_LEFT) != 0;
return chat == null || chat instanceof TLRPC.TL_chatEmpty || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || chat.left || chat.deactivated;
}
public static boolean isKickedFromChat(TLRPC.Chat chat) {
return chat == null || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || (chat.flags & TLRPC.CHAT_FLAG_USER_KICKED) != 0;
return chat == null || chat instanceof TLRPC.TL_chatEmpty || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || chat.kicked || chat.deactivated;
}
public static boolean isNotInChat(TLRPC.Chat chat) {
return chat == null || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || (chat.flags & TLRPC.CHAT_FLAG_USER_LEFT) != 0 || (chat.flags & TLRPC.CHAT_FLAG_USER_KICKED) != 0;
return chat == null || chat instanceof TLRPC.TL_chatEmpty || chat instanceof TLRPC.TL_chatForbidden || chat instanceof TLRPC.TL_channelForbidden || chat.left || chat.kicked || chat.deactivated;
}
public static boolean isChannel(TLRPC.Chat chat) {
@ -40,11 +41,11 @@ public class ChatObject {
public static boolean isCanWriteToChannel(int chatId) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(chatId);
return chat != null && ((chat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0 || (chat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) != 0);
return chat != null && (chat.creator || chat.editor || chat.megagroup);
}
public static boolean canWriteToChat(TLRPC.Chat chat) {
return !isChannel(chat) || (chat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0 || (chat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) != 0 || (chat.flags & TLRPC.CHAT_FLAG_IS_BROADCAST) == 0;
return !isChannel(chat) || chat.creator || chat.editor || !chat.broadcast;
}
public static TLRPC.Chat getChatByDialog(long did) {

View File

@ -208,8 +208,8 @@ public class ContactsController {
try {
accounts = am.getAccountsByType("org.telegram.account");
if (accounts != null && accounts.length > 0) {
for (Account c : accounts) {
am.removeAccount(c, null, null);
for (int a = 0; a < accounts.length; a++) {
am.removeAccount(accounts[a], null, null);
}
}
} catch (Exception e) {
@ -221,7 +221,7 @@ public class ContactsController {
if (UserConfig.isClientActivated()) {
if (accounts.length == 1) {
Account acc = accounts[0];
if (!acc.name.equals(UserConfig.getCurrentUser().phone)) {
if (!acc.name.equals("" + UserConfig.getClientUserId())) {
recreateAccount = true;
} else {
currentAccount = acc;
@ -236,12 +236,16 @@ public class ContactsController {
}
}
if (recreateAccount) {
for (Account c : accounts) {
am.removeAccount(c, null, null);
try {
for (int a = 0; a < accounts.length; a++) {
am.removeAccount(accounts[a], null, null);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
if (UserConfig.isClientActivated()) {
try {
currentAccount = new Account(UserConfig.getCurrentUser().phone, "org.telegram.messenger");
currentAccount = new Account("" + UserConfig.getClientUserId(), "org.telegram.messenger");
am.addAccountExplicitly(currentAccount, "", null);
} catch (Exception e) {
FileLog.e("tmessages", e);
@ -254,8 +258,8 @@ public class ContactsController {
try {
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
Account[] accounts = am.getAccountsByType("org.telegram.messenger");
for (Account c : accounts) {
am.removeAccount(c, null, null);
for (int a = 0; a < accounts.length; a++) {
am.removeAccount(accounts[a], null, null);
}
} catch (Exception e) {
e.printStackTrace();
@ -277,7 +281,7 @@ public class ContactsController {
private boolean checkContactsInternal() {
boolean reload = false;
try {
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (!hasContactsPermission()) {
return false;
}
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
@ -334,7 +338,7 @@ public class ContactsController {
private HashMap<Integer, Contact> readContactsFromPhoneBook() {
HashMap<Integer, Contact> contactsMap = new HashMap<>();
try {
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (!hasContactsPermission()) {
return contactsMap;
}
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
@ -1044,7 +1048,7 @@ public class ContactsController {
sortedSectionsArray.add(key);
}
arr.add(value);
if ((user.flags & TLRPC.USER_FLAG_MUTUAL_CONTACT) != 0) {
if (user.mutual_contact) {
arr = sectionsDictMutual.get(key);
if (arr == null) {
arr = new ArrayList<>();
@ -1280,9 +1284,34 @@ public class ContactsController {
sortedUsersSectionsArray = sortedSectionsArray;
}
private boolean hasContactsPermission() {
if (Build.VERSION.SDK_INT >= 23) {
return ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
}
Cursor cursor = null;
try {
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
if (cursor == null || cursor.getCount() == 0) {
return false;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
} finally {
try {
if (cursor != null) {
cursor.close();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
return true;
}
private void performWriteContactsToPhoneBookInternal(ArrayList<TLRPC.TL_contact> contactsArray) {
try {
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (!hasContactsPermission()) {
return;
}
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, currentAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, currentAccount.type).build();
@ -1294,7 +1323,8 @@ public class ContactsController {
}
c1.close();
for (TLRPC.TL_contact u : contactsArray) {
for (int a = 0; a < contactsArray.size(); a++) {
TLRPC.TL_contact u = contactsArray.get(a);
if (!bookContacts.containsKey(u.user_id)) {
TLRPC.User user = MessagesController.getInstance().getUser(u.user_id);
addContactToPhoneBook(user, false);
@ -1486,7 +1516,7 @@ public class ContactsController {
if (currentAccount == null || user == null || user.phone == null || user.phone.length() == 0) {
return -1;
}
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (!hasContactsPermission()) {
return -1;
}
long res = -1;
@ -1536,7 +1566,9 @@ public class ContactsController {
query.add(builder.build());
try {
ContentProviderResult[] result = contentResolver.applyBatch(ContactsContract.AUTHORITY, query);
res = Long.parseLong(result[0].uri.getLastPathSegment());
if (result != null && result.length > 0 && result[0].uri != null) {
res = Long.parseLong(result[0].uri.getLastPathSegment());
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
@ -1547,7 +1579,7 @@ public class ContactsController {
}
private void deleteContactFromPhoneBook(int uid) {
if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (!hasContactsPermission()) {
return;
}
synchronized (observerLock) {

View File

@ -12,9 +12,12 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.concurrent.CountDownLatch;
public class DispatchQueue extends Thread {
public volatile Handler handler = null;
private final Object handlerSyncObject = new Object();
private volatile Handler handler = null;
private CountDownLatch syncLatch = new CountDownLatch(1);
public DispatchQueue(final String threadName) {
setName(threadName);
@ -22,40 +25,24 @@ public class DispatchQueue extends Thread {
}
private void sendMessage(Message msg, int delay) {
if (handler == null) {
try {
synchronized (handlerSyncObject) {
handlerSyncObject.wait();
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if (handler != null) {
try {
syncLatch.await();
if (delay <= 0) {
handler.sendMessage(msg);
} else {
handler.sendMessageDelayed(msg, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void cancelRunnable(Runnable runnable) {
if (handler == null) {
synchronized (handlerSyncObject) {
if (handler == null) {
try {
handlerSyncObject.wait();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
if (handler != null) {
try {
syncLatch.await();
handler.removeCallbacks(runnable);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
@ -64,39 +51,32 @@ public class DispatchQueue extends Thread {
}
public void postRunnable(Runnable runnable, long delay) {
if (handler == null) {
synchronized (handlerSyncObject) {
if (handler == null) {
try {
handlerSyncObject.wait();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
if (handler != null) {
try {
syncLatch.await();
if (delay <= 0) {
handler.post(runnable);
} else {
handler.postDelayed(runnable, delay);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void cleanupQueue() {
if (handler != null) {
try {
syncLatch.await();
handler.removeCallbacksAndMessages(null);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
@Override
public void run() {
Looper.prepare();
synchronized (handlerSyncObject) {
handler = new Handler();
handlerSyncObject.notify();
}
handler = new Handler();
syncLatch.countDown();
Looper.loop();
}
}

View File

@ -266,10 +266,7 @@ public class Emoji {
}
if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) {
canvas.save();
canvas.clipRect(b);
canvas.drawBitmap(emojiBmp[info.page][info.page2], info.rect, b, fullSize ? null : paint);
canvas.restore();
canvas.drawBitmap(emojiBmp[info.page][info.page2], info.rect, b, paint);
}
}

View File

@ -468,7 +468,7 @@ public class FileLoadOperation {
delegate.didFailedLoadingFile(FileLoadOperation.this, 2);
} else {
if (location != null) {
FileLog.e("tmessages", "" + location + " id = " + location.id + " access_hash = " + location.access_hash + " volume_id = " + location.local_id + " secret = " + location.secret);
FileLog.e("tmessages", "" + location + " id = " + location.id + " local_id = " + location.local_id + " access_hash = " + location.access_hash + " volume_id = " + location.volume_id + " secret = " + location.secret);
}
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, 0);

View File

@ -753,7 +753,8 @@ public class FileLoader {
fileLoaderQueue.postRunnable(new Runnable() {
@Override
public void run() {
for (File file : files) {
for (int a = 0; a < files.size(); a++) {
File file = files.get(a);
if (file.exists()) {
try {
if (!file.delete()) {
@ -763,6 +764,16 @@ public class FileLoader {
FileLog.e("tmessages", e);
}
}
try {
File qFile = new File(file.getPath(), "q_" + file.getName());
if (qFile.exists()) {
if (!file.delete()) {
file.deleteOnExit();
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
});

View File

@ -67,6 +67,9 @@ public class FileLog {
}
public static String getNetworkLogPath() {
if (!BuildVars.DEBUG_VERSION) {
return "";
}
try {
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
if (sdCard == null) {

View File

@ -75,7 +75,7 @@ public class ImageLoader {
private HashMap<String, Runnable> retryHttpsTasks = new HashMap<>();
private int currentHttpFileLoadTasksCount = 0;
protected VMRuntimeHack runtimeHack = null;
public VMRuntimeHack runtimeHack = null;
private String ignoreRemoval = null;
private volatile long lastCacheOutTime = 0;
@ -1162,7 +1162,18 @@ public class ImageLoader {
FileLog.e("tmessages", "file system changed");
Runnable r = new Runnable() {
public void run() {
FileLoader.getInstance().setMediaDirs(createMediaPaths());
cacheOutQueue.postRunnable(new Runnable() {
@Override
public void run() {
final HashMap<Integer, File> paths = createMediaPaths();
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
FileLoader.getInstance().setMediaDirs(paths);
}
});
}
});
}
};
if (Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction())) {
@ -1186,7 +1197,35 @@ public class ImageLoader {
filter.addDataScheme("file");
ApplicationLoader.applicationContext.registerReceiver(receiver, filter);
FileLoader.getInstance().setMediaDirs(createMediaPaths());
HashMap<Integer, File> mediaDirs = new HashMap<>();
File cachePath = AndroidUtilities.getCacheDir();
if (!cachePath.isDirectory()) {
try {
cachePath.mkdirs();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
try {
new File(cachePath, ".nomedia").createNewFile();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
FileLoader.getInstance().setMediaDirs(mediaDirs);
cacheOutQueue.postRunnable(new Runnable() {
@Override
public void run() {
final HashMap<Integer, File> paths = createMediaPaths();
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
FileLoader.getInstance().setMediaDirs(paths);
}
});
}
});
}
public HashMap<Integer, File> createMediaPaths() {

View File

@ -46,14 +46,14 @@ public class LocaleController {
public static boolean isRTL = false;
public static int nameDisplayOrder = 1;
private static boolean is24HourFormat = false;
public static FastDateFormat formatterDay;
public static FastDateFormat formatterWeek;
public static FastDateFormat formatterMonth;
public static FastDateFormat formatterYear;
public static FastDateFormat formatterMonthYear;
public static FastDateFormat formatterYearMax;
public static FastDateFormat chatDate;
public static FastDateFormat chatFullDate;
public FastDateFormat formatterDay;
public FastDateFormat formatterWeek;
public FastDateFormat formatterMonth;
public FastDateFormat formatterYear;
public FastDateFormat formatterMonthYear;
public FastDateFormat formatterYearMax;
public FastDateFormat chatDate;
public FastDateFormat chatFullDate;
private HashMap<String, PluralRules> allRules = new HashMap<>();
@ -671,9 +671,9 @@ public class LocaleController {
int dateYear = rightNow.get(Calendar.YEAR);
if (year == dateYear) {
return chatDate.format(date * 1000);
return getInstance().chatDate.format(date * 1000);
}
return chatFullDate.format(date * 1000);
return getInstance().chatFullDate.format(date * 1000);
}
public static String formatDate(long date) {
@ -686,13 +686,13 @@ public class LocaleController {
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return formatterDay.format(new Date(date * 1000));
return getInstance().formatterDay.format(new Date(date * 1000));
} else if (dateDay + 1 == day && year == dateYear) {
return getString("Yesterday", R.string.Yesterday);
} else if (year == dateYear) {
return formatterMonth.format(new Date(date * 1000));
return getInstance().formatterMonth.format(new Date(date * 1000));
} else {
return formatterYear.format(new Date(date * 1000));
return getInstance().formatterYear.format(new Date(date * 1000));
}
} catch (Exception e) {
FileLog.e("tmessages", e);
@ -710,7 +710,7 @@ public class LocaleController {
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("TodayAt", R.string.TodayAt), formatterDay.format(new Date(date * 1000)));
return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("TodayAt", R.string.TodayAt), getInstance().formatterDay.format(new Date(date * 1000)));
/*int diff = (int) (ConnectionsManager.getInstance().getCurrentTime() - date) / 60;
if (diff < 1) {
return LocaleController.getString("LastSeenNow", R.string.LastSeenNow);
@ -720,12 +720,12 @@ public class LocaleController {
return LocaleController.formatPluralString("LastSeenHours", (int) Math.ceil(diff / 60.0f));
}*/
} else if (dateDay + 1 == day && year == dateYear) {
return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("YesterdayAt", R.string.YesterdayAt), formatterDay.format(new Date(date * 1000)));
return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("YesterdayAt", R.string.YesterdayAt), getInstance().formatterDay.format(new Date(date * 1000)));
} else if (year == dateYear) {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterMonth.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000)));
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterMonth.format(new Date(date * 1000)), getInstance().formatterDay.format(new Date(date * 1000)));
return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format);
} else {
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, formatterYear.format(new Date(date * 1000)), formatterDay.format(new Date(date * 1000)));
String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().formatterYear.format(new Date(date * 1000)), getInstance().formatterDay.format(new Date(date * 1000)));
return String.format("%s %s", LocaleController.getString("LastSeenDate", R.string.LastSeenDate), format);
}
} catch (Exception e) {
@ -780,15 +780,15 @@ public class LocaleController {
int dateYear = rightNow.get(Calendar.YEAR);
if (year != dateYear) {
return formatterYear.format(new Date(date * 1000));
return getInstance().formatterYear.format(new Date(date * 1000));
} else {
int dayDiff = dateDay - day;
if(dayDiff == 0 || dayDiff == -1 && (int)(System.currentTimeMillis() / 1000) - date < 60 * 60 * 8) {
return formatterDay.format(new Date(date * 1000));
return getInstance().formatterDay.format(new Date(date * 1000));
} else if(dayDiff > -7 && dayDiff <= -1) {
return formatterWeek.format(new Date(date * 1000));
return getInstance().formatterWeek.format(new Date(date * 1000));
} else {
return formatterMonth.format(new Date(date * 1000));
return getInstance().formatterMonth.format(new Date(date * 1000));
}
}
} catch (Exception e) {

View File

@ -542,13 +542,18 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
shuffleMusic = preferences.getBoolean("shuffleMusic", false);
repeatMode = preferences.getInt("repeatMode", 0);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad);
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);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.musicDidLoaded);
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileDidFailedLoad);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileDidLoaded);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileLoadProgressChanged);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.messagesDeleted);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.removeAllMessagesFromDialog);
NotificationCenter.getInstance().addObserver(MediaController.this, NotificationCenter.musicDidLoaded);
}
});
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
@Override
@ -1117,7 +1122,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
try {
ArrayList<SendMessagesHelper.DelayedMessage> delayedMessages = SendMessagesHelper.getInstance().getDelayedMessages(fileName);
if (delayedMessages != null) {
for (SendMessagesHelper.DelayedMessage delayedMessage : delayedMessages) {
for (int a = 0; a < delayedMessages.size(); a++) {
SendMessagesHelper.DelayedMessage delayedMessage = delayedMessages.get(a);
if (delayedMessage.encryptedChat == null) {
long dialog_id = delayedMessage.obj.getDialogId();
Long lastTime = typingTimes.get(dialog_id);
@ -2477,7 +2483,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
Cursor cursor = null;
try {
if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, "", null, MediaStore.Images.Media.DATE_TAKEN + " DESC");
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, null, null, MediaStore.Images.Media.DATE_TAKEN + " DESC");
if (cursor != null) {
int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID);
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
@ -2540,7 +2546,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
albums.clear();
AlbumEntry allVideosAlbum = null;
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, "", null, MediaStore.Video.Media.DATE_TAKEN + " DESC");
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, null, null, MediaStore.Video.Media.DATE_TAKEN + " DESC");
if (cursor != null) {
int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID);
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID);

View File

@ -21,6 +21,7 @@ import android.text.style.URLSpan;
import android.text.util.Linkify;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.Components.URLSpanBotCommand;
@ -77,6 +78,10 @@ public class MessageObject {
public ArrayList<TextLayoutBlock> textLayoutBlocks;
public MessageObject(TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users, boolean generateLayout) {
this(message, users, null, generateLayout);
}
public MessageObject(TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, boolean generateLayout) {
if (textPaint == null) {
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(0xff000000);
@ -88,7 +93,7 @@ public class MessageObject {
messageOwner = message;
if (message.replyMessage != null) {
replyMessageObject = new MessageObject(message.replyMessage, users, false);
replyMessageObject = new MessageObject(message.replyMessage, users, chats, false);
}
if (message instanceof TLRPC.TL_messageService) {
@ -143,39 +148,56 @@ public class MessageObject {
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatAddUser) {
TLRPC.User whoUser = null;
if (users != null) {
whoUser = users.get(message.action.user_id);
int singleUserId = messageOwner.action.user_id;
if (singleUserId == 0 && messageOwner.action.users.size() == 1) {
singleUserId = messageOwner.action.users.get(0);
}
if (whoUser == null) {
whoUser = MessagesController.getInstance().getUser(message.action.user_id);
}
if (message.to_id.channel_id != 0) {
if (whoUser != null && whoUser.id != UserConfig.getClientUserId()) {
messageText = replaceWithLink(LocaleController.getString("ChannelAddedBy", R.string.ChannelAddedBy), "un1", whoUser);
} else {
messageText = LocaleController.getString("ChannelJoined", R.string.ChannelJoined);
if (singleUserId != 0) {
TLRPC.User whoUser = null;
if (users != null) {
whoUser = users.get(singleUserId);
}
} else {
if (whoUser != null && fromUser != null) {
if (whoUser.id == fromUser.id) {
if (isOut()) {
messageText = LocaleController.getString("ActionAddUserSelfYou", R.string.ActionAddUserSelfYou);
if (whoUser == null) {
whoUser = MessagesController.getInstance().getUser(singleUserId);
}
if (message.to_id.channel_id != 0 && !isMegagroup()) {
if (whoUser != null && whoUser.id != UserConfig.getClientUserId()) {
if (isMegagroup()) {
messageText = replaceWithLink(LocaleController.getString("MegaAddedBy", R.string.MegaAddedBy), "un1", whoUser);
} else {
messageText = replaceWithLink(LocaleController.getString("ActionAddUserSelf", R.string.ActionAddUserSelf), "un1", fromUser);
messageText = replaceWithLink(LocaleController.getString("ChannelAddedBy", R.string.ChannelAddedBy), "un1", whoUser);
}
} else {
if (isOut()) {
messageText = replaceWithLink(LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser), "un2", whoUser);
} else if (message.action.user_id == UserConfig.getClientUserId()) {
messageText = replaceWithLink(LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou), "un1", fromUser);
} else {
messageText = replaceWithLink(LocaleController.getString("ActionAddUser", R.string.ActionAddUser), "un2", whoUser);
messageText = replaceWithLink(messageText, "un1", fromUser);
}
messageText = LocaleController.getString("ChannelJoined", R.string.ChannelJoined);
}
} else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", "").replace("un1", "");
if (whoUser != null && fromUser != null) {
if (whoUser.id == fromUser.id) {
if (isOut()) {
messageText = LocaleController.getString("ActionAddUserSelfYou", R.string.ActionAddUserSelfYou);
} else {
messageText = replaceWithLink(LocaleController.getString("ActionAddUserSelf", R.string.ActionAddUserSelf), "un1", fromUser);
}
} else {
if (isOut()) {
messageText = replaceWithLink(LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser), "un2", whoUser);
} else if (singleUserId == UserConfig.getClientUserId()) {
messageText = replaceWithLink(LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou), "un1", fromUser);
} else {
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", "");
}
}
} else {
if (isOut()) {
messageText = replaceWithLink(LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser), "un2", message.action.users, users);
} else {
messageText = replaceWithLink(LocaleController.getString("ActionAddUser", R.string.ActionAddUser), "un2", message.action.users, users);
messageText = replaceWithLink(messageText, "un1", fromUser);
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatJoinedByLink) {
@ -189,7 +211,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionInviteUser", R.string.ActionInviteUser).replace("un1", "");
}
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
if (message.to_id.channel_id != 0) {
if (message.to_id.channel_id != 0 && !isMegagroup()) {
messageText = LocaleController.getString("ActionChannelChangedPhoto", R.string.ActionChannelChangedPhoto);
} else {
if (isOut()) {
@ -203,7 +225,7 @@ public class MessageObject {
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatEditTitle) {
if (message.to_id.channel_id != 0) {
if (message.to_id.channel_id != 0 && !isMegagroup()) {
messageText = LocaleController.getString("ActionChannelChangedTitle", R.string.ActionChannelChangedTitle).replace("un2", message.action.title);
} else {
if (isOut()) {
@ -217,7 +239,7 @@ public class MessageObject {
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatDeletePhoto) {
if (message.to_id.channel_id != 0) {
if (message.to_id.channel_id != 0 && !isMegagroup()) {
messageText = LocaleController.getString("ActionChannelRemovedPhoto", R.string.ActionChannelRemovedPhoto);
} else {
if (isOut()) {
@ -253,7 +275,13 @@ public class MessageObject {
}
}
} else if (message.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
String date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(((long) message.date) * 1000), LocaleController.formatterDay.format(((long) message.date) * 1000));
String date;
long time = ((long) message.date) * 1000;
if (LocaleController.getInstance().formatterDay != null && LocaleController.getInstance().formatterYear != null) {
date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(time), LocaleController.getInstance().formatterDay.format(time));
} else {
date = "" + message.date;
}
TLRPC.User to_user = UserConfig.getCurrentUser();
if (to_user == null) {
if (users != null) {
@ -315,7 +343,15 @@ public class MessageObject {
} else if (message.action instanceof TLRPC.TL_messageActionCreatedBroadcastList) {
messageText = LocaleController.formatString("YouCreatedBroadcastList", R.string.YouCreatedBroadcastList);
} else if (message.action instanceof TLRPC.TL_messageActionChannelCreate) {
messageText = LocaleController.getString("ActionCreateChannel", R.string.ActionCreateChannel);
if (isMegagroup()) {
messageText = LocaleController.getString("ActionCreateMega", R.string.ActionCreateMega);
} else {
messageText = LocaleController.getString("ActionCreateChannel", R.string.ActionCreateChannel);
}
} else if (message.action instanceof TLRPC.TL_messageActionChatMigrateTo) {
messageText = LocaleController.getString("ActionMigrateFromGroup", R.string.ActionMigrateFromGroup);
} else if (message.action instanceof TLRPC.TL_messageActionChannelMigrateFrom) {
messageText = LocaleController.getString("ActionMigrateFromGroup", R.string.ActionMigrateFromGroup);
}
}
} else if (!isMediaEmpty()) {
@ -353,6 +389,9 @@ public class MessageObject {
} else {
messageText = message.message;
}
if (messageText == null) {
messageText = "";
}
if (generateLayout) {
messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
@ -360,7 +399,7 @@ public class MessageObject {
if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded_old2) {
if (isMediaEmpty()) {
contentType = type = 0;
if (messageText.length() == 0) {
if (messageText == null || messageText.length() == 0) {
messageText = "Empty message";
}
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
@ -423,6 +462,8 @@ public class MessageObject {
dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay);
if (contentType == 1 || contentType == 2 || contentType == 0 || contentType == 8) {
monthKey = String.format("%d_%02d", dateYear, dateMonth);
} else if (contentType == 9) {
//dateKey = "0_0_0";
}
if (messageOwner.message != null && messageOwner.id < 0 && messageOwner.message.length() > 6 && messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
@ -513,13 +554,50 @@ public class MessageObject {
}
}
public CharSequence replaceWithLink(CharSequence source, String param, TLRPC.User user) {
public CharSequence replaceWithLink(CharSequence source, String param, ArrayList<Integer> uids, AbstractMap<Integer, TLRPC.User> usersDict) {
int start = TextUtils.indexOf(source, param);
if (start >= 0) {
String name = UserObject.getUserName(user);
URLSpanNoUnderlineBold span = new URLSpanNoUnderlineBold("" + user.id);
SpannableStringBuilder names = new SpannableStringBuilder("");
for (int a = 0; a < uids.size(); a++) {
TLRPC.User user = null;
if (usersDict != null) {
user = usersDict.get(uids.get(a));
}
if (user == null) {
user = MessagesController.getInstance().getUser(uids.get(a));
}
if (user != null) {
String name = UserObject.getUserName(user);
start = names.length();
if (names.length() != 0) {
names.append(", ");
}
names.append(name);
names.setSpan(new URLSpanNoUnderlineBold("" + user.id), start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
return TextUtils.replace(source, new String[]{param}, new CharSequence[]{names});
}
return source;
}
public CharSequence replaceWithLink(CharSequence source, String param, TLObject object) {
int start = TextUtils.indexOf(source, param);
if (start >= 0) {
String name;
int id;
if (object instanceof TLRPC.User) {
name = UserObject.getUserName((TLRPC.User) object);
id = ((TLRPC.User) object).id;
} else if (object instanceof TLRPC.Chat) {
name = ((TLRPC.Chat) object).title;
id = -((TLRPC.Chat) object).id;
} else {
name = "";
id = 0;
}
SpannableStringBuilder builder = new SpannableStringBuilder(TextUtils.replace(source, new String[]{param}, new String[]{name}));
builder.setSpan(span, start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new URLSpanNoUnderlineBold("" + id), start, start + name.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return builder;
}
return source;
@ -647,6 +725,7 @@ public class MessageObject {
FileLog.e("tmessages", e);
}
}
linkDescription = Emoji.replaceEmoji(linkDescription, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
}
@ -662,12 +741,12 @@ public class MessageObject {
} catch (Exception e) {
FileLog.e("tmessages", e);
}
addUsernamesAndHashtags(caption);
addUsernamesAndHashtags(caption, true);
}
}
}
private static void addUsernamesAndHashtags(CharSequence charSequence) {
private static void addUsernamesAndHashtags(CharSequence charSequence, boolean botCommands) {
try {
if (urlPattern == null) {
urlPattern = Pattern.compile("(^|\\s)/[a-zA-Z@\\d_]{1,255}|(^|\\s)@[a-zA-Z\\d_]{5,32}|(^|\\s)#[\\w\\.]+");
@ -679,20 +758,29 @@ public class MessageObject {
if (charSequence.charAt(start) != '@' && charSequence.charAt(start) != '#' && charSequence.charAt(start) != '/') {
start++;
}
URLSpanNoUnderline url;
URLSpanNoUnderline url = null;
if (charSequence.charAt(start) == '/') {
url = new URLSpanBotCommand(charSequence.subSequence(start, end).toString());
if (botCommands) {
url = new URLSpanBotCommand(charSequence.subSequence(start, end).toString());
}
} else {
url = new URLSpanNoUnderline(charSequence.subSequence(start, end).toString());
}
((Spannable) charSequence).setSpan(url, start, end, 0);
if (url != null) {
((Spannable) charSequence).setSpan(url, start, end, 0);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public static void addLinks(CharSequence messageText) {
addLinks(messageText, true);
}
public static void addLinks(CharSequence messageText, boolean botCommands) {
if (messageText instanceof Spannable && containsUrls(messageText)) {
if (messageText.length() < 100) {
try {
@ -707,7 +795,7 @@ public class MessageObject {
FileLog.e("tmessages", e);
}
}
addUsernamesAndHashtags(messageText);
addUsernamesAndHashtags(messageText, botCommands);
}
}
@ -755,7 +843,7 @@ public class MessageObject {
spannable.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (entity instanceof TLRPC.TL_messageEntityItalic) {
spannable.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (entity instanceof TLRPC.TL_messageEntityCode) {
} else if (entity instanceof TLRPC.TL_messageEntityCode || entity instanceof TLRPC.TL_messageEntityPre) {
spannable.setSpan(new TypefaceSpan(Typeface.MONOSPACE), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (!useManualParse) {
String url = messageOwner.message.substring(entity.offset, entity.offset + entity.length);
@ -940,23 +1028,23 @@ public class MessageObject {
}
public boolean isOut() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
return messageOwner.out;
}
public boolean isOutOwner() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_OUT) != 0 && messageOwner.from_id > 0;
return messageOwner.out && messageOwner.from_id > 0;
}
public boolean isUnread() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
return messageOwner.unread;
}
public boolean isContentUnread() {
return (messageOwner.flags & TLRPC.MESSAGE_FLAG_CONTENT_UNREAD) != 0;
return messageOwner.media_unread;
}
public void setIsRead() {
messageOwner.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD;
messageOwner.unread = false;
}
public int getUnradFlags() {
@ -965,17 +1053,17 @@ public class MessageObject {
public static int getUnreadFlags(TLRPC.Message message) {
int flags = 0;
if ((message.flags & TLRPC.MESSAGE_FLAG_UNREAD) == 0) {
if (!message.unread) {
flags |= 1;
}
if ((message.flags & TLRPC.MESSAGE_FLAG_CONTENT_UNREAD) == 0) {
if (!message.media_unread) {
flags |= 2;
}
return flags;
}
public void setContentIsRead() {
messageOwner.flags &= ~TLRPC.MESSAGE_FLAG_CONTENT_UNREAD;
messageOwner.media_unread = false;
}
public int getId() {
@ -983,66 +1071,73 @@ public class MessageObject {
}
public boolean isSecretPhoto() {
return messageOwner instanceof TLRPC.TL_message_secret && messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60;
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_messageMediaPhoto && messageOwner.ttl > 0 && messageOwner.ttl <= 60 ||
messageOwner.media instanceof TLRPC.TL_messageMediaAudio ||
messageOwner.media instanceof TLRPC.TL_messageMediaVideo);
}
public static void setUnreadFlags(TLRPC.Message message, int flag) {
if ((flag & 1) == 0) {
message.flags |= TLRPC.MESSAGE_FLAG_UNREAD;
} else {
message.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD;
}
if ((flag & 2) == 0) {
message.flags |= TLRPC.MESSAGE_FLAG_CONTENT_UNREAD;
} else {
message.flags &= ~TLRPC.MESSAGE_FLAG_CONTENT_UNREAD;
}
message.unread = (flag & 1) == 0;
message.media_unread = (flag & 2) == 0;
}
public static boolean isUnread(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_UNREAD) != 0;
return message.unread;
}
public static boolean isContentUnread(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_CONTENT_UNREAD) != 0;
return message.media_unread;
}
public boolean isImportant() {
return isImportant(messageOwner);
}
public boolean isMegagroup() {
return isMegagroup(messageOwner);
}
public static boolean isImportant(TLRPC.Message message) {
return message.to_id.channel_id != 0 && (message.from_id <= 0 || (message.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0 || (message.flags & TLRPC.MESSAGE_FLAG_OUT) != 0 || (message.flags & TLRPC.MESSAGE_FLAG_HAS_FROM_ID) == 0);
if (isMegagroup(message)) {
return message.from_id <= 0;
}
return message.to_id.channel_id != 0 && (message.from_id <= 0 || message.mentioned || message.out || (message.flags & TLRPC.MESSAGE_FLAG_HAS_FROM_ID) == 0);
}
public static boolean isMegagroup(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_MEGAGROUP) != 0;
}
public static boolean isOut(TLRPC.Message message) {
return (message.flags & TLRPC.MESSAGE_FLAG_OUT) != 0;
return message.out;
}
public long getDialogId() {
if (messageOwner.dialog_id == 0) {
if (messageOwner.to_id.chat_id != 0) {
if (messageOwner.to_id.chat_id < 0) {
messageOwner.dialog_id = AndroidUtilities.makeBroadcastId(messageOwner.to_id.chat_id);
return getDialogId(messageOwner);
}
public static long getDialogId(TLRPC.Message message) {
if (message.dialog_id == 0 && message.to_id != null) {
if (message.to_id.chat_id != 0) {
if (message.to_id.chat_id < 0) {
message.dialog_id = AndroidUtilities.makeBroadcastId(message.to_id.chat_id);
} else {
messageOwner.dialog_id = -messageOwner.to_id.chat_id;
message.dialog_id = -message.to_id.chat_id;
}
} else if (messageOwner.to_id.channel_id != 0) {
messageOwner.dialog_id = -messageOwner.to_id.channel_id;
} else if (isOut()) {
messageOwner.dialog_id = messageOwner.to_id.user_id;
} else if (message.to_id.channel_id != 0) {
message.dialog_id = -message.to_id.channel_id;
} else if (isOut(message)) {
message.dialog_id = message.to_id.user_id;
} else {
messageOwner.dialog_id = messageOwner.from_id;
message.dialog_id = message.from_id;
}
}
return messageOwner.dialog_id;
return message.dialog_id;
}
public boolean isSending() {
@ -1274,6 +1369,9 @@ public class MessageObject {
}
public static boolean canDeleteMessage(TLRPC.Message message, TLRPC.Chat chat) {
if (message.id < 0) {
return true;
}
if (chat == null && message.to_id.channel_id != 0) {
chat = MessagesController.getInstance().getChat(message.to_id.channel_id);
}
@ -1281,13 +1379,13 @@ public class MessageObject {
if (message.id == 1) {
return false;
}
if ((chat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0) {
if (chat.creator) {
return true;
} else if ((chat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) != 0) {
} else if (chat.editor) {
if (isOut(message) || message.from_id > 0) {
return true;
}
} else if ((chat.flags & TLRPC.CHAT_FLAG_USER_IS_MODERATOR) != 0) {
} else if (chat.moderator) {
if (message.from_id > 0) {
return true;
}

View File

@ -1,19 +1,20 @@
package org.telegram.messenger;
import android.app.Activity;
import android.net.Uri;
import android.util.Log;
import net.hockeyapp.android.Constants;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import net.hockeyapp.android.utils.SimpleMultipartEntity;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.UUID;
@ -24,7 +25,7 @@ public class NativeCrashManager {
for (String dumpFilename : filenames) {
String logFilename = createLogFile();
if (logFilename != null) {
uploadDumpAndLog(activity, BuildVars.HOCKEY_APP_HASH, dumpFilename, logFilename);
uploadDumpAndLog(activity, BuildVars.DEBUG_VERSION ? BuildVars.HOCKEY_APP_HASH_DEBUG : BuildVars.HOCKEY_APP_HASH, dumpFilename, logFilename);
}
}
}
@ -61,17 +62,29 @@ public class NativeCrashManager {
@Override
public void run() {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://rink.hockeyapp.net/api/2/apps/" + identifier + "/crashes/upload");
MultipartEntity entity = new MultipartEntity();
File dumpFile = new File(Constants.FILES_PATH, dumpFilename);
entity.addPart("attachment0", new FileBody(dumpFile));
File logFile = new File(Constants.FILES_PATH, logFilename);
entity.addPart("log", new FileBody(logFile));
httpPost.setEntity(entity);
httpClient.execute(httpPost);
} catch (Exception e) {
FileLog.e("tmessages", e);
SimpleMultipartEntity entity = new SimpleMultipartEntity();
entity.writeFirstBoundaryIfNeeds();
Uri attachmentUri = Uri.fromFile(new File(Constants.FILES_PATH, dumpFilename));
InputStream input = activity.getContentResolver().openInputStream(attachmentUri);
entity.addPart("attachment0", attachmentUri.getLastPathSegment(), input, false);
attachmentUri = Uri.fromFile(new File(Constants.FILES_PATH, logFilename));
input = activity.getContentResolver().openInputStream(attachmentUri);
entity.addPart("log", attachmentUri.getLastPathSegment(), input, false);
entity.writeLastBoundaryIfNeeds();
HttpURLConnection urlConnection = (HttpURLConnection) new URL("https://rink.hockeyapp.net/api/2/apps/" + identifier + "/crashes/upload").openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", entity.getContentType());
urlConnection.setRequestProperty("Content-Length", String.valueOf(entity.getContentLength()));
urlConnection.getOutputStream().write(entity.getOutputStream().toByteArray());
urlConnection.connect();
} catch (IOException e) {
e.printStackTrace();
} finally {
activity.deleteFile(logFilename);
activity.deleteFile(dumpFilename);

View File

@ -23,7 +23,7 @@ import java.util.zip.ZipFile;
public class NativeLoader {
private final static int LIB_VERSION = 14;
private final static int LIB_VERSION = 15;
private final static String LIB_NAME = "tmessages." + LIB_VERSION;
private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so";
private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so";

View File

@ -195,6 +195,87 @@ public class NotificationsController {
});
}
public void removeNotificationsForDialog(long did) {
NotificationsController.getInstance().processReadMessages(null, did, 0, Integer.MAX_VALUE, false);
HashMap<Long, Integer> dialogsToUpdate = new HashMap<>();
dialogsToUpdate.put(did, 0);
NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate);
}
public void removeDeletedMessagesFromNotifications(final SparseArray<ArrayList<Integer>> deletedMessages) {
final ArrayList<MessageObject> popupArray = popupMessages.isEmpty() ? null : new ArrayList<>(popupMessages);
notificationsQueue.postRunnable(new Runnable() {
@Override
public void run() {
int old_unread_count = total_unread_count;
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
for (int a = 0; a < deletedMessages.size(); a++) {
int key = deletedMessages.keyAt(a);
long dialog_id = -key;
ArrayList<Integer> mids = deletedMessages.get(key);
Integer currentCount = pushDialogs.get(dialog_id);
if (currentCount == null) {
currentCount = 0;
}
Integer newCount = currentCount;
for (int b = 0; b < mids.size(); b++) {
long mid = mids.get(b);
mid |= ((long) key) << 32;
MessageObject messageObject = pushMessagesDict.get(mid);
if (messageObject != null) {
pushMessagesDict.remove(mid);
delayedPushMessages.remove(messageObject);
pushMessages.remove(messageObject);
if (isPersonalMessage(messageObject)) {
personal_count--;
}
if (popupArray != null) {
popupArray.remove(messageObject);
}
newCount--;
}
}
if (newCount <= 0) {
newCount = 0;
smartNotificationsDialogs.remove(dialog_id);
}
if (!newCount.equals(currentCount)) {
total_unread_count -= currentCount;
total_unread_count += newCount;
pushDialogs.put(dialog_id, newCount);
}
if (newCount == 0) {
pushDialogs.remove(dialog_id);
pushDialogsOverrideMention.remove(dialog_id);
if (popupArray != null && pushMessages.isEmpty() && !popupArray.isEmpty()) {
popupArray.clear();
}
}
}
if (popupArray != null) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
popupMessages = popupArray;
}
});
}
if (old_unread_count != total_unread_count) {
if (!notifyCheck) {
delayedPushMessages.clear();
showOrUpdateNotification(notifyCheck);
} else {
scheduleNotificationDelay(lastOnlineFromOtherDevice > ConnectionsManager.getInstance().getCurrentTime());
}
}
notifyCheck = false;
if (preferences.getBoolean("badgeNumber", true)) {
setBadge(total_unread_count);
}
}
});
}
public void processReadMessages(final SparseArray<Long> inbox, final long dialog_id, final int max_date, final int max_id, final boolean isPopup) {
final ArrayList<MessageObject> popupArray = popupMessages.isEmpty() ? null : new ArrayList<>(popupMessages);
notificationsQueue.postRunnable(new Runnable() {
@ -314,7 +395,7 @@ public class NotificationsController {
playInChatSound();
continue;
}
if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) {
if (messageObject.messageOwner.mentioned) {
dialog_id = messageObject.messageOwner.from_id;
}
if (isPersonalMessage(messageObject)) {
@ -490,7 +571,7 @@ public class NotificationsController {
}
long dialog_id = messageObject.getDialogId();
long original_dialog_id = dialog_id;
if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) {
if (messageObject.messageOwner.mentioned) {
dialog_id = messageObject.messageOwner.from_id;
}
Boolean value = settingsCache.get(dialog_id);
@ -650,7 +731,7 @@ public class NotificationsController {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
msg = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, name);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
String date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(((long) messageObject.messageOwner.date) * 1000), LocaleController.formatterDay.format(((long) messageObject.messageOwner.date) * 1000));
String date = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().formatterDay.format(((long) messageObject.messageOwner.date) * 1000));
msg = LocaleController.formatString("NotificationUnrecognizedDevice", R.string.NotificationUnrecognizedDevice, UserConfig.getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address);
}
} else {
@ -690,35 +771,54 @@ public class NotificationsController {
if (preferences.getBoolean("EnablePreviewGroup", true)) {
if (messageObject.messageOwner instanceof TLRPC.TL_messageService) {
if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) {
if (messageObject.messageOwner.to_id.channel_id != 0) {
TLRPC.User user = MessagesController.getInstance().getUser(messageObject.messageOwner.action.user_id);
if (user != null) {
name = UserObject.getUserName(user);
} else {
name = "";
}
msg = LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title);
} else {
if (messageObject.messageOwner.action.user_id == UserConfig.getClientUserId()) {
msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title);
} else {
TLRPC.User u2 = MessagesController.getInstance().getUser(messageObject.messageOwner.action.user_id);
if (u2 == null) {
return null;
}
if (from_id == u2.id) {
msg = LocaleController.formatString("NotificationGroupAddSelf", R.string.NotificationGroupAddSelf, name, chat.title);
int singleUserId = messageObject.messageOwner.action.user_id;
if (singleUserId == 0 && messageObject.messageOwner.action.users.size() == 1) {
singleUserId = messageObject.messageOwner.action.users.get(0);
}
if (singleUserId != 0) {
if (messageObject.messageOwner.to_id.channel_id != 0 && !messageObject.isMegagroup()) {
TLRPC.User user = MessagesController.getInstance().getUser(singleUserId);
if (user != null) {
name = UserObject.getUserName(user);
} else {
msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2));
name = "";
}
msg = LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title);
} else {
if (singleUserId == UserConfig.getClientUserId()) {
msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title);
} else {
TLRPC.User u2 = MessagesController.getInstance().getUser(singleUserId);
if (u2 == null) {
return null;
}
if (from_id == u2.id) {
msg = LocaleController.formatString("NotificationGroupAddSelf", R.string.NotificationGroupAddSelf, name, chat.title);
} else {
msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, UserObject.getUserName(u2));
}
}
}
} else {
StringBuilder names = new StringBuilder("");
for (int a = 0; a < messageObject.messageOwner.action.users.size(); a++) {
TLRPC.User user = MessagesController.getInstance().getUser(messageObject.messageOwner.action.users.get(a));
if (user != null) {
String name2 = UserObject.getUserName(user);
if (names.length() != 0) {
names.append(", ");
}
names.append(name2);
}
}
msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, name, chat.title, names.toString());
}
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink) {
msg = LocaleController.formatString("NotificationInvitedToGroupByLink", R.string.NotificationInvitedToGroupByLink, name, chat.title);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) {
msg = LocaleController.formatString("NotificationEditedGroupName", R.string.NotificationEditedGroupName, name, messageObject.messageOwner.action.title);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeletePhoto) {
if (messageObject.messageOwner.to_id.channel_id != 0) {
if (messageObject.messageOwner.to_id.channel_id != 0 && !messageObject.isMegagroup()) {
msg = LocaleController.formatString("ChannelPhotoEditNotification", R.string.ChannelPhotoEditNotification, chat.title);
} else {
msg = LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, name, chat.title);
@ -739,9 +839,13 @@ public class NotificationsController {
msg = messageObject.messageText.toString();
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelCreate) {
msg = messageObject.messageText.toString();
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatMigrateTo) {
msg = LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, chat.title);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom) {
msg = LocaleController.formatString("ActionMigrateFromGroupNotify", R.string.ActionMigrateFromGroupNotify, messageObject.messageOwner.action.title);
}
} else {
if (ChatObject.isChannel(chat)) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
if (from_id < 0) {
if (messageObject.isMediaEmpty()) {
if (!shortMessage && messageObject.messageOwner.message != null && messageObject.messageOwner.message.length() != 0) {
@ -921,7 +1025,7 @@ public class NotificationsController {
notificationsQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (lastSoundPlay > System.currentTimeMillis() - 500) {
if (Math.abs(System.currentTimeMillis() - lastSoundPlay) <= 500) {
return;
}
try {
@ -992,7 +1096,7 @@ public class NotificationsController {
long dialog_id = lastMessageObject.getDialogId();
long override_dialog_id = dialog_id;
if ((lastMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) {
if (lastMessageObject.messageOwner.mentioned) {
override_dialog_id = lastMessageObject.messageOwner.from_id;
}
int mid = lastMessageObject.getId();
@ -1158,7 +1262,7 @@ public class NotificationsController {
String name;
boolean replace = true;
if ((int)dialog_id == 0 || pushDialogs.size() > 1 || AndroidUtilities.needShowPasscode(false) || UserConfig.isWaitingForPasscodeEnter) {
if ((int) dialog_id == 0 || pushDialogs.size() > 1 || AndroidUtilities.needShowPasscode(false) || UserConfig.isWaitingForPasscodeEnter) {
name = LocaleController.getString("AppName", R.string.AppName);
replace = false;
} else {
@ -1348,10 +1452,24 @@ public class NotificationsController {
continue;
}
}
if (chat != null) {
name = chat.title;
TLRPC.FileLocation photoPath = null;
if (AndroidUtilities.needShowPasscode(false) || UserConfig.isWaitingForPasscodeEnter) {
name = LocaleController.getString("AppName", R.string.AppName);
} else {
name = UserObject.getUserName(user);
if (chat != null) {
name = chat.title;
} else {
name = UserObject.getUserName(user);
}
if (chat != null) {
if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) {
photoPath = chat.photo.photo_small;
}
} else {
if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) {
photoPath = user.photo.photo_small;
}
}
}
Integer notificationIdWear = oldIdsWear.get(dialog_id);
@ -1380,7 +1498,7 @@ public class NotificationsController {
NotificationCompat.Action wearReplyAction = null;
if (!ChatObject.isChannel(chat)) {
if (!ChatObject.isChannel(chat) && !AndroidUtilities.needShowPasscode(false) && !UserConfig.isWaitingForPasscodeEnter) {
Intent msgReplyIntent = new Intent();
msgReplyIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
msgReplyIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_REPLY");
@ -1424,17 +1542,6 @@ public class NotificationsController {
unreadConvBuilder.addMessage(message);
}
TLRPC.FileLocation photoPath = null;
if (chat != null) {
if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) {
photoPath = chat.photo.photo_small;
}
} else {
if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) {
photoPath = user.photo.photo_small;
}
}
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE);
intent.setFlags(32768);
@ -1496,7 +1603,7 @@ public class NotificationsController {
@Override
public void run() {
try {
if (lastSoundOutPlay > System.currentTimeMillis() - 100) {
if (Math.abs(System.currentTimeMillis() - lastSoundOutPlay) <= 100) {
return;
}
lastSoundOutPlay = System.currentTimeMillis();

View File

@ -80,7 +80,9 @@ public class SecretChatHelper {
newMsg.action.encryptedAction = decryptedMessage;
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.getClientUserId();
newMsg.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_OUT | TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMsg.unread = true;
newMsg.out = true;
newMsg.flags = TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMsg.dialog_id = ((long) encryptedChat.id) << 32;
newMsg.to_id = new TLRPC.TL_peerUser();
newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING;
@ -869,7 +871,8 @@ public class SecretChatHelper {
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.random_id = random_id;
newMessage.to_id.user_id = UserConfig.getClientUserId();
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_HAS_MEDIA | TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_HAS_MEDIA | TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMessage.dialog_id = ((long) chat.id) << 32;
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) {
newMessage.media = new TLRPC.TL_messageMediaEmpty();
@ -1043,7 +1046,8 @@ public class SecretChatHelper {
}
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
UserConfig.saveConfig(false);
newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMessage.unread = true;
newMessage.flags = TLRPC.MESSAGE_FLAG_HAS_FROM_ID;
newMessage.date = date;
newMessage.from_id = from_id;
newMessage.to_id = new TLRPC.TL_peerUser();

View File

@ -250,7 +250,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
String file = (String) args[1];
ArrayList<DelayedMessage> arr = delayedMessages.get(path);
if (arr != null) {
for (final DelayedMessage message : arr) {
for (int a = 0; a < arr.size(); a++) {
final DelayedMessage message = arr.get(a);
if (message.type == 0) {
String md5 = Utilities.MD5(message.httpLocation) + ".jpg";
final File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), md5);
@ -525,7 +526,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
public void sendMessage(TLRPC.User user, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, null, null, null, null, null, user, null, null, null, peer, false, null, reply_to_msg, null, true, asAdmin);
sendMessage(null, null, null, null, null, user, null, null, null, peer, null, reply_to_msg, null, true, asAdmin, null);
}
public void sendMessage(ArrayList<MessageObject> messages, final long peer, boolean asAdmin) {
@ -534,11 +535,15 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
int lower_id = (int) peer;
final TLRPC.Peer to_id = MessagesController.getPeer((int) peer);
boolean isMegagroup = false;
if (lower_id > 0) {
TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id);
if (sendToUser == null) {
return;
}
} else {
TLRPC.Chat chat = MessagesController.getInstance().getChat(-lower_id);
isMegagroup = ChatObject.isChannel(chat) && chat.megagroup;
}
ArrayList<MessageObject> objArr = new ArrayList<>();
@ -546,7 +551,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
ArrayList<Long> randomIds = new ArrayList<>();
ArrayList<Integer> ids = new ArrayList<>();
HashMap<Long, TLRPC.Message> messagesByRandomIds = new HashMap<>();
TLRPC.InputPeer inputPeer = MessagesController.getInputPeer((int) peer);
TLRPC.InputPeer inputPeer = MessagesController.getInputPeer(lower_id);
long lastDialogId = 0;
for (int a = 0; a < messages.size(); a++) {
MessageObject msgObj = messages.get(a);
if (msgObj.getId() <= 0) {
@ -571,6 +577,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (newMsg.media != null) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA;
}
if (isMegagroup) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP;
}
newMsg.message = msgObj.messageOwner.message;
newMsg.fwd_msg_id = msgObj.getId();
newMsg.attachPath = msgObj.messageOwner.attachPath;
@ -582,8 +591,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.attachPath = "";
}
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.flags |= TLRPC.MESSAGE_FLAG_OUT;
if (asAdmin && to_id.channel_id != 0) {
newMsg.out = true;
if (asAdmin && to_id.channel_id != 0 && !isMegagroup) {
newMsg.from_id = -to_id.channel_id;
} else {
newMsg.from_id = UserConfig.getClientUserId();
@ -597,10 +606,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
ids.add(newMsg.fwd_msg_id);
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
if (newMsg.media instanceof TLRPC.TL_messageMediaAudio) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_CONTENT_UNREAD;
newMsg.media_unread = true;
}
if (inputPeer instanceof TLRPC.TL_inputPeerChannel) {
if (asAdmin) {
if (asAdmin && !isMegagroup) {
newMsg.views = 1;
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS;
}
@ -609,18 +618,22 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.views = msgObj.messageOwner.views;
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS;
}
newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD;
newMsg.unread = true;
}
newMsg.dialog_id = peer;
newMsg.to_id = to_id;
if (msgObj.messageOwner.to_id instanceof TLRPC.TL_peerChannel) {
newMsg.ttl = -msgObj.messageOwner.to_id.channel_id;
}
MessageObject newMsgObj = new MessageObject(newMsg, null, true);
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING;
objArr.add(newMsgObj);
arr.add(newMsg);
putToSendingMessages(newMsg);
boolean differentDialog = false;
if (arr.size() == 100 || a == messages.size() - 1) {
if (arr.size() == 100 || a == messages.size() - 1 || a != messages.size() - 1 && messages.get(a + 1).getDialogId() != msgObj.getDialogId()) {
MessagesStorage.getInstance().putMessages(new ArrayList<>(arr), false, true, false, 0);
MessagesController.getInstance().updateInterfaceWithMessages(peer, objArr);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
@ -635,12 +648,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
req.random_id = randomIds;
req.id = ids;
if (asAdmin && req.to_peer.channel_id != 0) {
req.flags |= 16;
if (asAdmin && req.to_peer.channel_id != 0 && !isMegagroup) {
req.broadcast = true;
}
final ArrayList<TLRPC.Message> newMsgObjArr = arr;
final HashMap<Long, TLRPC.Message> messagesByRandomIdsFinal = messagesByRandomIds;
final boolean isMegagroupFinal = isMegagroup;
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, final TLRPC.TL_error error) {
@ -655,7 +669,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
a--;
}
}
for (TLRPC.Update update : updates.updates) {
for (int a = 0; a < updates.updates.size(); a++) {
TLRPC.Update update = updates.updates.get(a);
if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateNewChannelMessage) {
TLRPC.Message message;
if (update instanceof TLRPC.TL_updateNewMessage) {
@ -664,6 +679,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
} else {
message = ((TLRPC.TL_updateNewChannelMessage) update).message;
MessagesController.getInstance().processNewChannelDifferenceParams(update.pts, update.pts_count, message.to_id.channel_id);
if (isMegagroupFinal) {
message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP;
}
}
Long random_id = newMessagesByIds.get(message.id);
if (random_id != null) {
@ -738,35 +756,35 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
}
public void sendMessage(MessageObject message, boolean asAdmin) {
sendMessage(null, null, null, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath, null, null, true, asAdmin);
public void sendMessage(MessageObject retryMessageObject, boolean asAdmin) {
sendMessage(null, null, null, null, null, null, null, null, null, retryMessageObject.getDialogId(), retryMessageObject.messageOwner.attachPath, null, null, true, asAdmin, retryMessageObject);
}
public void sendMessage(TLRPC.TL_document document, String originalPath, String path, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, null, null, null, null, null, null, document, null, originalPath, peer, false, path, reply_to_msg, null, true, asAdmin);
sendMessage(null, null, null, null, null, null, document, null, originalPath, peer, path, reply_to_msg, null, true, asAdmin, null);
}
public void sendMessage(String message, long peer, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, boolean asAdmin) {
sendMessage(message, null, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, webPage, searchLinks, asAdmin);
sendMessage(message, null, null, null, null, null, null, null, null, peer, null, reply_to_msg, webPage, searchLinks, asAdmin, null);
}
public void sendMessage(TLRPC.MessageMedia location, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, location, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg, null, true, asAdmin);
sendMessage(null, location, null, null, null, null, null, null, null, peer, null, reply_to_msg, null, true, asAdmin, null);
}
public void sendMessage(TLRPC.TL_photo photo, String originalPath, String path, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, null, photo, null, null, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true, asAdmin);
sendMessage(null, null, photo, null, null, null, null, null, originalPath, peer, path, reply_to_msg, null, true, asAdmin, null);
}
public void sendMessage(TLRPC.TL_video video, VideoEditedInfo videoEditedInfo, String originalPath, String path, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, null, null, video, videoEditedInfo, null, null, null, null, originalPath, peer, false, path, reply_to_msg, null, true, asAdmin);
sendMessage(null, null, null, video, videoEditedInfo, null, null, null, originalPath, peer, path, reply_to_msg, null, true, asAdmin, null);
}
public void sendMessage(TLRPC.TL_audio audio, String path, long peer, MessageObject reply_to_msg, boolean asAdmin) {
sendMessage(null, null, null, null, null, null, null, null, audio, null, peer, false, path, reply_to_msg, null, true, asAdmin);
sendMessage(null, null, null, null, null, null, null, audio, null, peer, path, reply_to_msg, null, true, asAdmin, null);
}
private void sendMessage(String message, TLRPC.MessageMedia location, TLRPC.TL_photo photo, TLRPC.TL_video video, VideoEditedInfo videoEditedInfo, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, boolean asAdmin) {
private void sendMessage(String message, TLRPC.MessageMedia location, TLRPC.TL_photo photo, TLRPC.TL_video video, VideoEditedInfo videoEditedInfo, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, boolean asAdmin, MessageObject retryMessageObject) {
if (peer == 0) {
return;
}
@ -782,57 +800,54 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (lower_id == 0) {
encryptedChat = MessagesController.getInstance().getEncryptedChat(high_id);
if (encryptedChat == null) {
if (msgObj != null) {
MessagesStorage.getInstance().markMessageAsSendError(msgObj.messageOwner);
msgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, msgObj.getId());
processSentMessage(msgObj.getId());
if (retryMessageObject != null) {
MessagesStorage.getInstance().markMessageAsSendError(retryMessageObject.messageOwner);
retryMessageObject.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, retryMessageObject.getId());
processSentMessage(retryMessageObject.getId());
}
return;
}
} else if (asAdmin && sendToPeer instanceof TLRPC.TL_inputPeerChannel) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(sendToPeer.channel_id);
if (chat.megagroup) {
asAdmin = false;
}
}
try {
if (retry) {
newMsg = msgObj.messageOwner;
if (retryMessageObject != null) {
newMsg = retryMessageObject.messageOwner;
if (msgObj.type == 0) {
if (msgObj.isForwarded()) {
type = 4;
} else {
if (retryMessageObject.isForwarded()) {
type = 4;
} else {
if (retryMessageObject.type == 0) {
message = newMsg.message;
type = 0;
}
} else if (msgObj.type == 4) {
location = newMsg.media;
type = 1;
} else if (msgObj.type == 1) {
if (msgObj.isForwarded()) {
type = 4;
} else {
} else if (retryMessageObject.type == 4) {
location = newMsg.media;
type = 1;
} else if (retryMessageObject.type == 1) {
photo = (TLRPC.TL_photo) newMsg.media.photo;
type = 2;
}
} else if (msgObj.type == 3) {
if (msgObj.isForwarded()) {
type = 4;
} else {
} else if (retryMessageObject.type == 3) {
type = 3;
video = (TLRPC.TL_video) newMsg.media.video;
} else if (retryMessageObject.type == 12) {
user = new TLRPC.TL_userRequest_old2();
user.phone = newMsg.media.phone_number;
user.first_name = newMsg.media.first_name;
user.last_name = newMsg.media.last_name;
user.id = newMsg.media.user_id;
type = 6;
} else if (retryMessageObject.type == 8 || retryMessageObject.type == 9 || retryMessageObject.type == 13) {
document = (TLRPC.TL_document) newMsg.media.document;
type = 7;
} else if (retryMessageObject.type == 2) {
audio = (TLRPC.TL_audio) newMsg.media.audio;
type = 8;
}
} else if (msgObj.type == 12) {
user = new TLRPC.TL_userRequest_old2();
user.phone = newMsg.media.phone_number;
user.first_name = newMsg.media.first_name;
user.last_name = newMsg.media.last_name;
user.id = newMsg.media.user_id;
type = 6;
} else if (msgObj.type == 8 || msgObj.type == 9 || msgObj.type == 13) {
document = (TLRPC.TL_document) newMsg.media.document;
type = 7;
} else if (msgObj.type == 2) {
audio = (TLRPC.TL_audio) newMsg.media.audio;
type = 8;
}
} else {
if (message != null) {
@ -891,22 +906,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.message = videoEditedInfo.getString();
}
newMsg.attachPath = path;
} else if (msgObj != null) {
newMsg = new TLRPC.TL_message();
newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD;
if (msgObj.isForwarded()) {
newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id;
newMsg.fwd_date = msgObj.messageOwner.fwd_date;
} else {
newMsg.fwd_from_id = new TLRPC.TL_peerUser();
newMsg.fwd_from_id.user_id = msgObj.messageOwner.from_id;
newMsg.fwd_date = msgObj.messageOwner.date;
}
newMsg.media = msgObj.messageOwner.media;
newMsg.message = msgObj.messageOwner.message;
newMsg.fwd_msg_id = msgObj.getId();
newMsg.attachPath = msgObj.messageOwner.attachPath;
type = 4;
} else if (user != null) {
if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) {
newMsg = new TLRPC.TL_message_secret();
@ -953,7 +952,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.attachPath = "";
}
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.flags |= TLRPC.MESSAGE_FLAG_OUT;
newMsg.out = true;
if (asAdmin && sendToPeer != null && sendToPeer.channel_id != 0) {
newMsg.from_id = -sendToPeer.channel_id;
} else {
@ -968,15 +967,19 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA;
if (encryptedChat == null && high_id != 1 && newMsg.media instanceof TLRPC.TL_messageMediaAudio) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_CONTENT_UNREAD;
newMsg.media_unread = true;
}
if (sendToPeer instanceof TLRPC.TL_inputPeerChannel) {
if (asAdmin) {
newMsg.views = 1;
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS;
}
TLRPC.Chat chat = MessagesController.getInstance().getChat(sendToPeer.channel_id);
if (chat != null && chat.megagroup) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP;
}
} else {
newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD;
newMsg.unread = true;
}
newMsg.dialog_id = peer;
if (reply_to_msg != null) {
@ -992,7 +995,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
return;
}
sendToPeers = new ArrayList<>();
for (TLRPC.TL_chatParticipant participant : currentChatInfo.participants.participants) {
for (TLRPC.ChatParticipant participant : currentChatInfo.participants.participants) {
TLRPC.User sendToUser = MessagesController.getInstance().getUser(participant.user_id);
TLRPC.InputUser peerUser = MessagesController.getInputUser(sendToUser);
if (peerUser != null) {
@ -1009,8 +1012,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
processSentMessage(newMsg.id);
return;
}
if ((sendToUser.flags & TLRPC.USER_FLAG_BOT) != 0) {
newMsg.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD;
if (sendToUser.bot) {
newMsg.unread = false;
}
}
}
@ -1062,14 +1065,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
if (asAdmin && sendToPeer instanceof TLRPC.TL_inputPeerChannel) {
reqSend.flags |= 16;
reqSend.broadcast = true;
}
if (reply_to_msg != null) {
reqSend.flags |= 1;
reqSend.reply_to_msg_id = reply_to_msg.getId();
}
if (!searchLinks) {
reqSend.flags |= 2;
reqSend.no_webpage = true;
}
performSendMessageRequest(reqSend, newMsgObj.messageOwner, null);
}
@ -1223,7 +1226,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
request.random_id = newMsg.random_id;
request.media = inputMedia;
if (asAdmin && sendToPeer instanceof TLRPC.TL_inputPeerChannel) {
request.flags |= 16;
request.broadcast = true;
}
if (reply_to_msg != null) {
request.flags |= 1;
@ -1444,13 +1447,21 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
}
} else if (type == 4) {
TLRPC.TL_messages_forwardMessage reqSend = new TLRPC.TL_messages_forwardMessage(); //TODO remove
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
if (msgObj.getId() >= 0) {
reqSend.id = msgObj.getId();
TLRPC.TL_messages_forwardMessages reqSend = new TLRPC.TL_messages_forwardMessages();
reqSend.to_peer = sendToPeer;
if (retryMessageObject.messageOwner.ttl != 0) {
reqSend.from_peer = MessagesController.getInputPeer(retryMessageObject.messageOwner.ttl);
} else {
reqSend.id = msgObj.messageOwner.fwd_msg_id;
reqSend.from_peer = new TLRPC.TL_inputPeerEmpty();
}
reqSend.random_id.add(newMsg.random_id);
if (retryMessageObject.getId() >= 0) {
reqSend.id.add(retryMessageObject.getId());
} else {
reqSend.id.add(retryMessageObject.messageOwner.fwd_msg_id);
}
if (asAdmin && reqSend.to_peer.channel_id != 0) {
reqSend.broadcast = true;
}
performSendMessageRequest(reqSend, newMsgObj.messageOwner, null);
}
@ -1608,6 +1619,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsgObj.local_id = newMsgObj.id = res.id;
newMsgObj.date = res.date;
newMsgObj.entities = res.entities;
newMsgObj.out = res.out;
newMsgObj.unread = res.unread;
if (res.media != null) {
newMsgObj.media = res.media;
newMsgObj.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA;
@ -1632,6 +1645,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
TLRPC.TL_updateNewChannelMessage newMessage = (TLRPC.TL_updateNewChannelMessage) update;
sentMessages.add(newMessage.message);
newMsgObj.id = newMessage.message.id;
if ((newMsgObj.flags & TLRPC.MESSAGE_FLAG_MEGAGROUP) != 0) {
newMessage.message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP;
}
processSentMessage(newMsgObj, newMessage.message, originalPath);
MessagesController.getInstance().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.to_id.channel_id);
ok = true;
@ -1848,6 +1864,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
} else if (sentMessage.media instanceof TLRPC.TL_messageMediaContact && newMsg.media instanceof TLRPC.TL_messageMediaContact) {
newMsg.media = sentMessage.media;
} else if (sentMessage.media instanceof TLRPC.TL_messageMediaWebPage) {
newMsg.media = sentMessage.media;
}
}

View File

@ -61,7 +61,7 @@ public class TgChooserTargetService extends ChooserTargetService {
ArrayList<Integer> usersToLoad = new ArrayList<>();
usersToLoad.add(UserConfig.getClientUserId());
ArrayList<Integer> chatsToLoad = new ArrayList<>();
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs ORDER BY date DESC LIMIT %d,%d", 0, 20));
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs ORDER BY date DESC LIMIT %d,%d", 0, 30));
while (cursor.next()) {
long id = cursor.longValue(0);
@ -109,11 +109,13 @@ public class TgChooserTargetService extends ChooserTargetService {
for (int b = 0; b < users.size(); b++) {
TLRPC.User user = users.get(b);
if (user.id == id) {
extras.putLong("dialogId", (long) id);
if (user.photo != null && user.photo.photo_small != null) {
icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true));
if (!user.bot) {
extras.putLong("dialogId", (long) id);
if (user.photo != null && user.photo.photo_small != null) {
icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true));
}
name = ContactsController.formatName(user.first_name, user.last_name);
}
name = ContactsController.formatName(user.first_name, user.last_name);
break;
}
}
@ -121,11 +123,13 @@ public class TgChooserTargetService extends ChooserTargetService {
for (int b = 0; b < chats.size(); b++) {
TLRPC.Chat chat = chats.get(b);
if (chat.id == -id) {
extras.putLong("dialogId", (long) id);
if (chat.photo != null && chat.photo.photo_small != null) {
icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true));
if (!ChatObject.isNotInChat(chat) && (!ChatObject.isChannel(chat) || chat.megagroup)) {
extras.putLong("dialogId", (long) id);
if (chat.photo != null && chat.photo.photo_small != null) {
icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true));
}
name = chat.title;
}
name = chat.title;
break;
}
}

View File

@ -41,7 +41,13 @@ public class UserConfig {
public static boolean useFingerprint = true;
public static int lastUpdateVersion;
public static int lastContactsSyncTime;
public static boolean channelsLoaded = false;
public static int migrateOffsetId = -1;
public static int migrateOffsetDate = -1;
public static int migrateOffsetUserId = -1;
public static int migrateOffsetChatId = -1;
public static int migrateOffsetChannelId = -1;
public static long migrateOffsetAccess = -1;
public static int getNewMessageId() {
int id;
@ -79,9 +85,17 @@ public class UserConfig {
editor.putInt("lastPauseTime", lastPauseTime);
editor.putInt("lastUpdateVersion", lastUpdateVersion);
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
editor.putBoolean("channelsLoaded", channelsLoaded);
editor.putBoolean("useFingerprint", useFingerprint);
editor.putInt("migrateOffsetId", migrateOffsetId);
if (migrateOffsetId != -1) {
editor.putInt("migrateOffsetDate", migrateOffsetDate);
editor.putInt("migrateOffsetUserId", migrateOffsetUserId);
editor.putInt("migrateOffsetChatId", migrateOffsetChatId);
editor.putInt("migrateOffsetChannelId", migrateOffsetChannelId);
editor.putLong("migrateOffsetAccess", migrateOffsetAccess);
}
if (currentUser != null) {
if (withFile) {
SerializedData data = new SerializedData();
@ -212,7 +226,16 @@ public class UserConfig {
useFingerprint = preferences.getBoolean("useFingerprint", true);
lastUpdateVersion = preferences.getInt("lastUpdateVersion", 511);
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
channelsLoaded = preferences.getBoolean("channelsLoaded", false);
migrateOffsetId = preferences.getInt("migrateOffsetId", 0);
if (migrateOffsetId != -1) {
migrateOffsetDate = preferences.getInt("migrateOffsetDate", 0);
migrateOffsetUserId = preferences.getInt("migrateOffsetUserId", 0);
migrateOffsetChatId = preferences.getInt("migrateOffsetChatId", 0);
migrateOffsetChannelId = preferences.getInt("migrateOffsetChannelId", 0);
migrateOffsetAccess = preferences.getLong("migrateOffsetAccess", 0);
}
String user = preferences.getString("user", null);
if (user != null) {
byte[] userBytes = Base64.decode(user, Base64.DEFAULT);
@ -277,7 +300,12 @@ public class UserConfig {
lastBroadcastId = -1;
saveIncomingPhotos = false;
blockedUsersLoaded = false;
channelsLoaded = false;
migrateOffsetId = -1;
migrateOffsetDate = -1;
migrateOffsetUserId = -1;
migrateOffsetChatId = -1;
migrateOffsetChannelId = -1;
migrateOffsetAccess = -1;
appLocked = false;
passcodeType = 0;
passcodeHash = "";

View File

@ -14,15 +14,15 @@ import org.telegram.tgnet.TLRPC;
public class UserObject {
public static boolean isDeleted(TLRPC.User user) {
return user == null || user instanceof TLRPC.TL_userDeleted_old2 || user instanceof TLRPC.TL_userEmpty || (user.flags & TLRPC.USER_FLAG_DELETED) != 0;
return user == null || user instanceof TLRPC.TL_userDeleted_old2 || user instanceof TLRPC.TL_userEmpty || user.deleted;
}
public static boolean isContact(TLRPC.User user) {
return user instanceof TLRPC.TL_userContact_old2 || (user.flags & TLRPC.USER_FLAG_CONTACT) != 0 || (user.flags & TLRPC.USER_FLAG_MUTUAL_CONTACT) != 0;
return user instanceof TLRPC.TL_userContact_old2 || user.contact || user.mutual_contact;
}
public static boolean isUserSelf(TLRPC.User user) {
return user instanceof TLRPC.TL_userSelf_old3 || (user.flags & TLRPC.USER_FLAG_SELF) != 0;
return user instanceof TLRPC.TL_userSelf_old3 || user.self;
}
public static String getUserName(TLRPC.User user) {

View File

@ -32,6 +32,6 @@ public class WearReplyReceiver extends BroadcastReceiver {
return;
}
SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, null, null, true, false);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false);
MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, true, false);
}
}

View File

@ -20,18 +20,19 @@ import org.telegram.tgnet.TLRPC;
import java.util.ArrayList;
@SuppressWarnings("unchecked")
public class MessagesSearchQuery {
private static int reqId;
private static int lastReqId;
private static boolean messagesSearchEndReached;
private static boolean messagesSearchEndReached[] = new boolean[] {false, false};
private static ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
private static String lastSearchQuery;
private static int lastReturnedNum;
private static int getMask() {
int mask = 0;
if (lastReturnedNum < searchResultMessages.size() - 1) {
if (lastReturnedNum < searchResultMessages.size() - 1 || !messagesSearchEndReached[0] || !messagesSearchEndReached[1]) {
mask |= 1;
}
if (lastReturnedNum > 0) {
@ -40,25 +41,37 @@ public class MessagesSearchQuery {
return mask;
}
public static void searchMessagesInChat(String query, long dialog_id, final int guid, int direction) {
public static void searchMessagesInChat(String query, final long dialog_id, final long mergeDialogId, final int guid, int direction) {
if (reqId != 0) {
ConnectionsManager.getInstance().cancelRequest(reqId, true);
reqId = 0;
}
int max_id = 0;
long queryWithDialog = dialog_id;
if (query == null || query.length() == 0) {
if (direction == 1) {
lastReturnedNum++;
if (lastReturnedNum < searchResultMessages.size()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, searchResultMessages.get(lastReturnedNum).getId(), getMask());
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId());
return;
} else {
if (messagesSearchEndReached) {
if (messagesSearchEndReached[0] && mergeDialogId == 0 || messagesSearchEndReached[1]) {
lastReturnedNum--;
return;
}
query = lastSearchQuery;
max_id = searchResultMessages.get(searchResultMessages.size() - 1).getId();
MessageObject messageObject = searchResultMessages.get(searchResultMessages.size() - 1);
if (messageObject.getDialogId() == dialog_id && !messagesSearchEndReached[0]) {
max_id = messageObject.getId();
queryWithDialog = dialog_id;
} else {
if (messageObject.getDialogId() == mergeDialogId) {
max_id = messageObject.getId();
}
queryWithDialog = mergeDialogId;
messagesSearchEndReached[1] = false;
}
}
} else if (direction == 2) {
lastReturnedNum--;
@ -66,15 +79,22 @@ public class MessagesSearchQuery {
lastReturnedNum = 0;
return;
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, searchResultMessages.get(lastReturnedNum).getId(), getMask());
if (lastReturnedNum >= searchResultMessages.size()) {
lastReturnedNum = searchResultMessages.size() - 1;
}
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId());
return;
} else {
return;
}
}
if (messagesSearchEndReached[0] && !messagesSearchEndReached[1] && mergeDialogId != 0) {
queryWithDialog = mergeDialogId;
}
final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.limit = 21;
int lower_part = (int) dialog_id;
int lower_part = (int) queryWithDialog;
req.peer = MessagesController.getInputPeer(lower_part);
if (req.peer == null) {
return;
@ -84,19 +104,21 @@ public class MessagesSearchQuery {
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
final int currentReqId = ++lastReqId;
lastSearchQuery = query;
final long queryWithDialogFinal = queryWithDialog;
reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
reqId = 0;
if (currentReqId == lastReqId) {
if (error == null) {
TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
MessagesController.getInstance().putUsers(res.users, false);
MessagesController.getInstance().putChats(res.chats, false);
if (req.max_id == 0) {
if (req.max_id == 0 && queryWithDialogFinal == dialog_id) {
lastReturnedNum = 0;
searchResultMessages.clear();
}
@ -106,17 +128,27 @@ public class MessagesSearchQuery {
added = true;
searchResultMessages.add(new MessageObject(message, null, false));
}
messagesSearchEndReached = res.messages.size() != 21;
messagesSearchEndReached[queryWithDialogFinal == dialog_id ? 0 : 1] = res.messages.size() != 21;
if (mergeDialogId == 0) {
messagesSearchEndReached[1] = messagesSearchEndReached[0];
}
if (searchResultMessages.isEmpty()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask());
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0);
} else {
if (added) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, searchResultMessages.get(lastReturnedNum).getId(), getMask());
if (lastReturnedNum >= searchResultMessages.size()) {
lastReturnedNum = searchResultMessages.size() - 1;
}
MessageObject messageObject = searchResultMessages.get(lastReturnedNum);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId());
}
}
if (queryWithDialogFinal == dialog_id && messagesSearchEndReached[0] && mergeDialogId != 0) {
messagesSearchEndReached[1] = false;
searchMessagesInChat(lastSearchQuery, dialog_id, mergeDialogId, guid, 0);
}
}
}
reqId = 0;
}
});
}

View File

@ -82,39 +82,7 @@ public class ReplyMessageQuery {
message.id = cursor.intValue(1);
message.date = cursor.intValue(2);
message.dialog_id = dialog_id;
if (message.from_id > 0) {
if (!usersToLoad.contains(message.from_id)) {
usersToLoad.add(message.from_id);
}
} else {
if (!chatsToLoad.contains(-message.from_id)) {
chatsToLoad.add(-message.from_id);
}
}
if (message.action != null && message.action.user_id != 0) {
if (!usersToLoad.contains(message.action.user_id)) {
usersToLoad.add(message.action.user_id);
}
}
if (message.media != null && message.media.user_id != 0) {
if (!usersToLoad.contains(message.media.user_id)) {
usersToLoad.add(message.media.user_id);
}
}
if (message.media != null && message.media.audio != null && message.media.audio.user_id != 0) {
if (!usersToLoad.contains(message.media.audio.user_id)) {
usersToLoad.add(message.media.audio.user_id);
}
}
if (message.fwd_from_id instanceof TLRPC.TL_peerUser) {
if (!usersToLoad.contains(message.fwd_from_id.user_id)) {
usersToLoad.add(message.fwd_from_id.user_id);
}
} else if (message.fwd_from_id instanceof TLRPC.TL_peerChannel) {
if (!chatsToLoad.contains(message.fwd_from_id.channel_id)) {
chatsToLoad.add(message.fwd_from_id.channel_id);
}
}
MessagesStorage.addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad);
result.add(message);
replyMessages.remove((Integer) message.id);
}
@ -206,9 +174,15 @@ public class ReplyMessageQuery {
}
private static void broadcastReplyMessages(final ArrayList<TLRPC.Message> result, final HashMap<Integer, ArrayList<MessageObject>> replyMessageOwners, final ArrayList<TLRPC.User> users, final ArrayList<TLRPC.Chat> chats, final long dialog_id, final boolean isCache) {
final HashMap<Integer, TLRPC.User> usersHashMap = new HashMap<>();
for (TLRPC.User user : users) {
usersHashMap.put(user.id, user);
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<>();
for (int a = 0; a < users.size(); a++) {
TLRPC.User user = users.get(a);
usersDict.put(user.id, user);
}
final HashMap<Integer, TLRPC.Chat> chatsDict = new HashMap<>();
for (int a = 0; a < chats.size(); a++) {
TLRPC.Chat chat = chats.get(a);
chatsDict.put(chat.id, chat);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
@ -216,11 +190,13 @@ public class ReplyMessageQuery {
MessagesController.getInstance().putUsers(users, isCache);
MessagesController.getInstance().putChats(chats, isCache);
boolean changed = false;
for (TLRPC.Message message : result) {
for (int a = 0; a < result.size(); a++) {
TLRPC.Message message = result.get(a);
ArrayList<MessageObject> arrayList = replyMessageOwners.get(message.id);
if (arrayList != null) {
MessageObject messageObject = new MessageObject(message, usersHashMap, false);
for (MessageObject m : arrayList) {
MessageObject messageObject = new MessageObject(message, usersDict, chatsDict, false);
for (int b = 0; b < arrayList.size(); b++) {
MessageObject m = arrayList.get(b);
m.replyMessageObject = messageObject;
}
changed = true;

View File

@ -197,13 +197,15 @@ public class SharedMediaQuery {
putMediaDatabase(uid, type, res.messages, max_id, topReached);
}
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<>();
for (TLRPC.User u : res.users) {
usersLocal.put(u.id, u);
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<>();
for (int a = 0; a < res.users.size(); a++) {
TLRPC.User u = res.users.get(a);
usersDict.put(u.id, u);
}
final ArrayList<MessageObject> objects = new ArrayList<>();
for (TLRPC.Message message : res.messages) {
objects.add(new MessageObject(message, usersLocal, true));
for (int a = 0; a < res.messages.size(); a++) {
TLRPC.Message message = res.messages.get(a);
objects.add(new MessageObject(message, usersDict, true));
}
AndroidUtilities.runOnUIThread(new Runnable() {
@ -273,37 +275,6 @@ public class SharedMediaQuery {
}
cursor.dispose();
/*cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, send_state, date FROM messages WHERE uid = %d ORDER BY mid ASC LIMIT %d", uid, 1000));
ArrayList<TLRPC.Message> photos = new ArrayList<>();
ArrayList<TLRPC.Message> docs = new ArrayList<>();
while (cursor.next()) {
NativeByteBuffer data = new NativeByteBuffer(cursor.byteArrayLength(1));
if (data != null && cursor.byteBufferValue(1, data) != 0) {
TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32());
MessageObject.setIsUnread(message, cursor.intValue(0) != 1);
message.date = cursor.intValue(2);
message.send_state = cursor.intValue(1);
message.dialog_id = uid;
if (message.ttl > 60 && message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaVideo) {
photos.add(message);
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
docs.add(message);
}
}
data.reuse();
}
cursor.dispose();
if (!photos.isEmpty() || !docs.isEmpty()) {
MessagesStorage.getInstance().getDatabase().beginTransaction();
if (!photos.isEmpty()) {
putMediaDatabaseInternal(uid, MEDIA_PHOTOVIDEO, photos);
}
if (docs.isEmpty()) {
putMediaDatabaseInternal(uid, MEDIA_FILE, docs);
}
MessagesStorage.getInstance().getDatabase().commitTransaction();
}*/
if (count != -1) {
putMediaCountDatabase(uid, type, count);
}

View File

@ -74,7 +74,7 @@ public class StickersQuery {
if (document != null) {
long setId = getStickerSetId(document);
TLRPC.TL_messages_stickerSet stickerSet = stickerSetsById.get(setId);
if (stickerSet != null && (stickerSet.set.flags & 2) != 0) {
if (stickerSet != null && stickerSet.set.disabled) {
return null;
}
}
@ -156,7 +156,9 @@ public class StickersQuery {
TLRPC.TL_messages_stickerSet oldSet = stickerSetsById.get(stickerSet.id);
if (oldSet != null && oldSet.set.hash == stickerSet.hash) {
oldSet.set.flags = stickerSet.flags;
oldSet.set.disabled = stickerSet.disabled;
oldSet.set.installed = stickerSet.installed;
oldSet.set.official = stickerSet.official;
newStickerSets.put(oldSet.set.id, oldSet);
newStickerArray.add(oldSet);
@ -206,24 +208,32 @@ public class StickersQuery {
@Override
public void run() {
try {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO stickers_v2 VALUES(?, ?, ?, ?)");
state.requery();
int size = 4;
for (int a = 0; a < stickers.size(); a++) {
size += stickers.get(a).getObjectSize();
if (stickers != null) {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO stickers_v2 VALUES(?, ?, ?, ?)");
state.requery();
int size = 4;
for (int a = 0; a < stickers.size(); a++) {
size += stickers.get(a).getObjectSize();
}
NativeByteBuffer data = new NativeByteBuffer(size);
data.writeInt32(stickers.size());
for (int a = 0; a < stickers.size(); a++) {
stickers.get(a).serializeToStream(data);
}
state.bindInteger(1, 1);
state.bindByteBuffer(2, data);
state.bindInteger(3, date);
state.bindString(4, hash);
state.step();
data.reuse();
state.dispose();
} else {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("UPDATE stickers_v2 SET date = ?");
state.requery();
state.bindInteger(1, date);
state.step();
state.dispose();
}
NativeByteBuffer data = new NativeByteBuffer(size);
data.writeInt32(stickers.size());
for (int a = 0; a < stickers.size(); a++) {
stickers.get(a).serializeToStream(data);
}
state.bindInteger(1, 1);
state.bindByteBuffer(2, data);
state.bindInteger(3, date);
state.bindString(4, hash);
state.step();
data.reuse();
state.dispose();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
@ -291,7 +301,7 @@ public class StickersQuery {
}
stickersByIdNew.put(document.id, document);
}
if ((stickerSet.set.flags & 2) == 0) {
if (!stickerSet.set.disabled) {
for (int b = 0; b < stickerSet.packs.size(); b++) {
TLRPC.TL_stickerPack stickerPack = stickerSet.packs.get(b);
if (stickerPack == null || stickerPack.emoticon == null) {
@ -333,6 +343,14 @@ public class StickersQuery {
} catch (Throwable e) {
FileLog.e("tmessages", e);
}
} else if (!cache) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadDate = date;
}
});
putStickersToCache(null, date, null);
}
}
});
@ -433,11 +451,7 @@ public class StickersQuery {
stickerSetID.access_hash = stickerSet.access_hash;
stickerSetID.id = stickerSet.id;
if (hide != 0) {
if (hide == 1) {
stickerSet.flags |= 2;
} else {
stickerSet.flags &= ~2;
}
stickerSet.disabled = hide == 1;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
TLRPC.TL_messages_installStickerSet req = new TLRPC.TL_messages_installStickerSet();
req.stickerset = stickerSetID;

View File

@ -27,6 +27,7 @@ import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class ConnectionsManager {
@ -57,7 +58,7 @@ public class ConnectionsManager {
private int lastClassGuid = 1;
private boolean isUpdating = false;
private int connectionState = native_getConnectionState();
private volatile int lastRequestToken = 1;
private AtomicInteger lastRequestToken = new AtomicInteger(1);
private PowerManager.WakeLock wakeLock = null;
private static volatile ConnectionsManager Instance = null;
@ -114,11 +115,11 @@ public class ConnectionsManager {
}
public int sendRequest(final TLObject object, final RequestDelegate onComplete, final QuickAckDelegate onQuickAck, final int flags, final int datacenterId, final int connetionType, final boolean immediate) {
final int requestToken = lastRequestToken++;
final int requestToken = lastRequestToken.getAndIncrement();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
FileLog.d("tmessages", "send request " + object);
FileLog.d("tmessages", "send request " + object + " with token = " + requestToken);
NativeByteBuffer buffer = new NativeByteBuffer(object.getObjectSize());
object.serializeToStream(buffer);
object.freeResources();

File diff suppressed because it is too large Load Diff

View File

@ -896,7 +896,7 @@ public class ActionBarLayout extends FrameLayout {
onCloseAnimationEndRunnable = new Runnable() {
@Override
public void run() {
removeFragmentFromStack(currentFragment);
removeFragmentFromStackInternal(currentFragment);
setVisibility(GONE);
if (backgroundView != null) {
backgroundView.setVisibility(GONE);
@ -935,7 +935,7 @@ public class ActionBarLayout extends FrameLayout {
});
currentAnimation.start();
} else {
removeFragmentFromStack(currentFragment);
removeFragmentFromStackInternal(currentFragment);
setVisibility(GONE);
if (backgroundView != null) {
backgroundView.setVisibility(GONE);
@ -998,16 +998,24 @@ public class ActionBarLayout extends FrameLayout {
}
}
public void removeFragmentFromStack(BaseFragment fragment) {
private void removeFragmentFromStackInternal(BaseFragment fragment) {
fragment.onPause();
fragment.onFragmentDestroy();
fragment.setParentLayout(null);
fragmentsStack.remove(fragment);
}
public void removeFragmentFromStack(BaseFragment fragment) {
if (useAlphaAnimations && fragmentsStack.size() == 1 && AndroidUtilities.isTablet()) {
closeLastFragment(true);
} else {
removeFragmentFromStackInternal(fragment);
}
}
public void removeAllFragments() {
for (int a = 0; a < fragmentsStack.size(); a++) {
removeFragmentFromStack(fragmentsStack.get(a));
removeFragmentFromStackInternal(fragmentsStack.get(a));
a--;
}
}

View File

@ -288,7 +288,6 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
}
if (popupWindow == null) {
popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
//popupWindow.setBackgroundDrawable(new BitmapDrawable());
if (Build.VERSION.SDK_INT >= 19) {
popupWindow.setAnimationStyle(0);
} else {

View File

@ -90,13 +90,22 @@ public class ActionBarPopupWindow extends PopupWindow {
setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
setWillNotDraw(false);
scrollView = new ScrollView(context);
scrollView.setVerticalScrollBarEnabled(false);
addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
try {
scrollView = new ScrollView(context);
scrollView.setVerticalScrollBarEnabled(false);
addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
} catch (Throwable e) {
FileLog.e("tmessages", e);
}
linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
scrollView.addView(linearLayout, new ScrollView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
if (scrollView != null) {
scrollView.addView(linearLayout, new ScrollView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
} else {
addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
}
}
public void setShowedFromBotton(boolean value) {
@ -215,7 +224,9 @@ public class ActionBarPopupWindow extends PopupWindow {
}
public void scrollToTop() {
scrollView.scrollTo(0, 0);
if (scrollView != null) {
scrollView.scrollTo(0, 0);
}
}
}
@ -374,6 +385,7 @@ public class ActionBarPopupWindow extends PopupWindow {
}
public void dismiss(boolean animated) {
setFocusable(false);
if (animationEnabled && animated) {
if (windowAnimatorSet != null) {
windowAnimatorSet.cancel();
@ -414,7 +426,6 @@ public class ActionBarPopupWindow extends PopupWindow {
});
windowAnimatorSet.start();
} else {
setFocusable(false);
try {
super.dismiss();
} catch (Exception e) {

View File

@ -31,6 +31,7 @@ import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
@ -55,6 +56,7 @@ public class BottomSheet extends Dialog {
private LinearLayout containerView;
private FrameLayout container;
private Object lastInsets;
private boolean dismissed;
private int tag;
@ -70,6 +72,8 @@ public class BottomSheet extends Dialog {
private ColorDrawable backgroundDrawable = new ColorDrawable(0xff000000);
private static Drawable shadowDrawable;
private boolean focusable;
private Paint ciclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private static int backgroundPaddingTop;
@ -193,10 +197,11 @@ public class BottomSheet extends Dialog {
}
}
public BottomSheet(Context context) {
public BottomSheet(Context context, boolean needFocus) {
super(context);
container = new FrameLayout(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@ -225,7 +230,12 @@ public class BottomSheet extends Dialog {
if (child.getVisibility() == GONE || child == containerView) {
continue;
}
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
if (lastInsets != null && Build.VERSION.SDK_INT >= 21) {
WindowInsets wi = (WindowInsets) lastInsets;
wi = wi.replaceSystemWindowInsets(wi.getSystemWindowInsetLeft(), wi.getSystemWindowInsetTop(), 0, wi.getSystemWindowInsetBottom());
child.dispatchApplyWindowInsets(wi);
}
measureChildWithMargins(child, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 0, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY), 0);
}
}
@ -296,8 +306,18 @@ public class BottomSheet extends Dialog {
}
});
container.setBackgroundDrawable(backgroundDrawable);
if (Build.VERSION.SDK_INT >= 21) {
focusable = needFocus;
if (Build.VERSION.SDK_INT >= 21 && !focusable) {
container.setFitsSystemWindows(true);
container.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@SuppressLint("NewApi")
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
lastInsets = insets;
container.requestLayout();
return insets.consumeSystemWindowInsets();
}
});
container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}
@ -424,9 +444,13 @@ public class BottomSheet extends Dialog {
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.TOP | Gravity.LEFT;
params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
params.dimAmount = 0;
params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND;
if (!focusable) {
params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
params.dimAmount = 0;
params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND;
} else {
params.dimAmount = 0.2f;
}
if (Build.VERSION.SDK_INT < 21) {
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
}
@ -436,6 +460,9 @@ public class BottomSheet extends Dialog {
@Override
public void show() {
super.show();
if (focusable) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
dismissed = false;
if (Build.VERSION.SDK_INT >= 21 || !useRevealAnimation) {
containerView.setBackgroundDrawable(shadowDrawable);
@ -592,7 +619,7 @@ public class BottomSheet extends Dialog {
AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
animatorSetProxy.playTogether(
ObjectAnimatorProxy.ofFloat(containerView, "translationY", 0),
ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 51));
ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", focusable ? 0 : 51));
animatorSetProxy.setDuration(200);
animatorSetProxy.setStartDelay(20);
animatorSetProxy.setInterpolator(new DecelerateInterpolator());
@ -718,7 +745,11 @@ public class BottomSheet extends Dialog {
private BottomSheet bottomSheet;
public Builder(Context context) {
bottomSheet = new BottomSheet(context);
bottomSheet = new BottomSheet(context, false);
}
public Builder(Context context, boolean needFocus) {
bottomSheet = new BottomSheet(context, needFocus);
}
public Builder setItems(CharSequence[] items, final OnClickListener onClickListener) {

View File

@ -41,7 +41,7 @@ public class BaseSearchAdapter extends BaseFragmentAdapter {
protected HashMap<String, HashtagObject> hashtagsByText;
protected boolean hashtagsLoadedFromDb = false;
public void queryServerSearch(final String query, final boolean allowChats) {
public void queryServerSearch(final String query, final boolean allowChats, final boolean allowBots) {
if (reqId != 0) {
ConnectionsManager.getInstance().cancelRequest(reqId, true);
reqId = 0;
@ -72,6 +72,9 @@ public class BaseSearchAdapter extends BaseFragmentAdapter {
}
}
for (int a = 0; a < res.users.size(); a++) {
if (!allowBots && res.users.get(a).bot) {
continue;
}
globalSearch.add(res.users.get(a));
}
lastFoundUsername = query;

View File

@ -238,7 +238,7 @@ public class ContactsAdapter extends BaseSectionsAdapter {
}
} else if (type == 0) {
if (convertView == null) {
convertView = new UserCell(mContext, 58);
convertView = new UserCell(mContext, 58, 1);
((UserCell) convertView).setStatusColors(0xffa8a8a8, 0xff3b84c0);
}

View File

@ -46,7 +46,7 @@ public class DialogsAdapter extends RecyclerView.Adapter {
public boolean isDataSetChanged() {
int current = currentCount;
return current != getItemCount();
return current != getItemCount() || current == 1;
}
private ArrayList<TLRPC.Dialog> getDialogsArray() {

View File

@ -16,6 +16,7 @@ import android.view.ViewGroup;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
@ -128,15 +129,29 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
}
return;
}
final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
final TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal();
req.limit = 20;
req.peer = new TLRPC.TL_inputPeerEmpty();
req.q = query;
if (lastMessagesSearchString != null && query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty()) {
req.max_id = searchResultMessages.get(searchResultMessages.size() - 1).getId();
MessageObject lastMessage = searchResultMessages.get(searchResultMessages.size() - 1);
req.offset_id = lastMessage.getId();
req.offset_date = lastMessage.messageOwner.date;
int id;
if (lastMessage.messageOwner.to_id.channel_id != 0) {
id = -lastMessage.messageOwner.to_id.channel_id;
} else if (lastMessage.messageOwner.to_id.chat_id != 0) {
id = -lastMessage.messageOwner.to_id.chat_id;
} else {
id = lastMessage.messageOwner.to_id.user_id;
}
req.offset_peer = MessagesController.getInputPeer(id);
} else {
req.offset_date = 0;
req.offset_id = 0;
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
}
lastMessagesSearchString = query;
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
final int currentReqId = ++lastReqId;
if (delegate != null) {
delegate.searchStateChanged(true);
@ -153,7 +168,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
MessagesController.getInstance().putUsers(res.users, false);
MessagesController.getInstance().putChats(res.chats, false);
if (req.max_id == 0) {
if (req.offset_id == 0) {
searchResultMessages.clear();
}
for (TLRPC.Message message : res.messages) {
@ -258,7 +273,14 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
} else {
did = AndroidUtilities.makeBroadcastId(chat.id);
}
hashMap.get(did).object = chat;
if (chat.migrated_to != null) {
RecentSearchObject recentSearchObject = hashMap.remove(did);
if (recentSearchObject != null) {
arrayList.remove(recentSearchObject);
}
} else {
hashMap.get(did).object = chat;
}
}
}
@ -391,7 +413,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
int resultCount = 0;
HashMap<Long, DialogSearchResult> dialogsResult = new HashMap<>();
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 200");
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 400");
while (cursor.next()) {
long id = cursor.longValue(0);
DialogSearchResult dialogSearchResult = new DialogSearchResult();
@ -481,16 +503,18 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
NativeByteBuffer data = new NativeByteBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data) != 0) {
TLRPC.Chat chat = TLRPC.Chat.TLdeserialize(data, data.readInt32(false), false);
long dialog_id;
if (chat.id > 0) {
dialog_id = -chat.id;
} else {
dialog_id = AndroidUtilities.makeBroadcastId(chat.id);
if (!(chat == null || chat.deactivated || ChatObject.isChannel(chat) && ChatObject.isNotInChat(chat))) {
long dialog_id;
if (chat.id > 0) {
dialog_id = -chat.id;
} else {
dialog_id = AndroidUtilities.makeBroadcastId(chat.id);
}
DialogSearchResult dialogSearchResult = dialogsResult.get(dialog_id);
dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q);
dialogSearchResult.object = chat;
resultCount++;
}
DialogSearchResult dialogSearchResult = dialogsResult.get(dialog_id);
dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q);
dialogSearchResult.object = chat;
resultCount++;
}
data.reuse();
break;
@ -589,7 +613,8 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
for (DialogSearchResult dialogSearchResult : searchResults) {
for (int a = 0; a < searchResults.size(); a++) {
DialogSearchResult dialogSearchResult = searchResults.get(a);
resultArray.add(dialogSearchResult.object);
resultArrayNames.add(dialogSearchResult.name);
}
@ -797,7 +822,19 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler {
public Object getItem(int i) {
if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) {
if (i > 0 && i - 1 < recentSearchObjects.size()) {
return recentSearchObjects.get(i - 1).object;
TLObject object = recentSearchObjects.get(i - 1).object;
if (object instanceof TLRPC.User) {
TLRPC.User user = MessagesController.getInstance().getUser(((TLRPC.User) object).id);
if (user != null) {
object = user;
}
} else if (object instanceof TLRPC.Chat) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(((TLRPC.Chat) object).id);
if (chat != null) {
object = chat;
}
}
return object;
} else {
return null;
}

View File

@ -166,8 +166,9 @@ public class MentionsAdapter extends BaseSearchAdapter {
}
String usernameString = result.toString().toLowerCase();
ArrayList<TLRPC.User> newResult = new ArrayList<>();
if (info instanceof TLRPC.TL_chatFull) {
for (TLRPC.TL_chatParticipant chatParticipant : info.participants.participants) {
if (info.participants != null) {
for (int a = 0; a < info.participants.participants.size(); a++) {
TLRPC.ChatParticipant chatParticipant = info.participants.participants.get(a);
TLRPC.User user = MessagesController.getInstance().getUser(chatParticipant.user_id);
if (user == null || UserObject.isUserSelf(user)) {
continue;
@ -220,11 +221,13 @@ public class MentionsAdapter extends BaseSearchAdapter {
ArrayList<TLRPC.User> newResultUsers = new ArrayList<>();
String command = result.toString().toLowerCase();
for (HashMap.Entry<Integer, TLRPC.BotInfo> entry : botInfo.entrySet()) {
for (TLRPC.TL_botCommand botCommand : entry.getValue().commands) {
TLRPC.BotInfo botInfo = entry.getValue();
for (int a = 0; a < botInfo.commands.size(); a++) {
TLRPC.TL_botCommand botCommand = botInfo.commands.get(a);
if (botCommand != null && botCommand.command != null && botCommand.command.startsWith(command)) {
newResult.add("/" + botCommand.command);
newResultHelp.add(botCommand.description);
newResultUsers.add(MessagesController.getInstance().getUser(entry.getValue().user_id));
newResultUsers.add(MessagesController.getInstance().getUser(botInfo.user_id));
}
}
}
@ -311,8 +314,12 @@ public class MentionsAdapter extends BaseSearchAdapter {
if (i < 0 || i >= searchResultCommands.size()) {
return null;
}
if (searchResultCommandsUsers != null && botsCount != 1) {
return String.format("%s@%s", searchResultCommands.get(i), searchResultCommandsUsers.get(i).username);
if (searchResultCommandsUsers != null && (botsCount != 1 || info instanceof TLRPC.TL_channelFull)) {
if (searchResultCommandsUsers.get(i) != null) {
return String.format("%s@%s", searchResultCommands.get(i), searchResultCommandsUsers.get(i) != null ? searchResultCommandsUsers.get(i).username : "");
} else {
return String.format("%s", searchResultCommands.get(i));
}
}
return searchResultCommands.get(i);
}
@ -338,7 +345,7 @@ public class MentionsAdapter extends BaseSearchAdapter {
} else if (searchResultHashtags != null) {
((MentionCell) view).setText(searchResultHashtags.get(i));
} else if (searchResultCommands != null) {
((MentionCell) view).setBotCommand(searchResultCommands.get(i), searchResultCommandsHelp.get(i), searchResultCommandsUsers.get(i));
((MentionCell) view).setBotCommand(searchResultCommands.get(i), searchResultCommandsHelp.get(i), searchResultCommandsUsers != null ? searchResultCommandsUsers.get(i) : null);
}
return view;
}

View File

@ -74,20 +74,19 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
PhotoAttachPhotoCell cell = new PhotoAttachPhotoCell(mContext);
cell.setOnCheckClickLisnener(new View.OnClickListener() {
cell.setDelegate(new PhotoAttachPhotoCell.PhotoAttachPhotoCellDelegate() {
@Override
public void onClick(View v) {
PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) v.getParent();
MediaController.PhotoEntry photoEntry = cell.getPhotoEntry();
public void onCheckClick(PhotoAttachPhotoCell v) {
MediaController.PhotoEntry photoEntry = v.getPhotoEntry();
if (selectedPhotos.containsKey(photoEntry.imageId)) {
selectedPhotos.remove(photoEntry.imageId);
cell.setChecked(false, true);
v.setChecked(false, true);
photoEntry.imagePath = null;
photoEntry.thumbPath = null;
cell.setPhotoEntry(photoEntry, cell.getTag() == MediaController.allPhotosAlbumEntry.photos.size() - 1);
v.setPhotoEntry(photoEntry, v.getTag() == MediaController.allPhotosAlbumEntry.photos.size() - 1);
} else {
selectedPhotos.put(photoEntry.imageId, photoEntry);
cell.setChecked(true, true);
v.setChecked(true, true);
}
delegate.selectedPhotosChanged();
}

View File

@ -43,13 +43,15 @@ public class SearchAdapter extends BaseSearchAdapter {
private boolean useUserCell;
private boolean onlyMutual;
private boolean allowChats;
private boolean allowBots;
public SearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1, boolean usernameSearch, boolean mutual, boolean chats) {
public SearchAdapter(Context context, HashMap<Integer, TLRPC.User> arg1, boolean usernameSearch, boolean mutual, boolean chats, boolean bots) {
mContext = context;
ignoreUsers = arg1;
onlyMutual = mutual;
allowUsernameSearch = usernameSearch;
allowChats = chats;
allowBots = bots;
}
public void setCheckedMap(HashMap<Integer, ?> map) {
@ -72,7 +74,7 @@ public class SearchAdapter extends BaseSearchAdapter {
searchResult.clear();
searchResultNames.clear();
if (allowUsernameSearch) {
queryServerSearch(null, allowChats);
queryServerSearch(null, allowChats, allowBots);
}
notifyDataSetChanged();
} else {
@ -97,7 +99,7 @@ public class SearchAdapter extends BaseSearchAdapter {
@Override
public void run() {
if (allowUsernameSearch) {
queryServerSearch(query, allowChats);
queryServerSearch(query, allowChats, allowBots);
}
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<>();
contactsCopy.addAll(ContactsController.getInstance().contacts);
@ -122,9 +124,10 @@ public class SearchAdapter extends BaseSearchAdapter {
ArrayList<TLRPC.User> resultArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
for (TLRPC.TL_contact contact : contactsCopy) {
for (int a = 0; a < contactsCopy.size(); a++) {
TLRPC.TL_contact contact = contactsCopy.get(a);
TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id);
if (user.id == UserConfig.getClientUserId() || onlyMutual && (user.flags & TLRPC.USER_FLAG_MUTUAL_CONTACT) == 0) {
if (user.id == UserConfig.getClientUserId() || onlyMutual && !user.mutual_contact) {
continue;
}
@ -235,7 +238,7 @@ public class SearchAdapter extends BaseSearchAdapter {
} else {
if (view == null) {
if (useUserCell) {
view = new UserCell(mContext, 1);
view = new UserCell(mContext, 1, 1);
if (checkedMap != null) {
((UserCell) view).setChecked(false, false);
}

View File

@ -217,7 +217,7 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen
File file = new File(audioEntry.path);
TLRPC.TL_message message = new TLRPC.TL_message();
message.flags = TLRPC.MESSAGE_FLAG_OUT;
message.out = true;
message.id = id;
message.to_id = new TLRPC.TL_peerUser();
message.to_id.user_id = message.from_id = UserConfig.getClientUserId();

View File

@ -263,7 +263,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe
int type = getItemViewType(i);
if (type == 0) {
if (view == null) {
view = new UserCell(mContext, 1);
view = new UserCell(mContext, 1, 0);
}
TLRPC.User user = MessagesController.getInstance().getUser(MessagesController.getInstance().blockedUsers.get(i));
if (user != null) {

View File

@ -0,0 +1,187 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.ui.Cells;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.ImageView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.Components.URLSpanNoUnderline;
public class AboutLinkCell extends FrameLayout {
private StaticLayout textLayout;
private TextPaint textPaint;
private Paint urlPaint;
private String oldText;
private int textX;
private int textY;
private SpannableStringBuilder stringBuilder;
private ImageView imageView;
private ClickableSpan pressedLink;
private LinkPath urlPath = new LinkPath();
private AboutLinkCellDelegate delegate;
public interface AboutLinkCellDelegate {
void didPressUrl(String url);
}
public AboutLinkCell(Context context) {
super(context);
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(AndroidUtilities.dp(16));
textPaint.setColor(0xff000000);
textPaint.linkColor = 0xff316f9f;
urlPaint = new Paint();
urlPaint.setColor(0x33316f9f);
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER);
addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 16, 5, LocaleController.isRTL ? 16 : 0, 0));
setWillNotDraw(false);
}
public void setDelegate(AboutLinkCellDelegate botHelpCellDelegate) {
delegate = botHelpCellDelegate;
}
private void resetPressedLink() {
if (pressedLink != null) {
pressedLink = null;
}
invalidate();
}
public void setTextAndIcon(String text, int resId) {
if (text == null || text.length() == 0) {
setVisibility(GONE);
return;
}
if (text != null && oldText != null && text.equals(oldText)) {
return;
}
oldText = text;
stringBuilder = new SpannableStringBuilder(oldText);
MessageObject.addLinks(stringBuilder, false);
Emoji.replaceEmoji(stringBuilder, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
requestLayout();
if (resId == 0) {
imageView.setImageDrawable(null);
} else {
imageView.setImageResource(resId);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean result = false;
if (textLayout != null) {
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
resetPressedLink();
try {
int x2 = (int) (x - textX);
int y2 = (int) (y - textY);
final int line = textLayout.getLineForVertical(y2);
final int off = textLayout.getOffsetForHorizontal(line, x2);
final float left = textLayout.getLineLeft(line);
if (left <= x2 && left + textLayout.getLineWidth(line) >= x2) {
Spannable buffer = (Spannable) textLayout.getText();
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
resetPressedLink();
pressedLink = link[0];
result = true;
try {
int start = buffer.getSpanStart(pressedLink);
urlPath.setCurrentLayout(textLayout, start);
textLayout.getSelectionPath(start, buffer.getSpanEnd(pressedLink), urlPath);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else {
resetPressedLink();
}
} else {
resetPressedLink();
}
} catch (Exception e) {
resetPressedLink();
FileLog.e("tmessages", e);
}
} else if (pressedLink != null) {
try {
if (pressedLink instanceof URLSpanNoUnderline) {
String url = ((URLSpanNoUnderline) pressedLink).getURL();
if (url.startsWith("@") || url.startsWith("#") || url.startsWith("/")) {
if (delegate != null) {
delegate.didPressUrl(url);
}
}
} else {
pressedLink.onClick(this);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
resetPressedLink();
result = true;
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
resetPressedLink();
}
}
return result || super.onTouchEvent(event);
}
@SuppressLint("DrawAllocation")
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
textLayout = new StaticLayout(stringBuilder, textPaint, MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(71 + 16), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(textLayout.getHeight() + AndroidUtilities.dp(16), MeasureSpec.EXACTLY));
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(textX = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71), textY = AndroidUtilities.dp(8));
if (pressedLink != null) {
canvas.drawPath(urlPath, urlPaint);
}
textLayout.draw(canvas);
canvas.restore();
}
}

View File

@ -1,61 +0,0 @@
/*
* This is the source code of Telegram for Android v. 3.x.x
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.ui.Cells;
import android.content.Context;
import android.os.Build;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.ImageView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.SimpleTextView;
public class AddMemberCell extends FrameLayout {
private SimpleTextView textView;
public AddMemberCell(Context context) {
super(context);
ImageView imageView = new ImageView(context);
imageView.setImageResource(R.drawable.addmember);
imageView.setScaleType(ImageView.ScaleType.CENTER);
addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 68, 8, LocaleController.isRTL ? 68 : 0, 0));
textView = new SimpleTextView(context);
textView.setTextColor(0xff212121);
textView.setTextSize(17);
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 129, 22.5f, LocaleController.isRTL ? 129 : 28, 0));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) {
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
getBackground().setHotspot(event.getX(), event.getY());
}
}
return super.onTouchEvent(event);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY));
}
public void setText(String text) {
textView.setText(text);
}
}

View File

@ -22,6 +22,7 @@ import android.view.MotionEvent;
import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.FileLog;
@ -97,6 +98,7 @@ public class BotHelpCell extends View {
stringBuilder.append(text);
MessageObject.addLinks(stringBuilder);
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Emoji.replaceEmoji(stringBuilder, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
textLayout = new StaticLayout(stringBuilder, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
width = 0;
height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18);

View File

@ -51,6 +51,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
void didPressUrl(MessageObject messageObject, ClickableSpan url, boolean longPress);
void needOpenWebView(String url, String title, String originalUrl, int w, int h);
void didClickedImage(ChatBaseCell cell);
void didPressShare(ChatBaseCell cell);
boolean canPerformActions();
}
@ -104,6 +105,11 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
private boolean replyPressed = false;
private TLRPC.FileLocation currentReplyPhoto;
private boolean drawShareButton;
private boolean sharePressed;
private int shareStartX;
private int shareStartY;
private StaticLayout nameLayout;
protected int nameWidth;
private float nameOffsetX = 0;
@ -306,7 +312,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
}
protected void measureTime(MessageObject messageObject) {
currentTimeString = LocaleController.formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
currentTimeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
timeTextWidth = timeWidth = (int) Math.ceil(timeMediaPaint.measureText(currentTimeString));
if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) {
currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null));
@ -323,6 +329,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
isCheckPressed = true;
isAvatarVisible = false;
wasLayout = false;
drawShareButton = false;
replyNameLayout = null;
replyTextLayout = null;
replyNameWidth = 0;
@ -345,6 +352,9 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
currentUser = MessagesController.getInstance().getUser(messageObject.messageOwner.from_id);
} else if (messageObject.messageOwner.from_id < 0) {
currentChat = MessagesController.getInstance().getChat(-messageObject.messageOwner.from_id);
if (messageObject.messageOwner.to_id.channel_id != 0 && (messageObject.messageOwner.reply_to_msg_id == 0 || messageObject.type != 13)) {
drawShareButton = true;
}
}
if (isChat && !messageObject.isOutOwner() && messageObject.messageOwner.from_id > 0) {
isAvatarVisible = true;
@ -379,7 +389,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
currentTimePaint = timeMediaPaint;
}
currentTimeString = LocaleController.formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
currentTimeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
timeTextWidth = timeWidth = (int)Math.ceil(currentTimePaint.measureText(currentTimeString));
if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) {
currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null));
@ -398,15 +408,22 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
currentNameString = "DELETED";
}
nameWidth = getMaxNameWidth();
if (nameWidth < 0) {
nameWidth = AndroidUtilities.dp(100);
}
CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace("\n", " "), namePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
nameLayout = new StaticLayout(nameStringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (nameLayout.getLineCount() > 0) {
nameWidth = (int)Math.ceil(nameLayout.getLineWidth(0));
namesOffset += AndroidUtilities.dp(19);
nameOffsetX = nameLayout.getLineLeft(0);
} else {
nameWidth = 0;
try {
nameLayout = new StaticLayout(nameStringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (nameLayout != null && nameLayout.getLineCount() > 0) {
nameWidth = (int)Math.ceil(nameLayout.getLineWidth(0));
namesOffset += AndroidUtilities.dp(19);
nameOffsetX = nameLayout.getLineLeft(0);
} else {
nameWidth = 0;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else {
currentNameString = null;
@ -580,16 +597,16 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
if (isAvatarVisible && avatarImage.isInsideImage(x, y)) {
avatarPressed = true;
result = true;
} else if (drawForwardedName && forwardedNameLayout != null) {
if (x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + AndroidUtilities.dp(32)) {
forwardNamePressed = true;
result = true;
}
} else if (currentMessageObject.isReply()) {
if (x >= replyStartX && x <= replyStartX + Math.max(replyNameWidth, replyTextWidth) && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35)) {
replyPressed = true;
result = true;
}
} else if (drawForwardedName && forwardedNameLayout != null && x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + AndroidUtilities.dp(32)) {
forwardNamePressed = true;
result = true;
} else if (currentMessageObject.isReply() && x >= replyStartX && x <= replyStartX + Math.max(replyNameWidth, replyTextWidth) && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35)) {
replyPressed = true;
result = true;
} else if (drawShareButton && x >= shareStartX && x <= shareStartX + AndroidUtilities.dp(40) && y >= shareStartY && y <= shareStartY + AndroidUtilities.dp(32)) {
sharePressed = true;
result = true;
invalidate();
}
if (result) {
startCheckLongPress();
@ -649,6 +666,21 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
replyPressed = false;
}
}
} else if (sharePressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
sharePressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
if (delegate != null) {
delegate.didPressShare(this);
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
sharePressed = false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(x >= shareStartX && x <= shareStartX + AndroidUtilities.dp(40) && y >= shareStartY && y <= shareStartY + AndroidUtilities.dp(32))) {
sharePressed = false;
}
}
invalidate();
}
}
return result;
@ -767,6 +799,11 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo
onAfterBackgroundDraw(canvas);
if (drawShareButton) {
ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].setBounds(shareStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8), shareStartY = layoutHeight - AndroidUtilities.dp(41), currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(40), layoutHeight - AndroidUtilities.dp(9));
ResourceLoader.shareDrawable[ApplicationLoader.isCustomTheme() ? 1 : 0][sharePressed ? 1 : 0].draw(canvas);
}
if (drawName && nameLayout != null) {
canvas.save();
if (media) {

View File

@ -198,6 +198,9 @@ public class ChatContactCell extends ChatBaseCell {
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);
if (maxWidth < 0) {
maxWidth = AndroidUtilities.dp(100);
}
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);

View File

@ -498,7 +498,7 @@ public class ChatMediaCell extends ChatBaseCell {
if (currentNameString == null || !currentNameString.equals(name)) {
currentNameString = name;
nameLayout = StaticLayoutEx.createStaticLayout(currentNameString, namePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, maxWidth, 1);
if (nameLayout.getLineCount() > 0) {
if (nameLayout != null && nameLayout.getLineCount() > 0) {
nameWidth = Math.min(maxWidth, (int) Math.ceil(nameLayout.getLineWidth(0)));
nameOffsetX = (int) Math.ceil(-nameLayout.getLineLeft(0));
} else {
@ -746,14 +746,18 @@ public class ChatMediaCell extends ChatBaseCell {
backgroundWidth += AndroidUtilities.dp(9);
}
if (messageObject.caption != null) {
nameLayout = new StaticLayout(messageObject.caption, MessageObject.textPaint, photoWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (nameLayout.getLineCount() > 0) {
captionHeight = nameLayout.getHeight();
additionHeight += captionHeight + AndroidUtilities.dp(9);
float lastLineWidth = nameLayout.getLineWidth(nameLayout.getLineCount() - 1) + nameLayout.getLineLeft(nameLayout.getLineCount() - 1);
if (photoWidth - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) {
additionHeight += AndroidUtilities.dp(14);
try {
nameLayout = new StaticLayout(messageObject.caption, MessageObject.textPaint, photoWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (nameLayout != null && nameLayout.getLineCount() > 0) {
captionHeight = nameLayout.getHeight();
additionHeight += captionHeight + AndroidUtilities.dp(9);
float lastLineWidth = nameLayout.getLineWidth(nameLayout.getLineCount() - 1) + nameLayout.getLineLeft(nameLayout.getLineCount() - 1);
if (photoWidth - AndroidUtilities.dp(8) - lastLineWidth < timeWidthTotal) {
additionHeight += AndroidUtilities.dp(14);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}

View File

@ -532,17 +532,18 @@ public class ChatMessageCell extends ChatBaseCell {
}
}
boolean authorIsRTL = false;
if (webPage.author != null) {
try {
if (linkPreviewHeight != 0) {
linkPreviewHeight += AndroidUtilities.dp(2);
totalHeight += AndroidUtilities.dp(2);
}
int width = Math.min((int) Math.ceil(replyNamePaint.measureText(webPage.author)), linkPreviewMaxWidth);
//int width = Math.min((int) Math.ceil(replyNamePaint.measureText(webPage.author)), linkPreviewMaxWidth);
if (restLinesCount == 3 && (!isSmallImage || webPage.description == null)) {
authorLayout = new StaticLayout(webPage.author, replyNamePaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
authorLayout = new StaticLayout(webPage.author, replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
} else {
authorLayout = generateStaticLayout(webPage.author, replyNamePaint, width, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 2), restLinesCount, 1);
authorLayout = generateStaticLayout(webPage.author, replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 2), restLinesCount, 1);
restLinesCount -= authorLayout.getLineCount();
}
int height = authorLayout.getLineBottom(authorLayout.getLineCount() - 1);
@ -550,6 +551,13 @@ public class ChatMessageCell extends ChatBaseCell {
totalHeight += height;
int lineLeft = (int) authorLayout.getLineLeft(0);
authorX = -lineLeft;
int width;
if (lineLeft != 0) {
width = authorLayout.getWidth() - lineLeft;
authorIsRTL = true;
} else {
width = (int) Math.ceil(authorLayout.getLineWidth(0));
}
maxChildWidth = Math.max(maxChildWidth, width + additinalWidth);
maxWebWidth = Math.max(maxWebWidth, width + additinalWidth);
} catch (Exception e) {
@ -575,19 +583,31 @@ public class ChatMessageCell extends ChatBaseCell {
int height = descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1);
linkPreviewHeight += height;
totalHeight += height;
boolean hasRTL = false;
for (int a = 0; a < descriptionLayout.getLineCount(); a++) {
int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a));
if (a == 0 && descriptionX == 0) {
descriptionX = -lineLeft;
} else {
descriptionX = Math.max(descriptionX, -lineLeft);
if (lineLeft != 0) {
hasRTL = true;
if (descriptionX == 0) {
descriptionX = -lineLeft;
} else {
descriptionX = Math.max(descriptionX, -lineLeft);
}
}
}
for (int a = 0; a < descriptionLayout.getLineCount(); a++) {
int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a));
if (lineLeft == 0 && descriptionX != 0) {
descriptionX = 0;
}
int width;
if (lineLeft != 0) {
width = descriptionLayout.getWidth() - lineLeft;
} else {
width = (int) Math.ceil(descriptionLayout.getLineWidth(a));
width = hasRTL ? descriptionLayout.getWidth() : (int) Math.ceil(descriptionLayout.getLineWidth(a));
}
if (a < restLines || lineLeft != 0 && isSmallImage) {
width += AndroidUtilities.dp(48 + 2);
@ -596,6 +616,9 @@ public class ChatMessageCell extends ChatBaseCell {
if (titleIsRTL) {
titleX += (width + additinalWidth - maxWebWidth);
}
if (authorIsRTL) {
authorX += (width + additinalWidth - maxWebWidth);
}
maxWebWidth = width + additinalWidth;
}
maxChildWidth = Math.max(maxChildWidth, width + additinalWidth);

View File

@ -21,6 +21,7 @@ import android.view.MotionEvent;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.UserObject;
@ -40,7 +41,6 @@ public class DialogCell extends BaseCell {
private static TextPaint namePaint;
private static TextPaint nameEncryptedPaint;
private static TextPaint nameUnknownPaint;
private static TextPaint messagePaint;
private static TextPaint messagePrintingPaint;
private static TextPaint timePaint;
@ -55,6 +55,7 @@ public class DialogCell extends BaseCell {
private static Drawable countDrawableGrey;
private static Drawable groupDrawable;
private static Drawable broadcastDrawable;
private static Drawable botDrawable;
private static Drawable muteDrawable;
private static Drawable verifiedDrawable;
@ -87,6 +88,7 @@ public class DialogCell extends BaseCell {
private boolean drawNameLock;
private boolean drawNameGroup;
private boolean drawNameBroadcast;
private boolean drawNameBot;
private int nameMuteLeft;
private int nameLockLeft;
private int nameLockTop;
@ -136,11 +138,6 @@ public class DialogCell extends BaseCell {
nameEncryptedPaint.setColor(0xff00a60e);
nameEncryptedPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
nameUnknownPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
nameUnknownPaint.setTextSize(AndroidUtilities.dp(17));
nameUnknownPaint.setColor(0xff4d83b3);
nameUnknownPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
messagePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
messagePaint.setTextSize(AndroidUtilities.dp(16));
messagePaint.setColor(0xff8f8f8f);
@ -176,6 +173,7 @@ public class DialogCell extends BaseCell {
broadcastDrawable = getResources().getDrawable(R.drawable.list_broadcast);
muteDrawable = getResources().getDrawable(R.drawable.mute_grey);
verifiedDrawable = getResources().getDrawable(R.drawable.check_list);
botDrawable = getResources().getDrawable(R.drawable.bot_list);
}
setBackgroundResource(R.drawable.list_selector);
@ -264,6 +262,7 @@ public class DialogCell extends BaseCell {
drawNameGroup = false;
drawNameBroadcast = false;
drawNameLock = false;
drawNameBot = false;
drawVerified = false;
if (encryptedChat != null) {
@ -278,14 +277,14 @@ public class DialogCell extends BaseCell {
}
} else {
if (chat != null) {
if (chat.id < 0 || chat instanceof TLRPC.TL_channel || chat instanceof TLRPC.TL_channelForbidden) {
if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) {
drawNameBroadcast = true;
nameLockTop = AndroidUtilities.dp(16.5f);
} else {
drawNameGroup = true;
nameLockTop = AndroidUtilities.dp(17.5f);
}
drawVerified = (chat.flags & TLRPC.CHAT_FLAG_IS_VERIFIED) != 0;
drawVerified = chat.verified;
if (!LocaleController.isRTL) {
nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
@ -300,6 +299,20 @@ public class DialogCell extends BaseCell {
} else {
nameLeft = AndroidUtilities.dp(14);
}
if (user != null) {
if (user.bot) {
drawNameBot = true;
nameLockTop = AndroidUtilities.dp(16.5f);
if (!LocaleController.isRTL) {
nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + botDrawable.getIntrinsicWidth();
} else {
nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - botDrawable.getIntrinsicWidth();
nameLeft = AndroidUtilities.dp(14);
}
}
drawVerified = user.verified;
}
}
}
@ -383,11 +396,11 @@ public class DialogCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff808080>%s</c>", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff808080>%s</c>", name.replace("\n", ""), mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
} else {
if (message.messageOwner.media != null && !message.isMediaEmpty()) {
currentMessagePaint = messagePrintingPaint;
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff4d83b3>%s</c>", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff4d83b3>%s</c>", name.replace("\n", ""), message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
} else {
if (message.messageOwner.message != null) {
String mess = message.messageOwner.message;
@ -395,7 +408,7 @@ public class DialogCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff808080>%s</c>", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("<c#ff4d83b3>%s:</c> <c#ff808080>%s</c>", name.replace("\n", ""), mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
}
}
@ -468,7 +481,6 @@ public class DialogCell extends BaseCell {
if (user.phone != null && user.phone.length() != 0) {
nameString = PhoneFormat.getInstance().format("+" + user.phone);
} else {
currentNamePaint = nameUnknownPaint;
nameString = UserObject.getUserName(user);
}
}
@ -497,6 +509,8 @@ public class DialogCell extends BaseCell {
nameWidth -= AndroidUtilities.dp(4) + groupDrawable.getIntrinsicWidth();
} else if (drawNameBroadcast) {
nameWidth -= AndroidUtilities.dp(4) + broadcastDrawable.getIntrinsicWidth();
} else if (drawNameBot) {
nameWidth -= AndroidUtilities.dp(4) + botDrawable.getIntrinsicWidth();
}
if (drawClock) {
int w = clockDrawable.getIntrinsicWidth() + AndroidUtilities.dp(5);
@ -678,7 +692,7 @@ public class DialogCell extends BaseCell {
public void checkCurrentDialogIndex() {
if (index < getDialogsArray().size()) {
TLRPC.Dialog dialog = getDialogsArray().get(index);
if (currentDialogId != dialog.id || message != null && message.getId() != dialog.top_message || unreadCount != dialog.unread_count) {
if (currentDialogId != dialog.id || message != null && message.getId() != dialog.top_message || unreadCount != dialog.unread_count || message == null && MessagesController.getInstance().dialogMessage.get(dialog.id) != null) {
currentDialogId = dialog.id;
update(0);
}
@ -766,6 +780,12 @@ public class DialogCell extends BaseCell {
} else {
if (lower_id < 0) {
chat = MessagesController.getInstance().getChat(-lower_id);
if (!isDialogCell && chat != null && chat.migrated_to != null) {
TLRPC.Chat chat2 = MessagesController.getInstance().getChat(chat.migrated_to.channel_id);
if (chat2 != null) {
chat = chat2;
}
}
} else {
user = MessagesController.getInstance().getUser(lower_id);
}
@ -819,6 +839,9 @@ public class DialogCell extends BaseCell {
} else if (drawNameBroadcast) {
setDrawableBounds(broadcastDrawable, nameLockLeft, nameLockTop);
broadcastDrawable.draw(canvas);
} else if (drawNameBot) {
setDrawableBounds(botDrawable, nameLockLeft, nameLockTop);
botDrawable.draw(canvas);
}
if (nameLayout != null) {

View File

@ -15,6 +15,7 @@ import android.widget.FrameLayout;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.ui.Components.LayoutHelper;
public class DrawerActionCell extends FrameLayout {
@ -42,7 +43,11 @@ public class DrawerActionCell extends FrameLayout {
}
public void setTextAndIcon(String text, int resId) {
textView.setText(text);
textView.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0);
try {
textView.setText(text);
textView.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0);
} catch (Throwable e) {
FileLog.e("tmessages", e);
}
}
}

View File

@ -9,8 +9,10 @@
package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Rect;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.widget.FrameLayout;
@ -28,6 +30,13 @@ public class PhotoAttachPhotoCell extends FrameLayout {
private FrameLayout checkFrame;
private CheckBox checkBox;
private boolean isLast;
private boolean pressed;
private static Rect rect = new Rect();
private PhotoAttachPhotoCellDelegate delegate;
public interface PhotoAttachPhotoCellDelegate {
void onCheckClick(PhotoAttachPhotoCell v);
}
private MediaController.PhotoEntry photoEntry;
@ -36,13 +45,7 @@ public class PhotoAttachPhotoCell extends FrameLayout {
imageView = new BackupImageView(context);
addView(imageView, LayoutHelper.createFrame(80, 80));
checkFrame = new FrameLayout(context) {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.onInterceptTouchEvent(ev);
}
};
checkFrame = new FrameLayout(context);
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0));
checkBox = new CheckBox(context, R.drawable.checkbig);
@ -72,6 +75,7 @@ public class PhotoAttachPhotoCell extends FrameLayout {
}
public void setPhotoEntry(MediaController.PhotoEntry entry, boolean last) {
pressed = false;
photoEntry = entry;
isLast = last;
if (photoEntry.thumbPath != null) {
@ -95,4 +99,43 @@ public class PhotoAttachPhotoCell extends FrameLayout {
public void setOnCheckClickLisnener(OnClickListener onCheckClickLisnener) {
checkFrame.setOnClickListener(onCheckClickLisnener);
}
public void setDelegate(PhotoAttachPhotoCellDelegate delegate) {
this.delegate = delegate;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = false;
checkFrame.getHitRect(rect);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (rect.contains((int) event.getX(), (int) event.getY())) {
pressed = true;
invalidate();
result = true;
}
} else if (pressed) {
if (event.getAction() == MotionEvent.ACTION_UP) {
getParent().requestDisallowInterceptTouchEvent(true);
pressed = false;
playSoundEffect(SoundEffectConstants.CLICK);
delegate.onCheckClick(this);
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
pressed = false;
invalidate();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (!(rect.contains((int) event.getX(), (int) event.getY()))) {
pressed = false;
invalidate();
}
}
}
if (!result) {
result = super.onTouchEvent(event);
}
return result;
}
}

View File

@ -41,9 +41,11 @@ public class ProfileSearchCell extends BaseCell {
private static TextPaint offlinePaint;
private static TextPaint countPaint;
private static Drawable lockDrawable;
private static Drawable botDrawable;
private static Drawable broadcastDrawable;
private static Drawable groupDrawable;
private static Drawable countDrawable;
private static Drawable countDrawableGrey;
private static Drawable checkDrawable;
private static Paint linePaint;
@ -55,7 +57,7 @@ public class ProfileSearchCell extends BaseCell {
private TLRPC.User user = null;
private TLRPC.Chat chat = null;
private TLRPC.EncryptedChat encryptedChat = null;
long dialog_id;
private long dialog_id;
private String lastName = null;
private int lastStatus = 0;
@ -70,6 +72,7 @@ public class ProfileSearchCell extends BaseCell {
private boolean drawNameLock;
private boolean drawNameBroadcast;
private boolean drawNameGroup;
private boolean drawNameBot;
private int nameLockLeft;
private int nameLockTop;
@ -119,7 +122,9 @@ public class ProfileSearchCell extends BaseCell {
lockDrawable = getResources().getDrawable(R.drawable.list_secret);
groupDrawable = getResources().getDrawable(R.drawable.list_group);
countDrawable = getResources().getDrawable(R.drawable.dialogs_badge);
countDrawableGrey = getResources().getDrawable(R.drawable.dialogs_badge2);
checkDrawable = getResources().getDrawable(R.drawable.check_list);
botDrawable = getResources().getDrawable(R.drawable.bot_list);
}
avatarImage = new ImageReceiver(this);
@ -188,6 +193,7 @@ public class ProfileSearchCell extends BaseCell {
drawNameLock = false;
drawNameGroup = false;
drawCheck = false;
drawNameBot = false;
if (encryptedChat != null) {
drawNameLock = true;
@ -208,7 +214,7 @@ public class ProfileSearchCell extends BaseCell {
nameLockTop = AndroidUtilities.dp(28.5f);
} else {
dialog_id = -chat.id;
if (ChatObject.isChannel(chat)) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
drawNameBroadcast = true;
nameLockTop = AndroidUtilities.dp(28.5f);
} else {
@ -216,7 +222,7 @@ public class ProfileSearchCell extends BaseCell {
nameLockTop = AndroidUtilities.dp(30);
}
}
drawCheck = (chat.flags & TLRPC.CHAT_FLAG_IS_VERIFIED) != 0;
drawCheck = chat.verified;
if (!LocaleController.isRTL) {
nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth());
@ -231,6 +237,20 @@ public class ProfileSearchCell extends BaseCell {
} else {
nameLeft = AndroidUtilities.dp(11);
}
if (user.bot) {
drawNameBot = true;
if (!LocaleController.isRTL) {
nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + botDrawable.getIntrinsicWidth();
} else {
nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - botDrawable.getIntrinsicWidth();
nameLeft = AndroidUtilities.dp(11);
}
nameLockTop = AndroidUtilities.dp(16.5f);
} else {
nameLockTop = AndroidUtilities.dp(17);
}
drawCheck = user.verified;
}
}
@ -271,6 +291,8 @@ public class ProfileSearchCell extends BaseCell {
nameWidth -= AndroidUtilities.dp(6) + broadcastDrawable.getIntrinsicWidth();
} else if (drawNameGroup) {
nameWidth -= AndroidUtilities.dp(6) + groupDrawable.getIntrinsicWidth();
} else if (drawNameBot) {
nameWidth -= AndroidUtilities.dp(6) + botDrawable.getIntrinsicWidth();
}
if (drawCount) {
@ -313,7 +335,7 @@ public class ProfileSearchCell extends BaseCell {
if (subLabel != null) {
onlineString = subLabel;
} else if (user != null) {
if ((user.flags & TLRPC.USER_FLAG_BOT) != 0) {
if (user.bot) {
onlineString = LocaleController.getString("Bot", R.string.Bot);
} else {
onlineString = LocaleController.formatUserStatus(user);
@ -327,7 +349,7 @@ public class ProfileSearchCell extends BaseCell {
CharSequence onlineStringFinal = TextUtils.ellipsize(onlineString, currentOnlinePaint, onlineWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
onlineLayout = new StaticLayout(onlineStringFinal, currentOnlinePaint, onlineWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
nameTop = AndroidUtilities.dp(13);
if (subLabel != null) {
if (subLabel != null && !drawNameBot) {
nameLockTop -= AndroidUtilities.dp(12);
}
} else {
@ -492,6 +514,9 @@ public class ProfileSearchCell extends BaseCell {
} else if (drawNameBroadcast) {
setDrawableBounds(broadcastDrawable, nameLockLeft, nameLockTop);
broadcastDrawable.draw(canvas);
} else if (drawNameBot) {
setDrawableBounds(botDrawable, nameLockLeft, nameLockTop);
botDrawable.draw(canvas);
}
if (nameLayout != null) {
@ -517,8 +542,13 @@ public class ProfileSearchCell extends BaseCell {
}
if (countLayout != null) {
setDrawableBounds(countDrawable, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight());
countDrawable.draw(canvas);
if (MessagesController.getInstance().isDialogMuted(dialog_id)) {
setDrawableBounds(countDrawableGrey, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawableGrey.getIntrinsicHeight());
countDrawableGrey.draw(canvas);
} else {
setDrawableBounds(countDrawable, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight());
countDrawable.draw(canvas);
}
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
countLayout.draw(canvas);

View File

@ -0,0 +1,101 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.ui.Cells;
import android.content.Context;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox;
import org.telegram.ui.Components.LayoutHelper;
public class ShareDialogCell extends FrameLayout {
private BackupImageView imageView;
private TextView nameTextView;
private CheckBox checkBox;
private AvatarDrawable avatarDrawable = new AvatarDrawable();
public ShareDialogCell(Context context) {
super(context);
imageView = new BackupImageView(context);
imageView.setRoundRadius(AndroidUtilities.dp(27));
addView(imageView, LayoutHelper.createFrame(54, 54, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 7, 0, 0));
nameTextView = new TextView(context);
nameTextView.setTextColor(0xff212121);
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
nameTextView.setMaxLines(2);
nameTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
nameTextView.setLines(2);
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 64, 6, 0));
checkBox = new CheckBox(context, R.drawable.round_check2);
checkBox.setSize(24);
checkBox.setCheckOffset(AndroidUtilities.dp(1));
checkBox.setVisibility(VISIBLE);
checkBox.setColor(0xff3ec1f9);
addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 17, 39, 0, 0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.EXACTLY));
}
public void setDialog(TLRPC.Dialog dialog, boolean checked, CharSequence name) {
int lower_id = (int) dialog.id;
TLRPC.FileLocation photo = null;
if (lower_id > 0) {
TLRPC.User user = MessagesController.getInstance().getUser(lower_id);
if (name != null) {
nameTextView.setText(name);
} else if (user != null) {
nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name));
} else {
nameTextView.setText("");
}
avatarDrawable.setInfo(user);
if (user != null && user.photo != null) {
photo = user.photo.photo_small;
}
} else {
TLRPC.Chat chat = MessagesController.getInstance().getChat(-lower_id);
if (name != null) {
nameTextView.setText(name);
} else if (chat != null) {
nameTextView.setText(chat.title);
} else {
nameTextView.setText("");
}
avatarDrawable.setInfo(chat);
if (chat != null && chat.photo != null) {
photo = chat.photo.photo_small;
}
}
imageView.setImage(photo, "50_50", avatarDrawable);
checkBox.setChecked(checked, false);
}
public void setChecked(boolean checked, boolean animated) {
checkBox.setChecked(checked, animated);
}
}

View File

@ -220,7 +220,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F
thumbImageView.setImage(document.messageOwner.media.document.thumb.location, "40_40", (Drawable) null);
}
long date = (long) document.messageOwner.date * 1000;
dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(document.messageOwner.media.document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.formatterYear.format(new Date(date)), LocaleController.formatterDay.format(new Date(date)))));
dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(document.messageOwner.media.document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date)))));
} else {
nameTextView.setText("");
extTextView.setText("");

View File

@ -98,7 +98,7 @@ public class StickerSetCell extends FrameLayout {
stickersSet = set;
textView.setText(stickersSet.set.title);
if ((stickersSet.set.flags & 2) != 0) {
if (stickersSet.set.disabled) {
ViewProxy.setAlpha(textView, 0.5f);
ViewProxy.setAlpha(valueTextView, 0.5f);
ViewProxy.setAlpha(imageView, 0.5f);

View File

@ -28,8 +28,6 @@ public class TextCell extends FrameLayout {
private ImageView imageView;
private ImageView valueImageView;
private boolean multiline;
public TextCell(Context context) {
super(context);
@ -63,7 +61,7 @@ public class TextCell extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), multiline ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) : MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY));
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY));
}
public void setTextColor(int color) {
@ -83,27 +81,7 @@ public class TextCell extends FrameLayout {
imageView.setVisibility(VISIBLE);
valueTextView.setVisibility(INVISIBLE);
valueImageView.setVisibility(INVISIBLE);
if (multiline) {
imageView.setPadding(0, 0, 0, 0);
} else {
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
}
}
public void setMultiline(boolean value) {
if (multiline == value) {
return;
}
multiline = value;
if (value) {
textView.setSingleLine(false);
textView.setPadding(0, AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6));
} else {
textView.setLines(1);
textView.setMaxLines(1);
textView.setSingleLine(true);
}
requestLayout();
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
}
public void setTextAndValue(String text, String value) {
@ -120,10 +98,6 @@ public class TextCell extends FrameLayout {
valueImageView.setImageDrawable(drawable);
valueTextView.setVisibility(INVISIBLE);
imageView.setVisibility(INVISIBLE);
if (multiline) {
imageView.setPadding(0, 0, 0, 0);
} else {
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
}
imageView.setPadding(0, AndroidUtilities.dp(7), 0, 0);
}
}

View File

@ -25,6 +25,7 @@ import org.telegram.messenger.UserConfig;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox;
import org.telegram.ui.Components.CheckBoxSquare;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.SimpleTextView;
@ -35,6 +36,7 @@ public class UserCell extends FrameLayout {
private SimpleTextView statusTextView;
private ImageView imageView;
private CheckBox checkBox;
private CheckBoxSquare checkBoxBig;
private AvatarDrawable avatarDrawable;
private TLObject currentObject = null;
@ -50,7 +52,7 @@ public class UserCell extends FrameLayout {
private int statusColor = 0xffa8a8a8;
private int statusOnlineColor = 0xff3b84c0;
public UserCell(Context context, int padding) {
public UserCell(Context context, int padding, int checkbox) {
super(context);
avatarDrawable = new AvatarDrawable();
@ -75,9 +77,14 @@ public class UserCell extends FrameLayout {
imageView.setVisibility(GONE);
addView(imageView, LayoutHelper.createFrame(LayoutParams.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 16, 0, LocaleController.isRTL ? 16 : 0, 0));
checkBox = new CheckBox(context, R.drawable.round_check2);
checkBox.setVisibility(INVISIBLE);
addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 37 + padding, 38, LocaleController.isRTL ? 37 + padding : 0, 0));
if (checkbox == 2) {
checkBoxBig = new CheckBoxSquare(context);
addView(checkBoxBig, LayoutHelper.createFrame(18, 18, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 19 : 0, 0, LocaleController.isRTL ? 0 : 19, 0));
} else if (checkbox == 1) {
checkBox = new CheckBox(context, R.drawable.round_check2);
checkBox.setVisibility(INVISIBLE);
addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 37 + padding, 38, LocaleController.isRTL ? 37 + padding : 0, 0));
}
}
public void setData(TLObject user, CharSequence name, CharSequence status, int resId) {
@ -98,10 +105,23 @@ public class UserCell extends FrameLayout {
}
public void setChecked(boolean checked, boolean animated) {
if (checkBox.getVisibility() != VISIBLE) {
checkBox.setVisibility(VISIBLE);
if (checkBox != null) {
if (checkBox.getVisibility() != VISIBLE) {
checkBox.setVisibility(VISIBLE);
}
checkBox.setChecked(checked, animated);
} else if (checkBoxBig != null) {
if (checkBoxBig.getVisibility() != VISIBLE) {
checkBoxBig.setVisibility(VISIBLE);
}
checkBoxBig.setChecked(checked, animated);
}
}
public void setCheckDisabled(boolean disabled) {
if (checkBoxBig != null) {
checkBoxBig.setDisabled(disabled);
}
checkBox.setChecked(checked, animated);
}
@Override
@ -191,9 +211,9 @@ public class UserCell extends FrameLayout {
statusTextView.setTextColor(statusColor);
statusTextView.setText(currrntStatus);
} else if (currentUser != null) {
if ((currentUser.flags & TLRPC.USER_FLAG_BOT) != 0) {
if (currentUser.bot) {
statusTextView.setTextColor(statusColor);
if ((currentUser.flags & TLRPC.USER_FLAG_BOT_READING_HISTORY) != 0) {
if (currentUser.bot_chat_history) {
statusTextView.setText(LocaleController.getString("BotStatusRead", R.string.BotStatusRead));
} else {
statusTextView.setText(LocaleController.getString("BotStatusCantRead", R.string.BotStatusCantRead));

View File

@ -139,8 +139,15 @@ public class ChangeChatNameActivity extends BaseFragment {
@Override
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen) {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (firstNameField != null) {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
}
}
}, 100);
}
}

View File

@ -187,8 +187,15 @@ public class ChangeNameActivity extends BaseFragment {
@Override
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen) {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
if (firstNameField != null) {
firstNameField.requestFocus();
AndroidUtilities.showKeyboard(firstNameField);
}
}
}, 100);
}
}
}

View File

@ -56,6 +56,7 @@ import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy;
import org.telegram.messenger.AnimationCompat.AnimatorSetProxy;
import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy;
import org.telegram.messenger.AnimationCompat.ViewProxy;
import org.telegram.ui.Components.HintEditText;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.SlideView;
import org.telegram.ui.Components.TypefaceSpan;
@ -259,7 +260,7 @@ public class ChangePhoneActivity extends BaseFragment {
public class PhoneView extends SlideView implements AdapterView.OnItemSelectedListener {
private EditText codeField;
private EditText phoneField;
private HintEditText phoneField;
private TextView countryButton;
private int countryState = 0;
@ -267,6 +268,7 @@ public class ChangePhoneActivity extends BaseFragment {
private ArrayList<String> countriesArray = new ArrayList<>();
private HashMap<String, String> countriesMap = new HashMap<>();
private HashMap<String, String> codesMap = new HashMap<>();
private HashMap<String, String> phoneFormatMap = new HashMap<>();
private boolean ignoreSelection = false;
private boolean ignoreOnTextChange = false;
@ -287,14 +289,7 @@ public class ChangePhoneActivity extends BaseFragment {
countryButton.setEllipsize(TextUtils.TruncateAt.END);
countryButton.setGravity(Gravity.LEFT | Gravity.CENTER_HORIZONTAL);
countryButton.setBackgroundResource(R.drawable.spinner_states);
addView(countryButton);
LayoutParams layoutParams = (LayoutParams) countryButton.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(36);
layoutParams.leftMargin = AndroidUtilities.dp(20);
layoutParams.rightMargin = AndroidUtilities.dp(20);
layoutParams.bottomMargin = AndroidUtilities.dp(14);
countryButton.setLayoutParams(layoutParams);
addView(countryButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 20, 0, 20, 14));
countryButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@ -303,7 +298,14 @@ public class ChangePhoneActivity extends BaseFragment {
@Override
public void didSelectCountry(String name) {
selectCountry(name);
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
AndroidUtilities.showKeyboard(phoneField);
}
}, 300);
phoneField.requestFocus();
phoneField.setSelection(phoneField.length());
}
});
presentFragment(fragment);
@ -313,34 +315,17 @@ public class ChangePhoneActivity extends BaseFragment {
View view = new View(context);
view.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0);
view.setBackgroundColor(0xffdbdbdb);
addView(view);
layoutParams = (LayoutParams) view.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = 1;
layoutParams.leftMargin = AndroidUtilities.dp(24);
layoutParams.rightMargin = AndroidUtilities.dp(24);
layoutParams.topMargin = AndroidUtilities.dp(-17.5f);
view.setLayoutParams(layoutParams);
addView(view, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1, 24, -17.5f, 24, 0));
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(HORIZONTAL);
addView(linearLayout);
layoutParams = (LayoutParams) linearLayout.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = LayoutHelper.WRAP_CONTENT;
layoutParams.topMargin = AndroidUtilities.dp(20);
linearLayout.setLayoutParams(layoutParams);
addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 20, 0, 0));
TextView textView = new TextView(context);
textView.setText("+");
textView.setTextColor(0xff212121);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
linearLayout.addView(textView);
layoutParams = (LayoutParams) textView.getLayoutParams();
layoutParams.width = LayoutHelper.WRAP_CONTENT;
layoutParams.height = LayoutHelper.WRAP_CONTENT;
layoutParams.leftMargin = AndroidUtilities.dp(24);
textView.setLayoutParams(layoutParams);
linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 24, 0, 0, 0));
codeField = new EditText(context);
codeField.setInputType(InputType.TYPE_CLASS_PHONE);
@ -352,15 +337,9 @@ public class ChangePhoneActivity extends BaseFragment {
codeField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
InputFilter[] inputFilters = new InputFilter[1];
inputFilters[0] = new InputFilter.LengthFilter(4);
inputFilters[0] = new InputFilter.LengthFilter(5);
codeField.setFilters(inputFilters);
linearLayout.addView(codeField);
layoutParams = (LayoutParams) codeField.getLayoutParams();
layoutParams.width = AndroidUtilities.dp(55);
layoutParams.height = AndroidUtilities.dp(36);
layoutParams.rightMargin = AndroidUtilities.dp(16);
layoutParams.leftMargin = AndroidUtilities.dp(-9);
codeField.setLayoutParams(layoutParams);
linearLayout.addView(codeField, LayoutHelper.createLinear(55, 36, -9, 0, 16, 0));
codeField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
@ -383,26 +362,57 @@ public class ChangePhoneActivity extends BaseFragment {
codeField.setText(text);
if (text.length() == 0) {
countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry));
phoneField.setHintText(null);
countryState = 1;
} else {
String country = codesMap.get(text);
String country;
boolean ok = false;
String textToSet = null;
if (text.length() > 4) {
ignoreOnTextChange = true;
for (int a = 4; a >= 1; a--) {
String sub = text.substring(0, a);
country = codesMap.get(sub);
if (country != null) {
ok = true;
textToSet = text.substring(a, text.length()) + phoneField.getText().toString();
codeField.setText(text = sub);
break;
}
}
if (!ok) {
ignoreOnTextChange = true;
textToSet = text.substring(1, text.length()) + phoneField.getText().toString();
codeField.setText(text = text.substring(0, 1));
}
}
country = codesMap.get(text);
if (country != null) {
int index = countriesArray.indexOf(country);
if (index != -1) {
ignoreSelection = true;
countryButton.setText(countriesArray.get(index));
updatePhoneField();
String hint = phoneFormatMap.get(text);
phoneField.setHintText(hint != null ? hint.replace('X', '') : null);
countryState = 0;
} else {
countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry));
phoneField.setHintText(null);
countryState = 2;
}
} else {
countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry));
phoneField.setHintText(null);
countryState = 2;
}
codeField.setSelection(codeField.getText().length());
if (!ok) {
codeField.setSelection(codeField.getText().length());
}
if (textToSet != null) {
phoneField.requestFocus();
phoneField.setText(textToSet);
phoneField.setSelection(phoneField.length());
}
}
}
});
@ -411,13 +421,14 @@ public class ChangePhoneActivity extends BaseFragment {
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_NEXT) {
phoneField.requestFocus();
phoneField.setSelection(phoneField.length());
return true;
}
return false;
}
});
phoneField = new EditText(context);
phoneField = new HintEditText(context);
phoneField.setInputType(InputType.TYPE_CLASS_PHONE);
phoneField.setTextColor(0xff212121);
phoneField.setHintTextColor(0xff979797);
@ -427,43 +438,25 @@ public class ChangePhoneActivity extends BaseFragment {
phoneField.setMaxLines(1);
phoneField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
phoneField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
linearLayout.addView(phoneField);
layoutParams = (LayoutParams) phoneField.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(36);
layoutParams.rightMargin = AndroidUtilities.dp(24);
phoneField.setLayoutParams(layoutParams);
linearLayout.addView(phoneField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 0, 0, 24, 0));
phoneField.addTextChangedListener(new TextWatcher() {
private int characterAction = -1;
private int actionPosition;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (ignoreOnPhoneChange) {
return;
}
if (count == 1 && after == 0 && s.length() > 1) {
String phoneChars = "0123456789";
String str = s.toString();
String substr = str.substring(start, start + 1);
if (!phoneChars.contains(substr)) {
ignoreOnPhoneChange = true;
StringBuilder builder = new StringBuilder(str);
int toDelete = 0;
for (int a = start; a >= 0; a--) {
substr = str.substring(a, a + 1);
if(phoneChars.contains(substr)) {
break;
}
toDelete++;
}
builder.delete(Math.max(0, start - toDelete), start + 1);
str = builder.toString();
if (PhoneFormat.strip(str).length() == 0) {
phoneField.setText("");
} else {
phoneField.setText(str);
updatePhoneField();
}
ignoreOnPhoneChange = false;
if (count == 0 && after == 1) {
characterAction = 1;
} else if (count == 1 && after == 0) {
if (s.charAt(start) == ' ' && start > 0) {
characterAction = 3;
actionPosition = start - 1;
} else {
characterAction = 2;
}
} else {
characterAction = -1;
}
}
@ -477,7 +470,47 @@ public class ChangePhoneActivity extends BaseFragment {
if (ignoreOnPhoneChange) {
return;
}
updatePhoneField();
int start = phoneField.getSelectionStart();
String phoneChars = "0123456789";
String str = phoneField.getText().toString();
if (characterAction == 3) {
str = str.substring(0, actionPosition) + str.substring(actionPosition + 1, str.length());
start--;
}
StringBuilder builder = new StringBuilder(str.length());
for (int a = 0; a < str.length(); a++) {
String ch = str.substring(a, a + 1);
if (phoneChars.contains(ch)) {
builder.append(ch);
}
}
ignoreOnPhoneChange = true;
String hint = phoneField.getHintText();
if (hint != null) {
for (int a = 0; a < builder.length(); a++) {
if (a < hint.length()) {
if (hint.charAt(a) == ' ') {
builder.insert(a, ' ');
a++;
if (start == a && characterAction != 2 && characterAction != 3) {
start++;
}
}
} else {
builder.insert(a, ' ');
if (start == a + 1 && characterAction != 2 && characterAction != 3) {
start++;
}
break;
}
}
}
phoneField.setText(builder);
if (start >= 0) {
phoneField.setSelection(start <= phoneField.length() ? start : phoneField.length());
}
phoneField.onTextChange();
ignoreOnPhoneChange = false;
}
});
phoneField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@ -497,16 +530,7 @@ public class ChangePhoneActivity extends BaseFragment {
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setGravity(Gravity.LEFT);
textView.setLineSpacing(AndroidUtilities.dp(2), 1.0f);
addView(textView);
layoutParams = (LayoutParams) textView.getLayoutParams();
layoutParams.width = LayoutHelper.WRAP_CONTENT;
layoutParams.height = LayoutHelper.WRAP_CONTENT;
layoutParams.leftMargin = AndroidUtilities.dp(24);
layoutParams.rightMargin = AndroidUtilities.dp(24);
layoutParams.topMargin = AndroidUtilities.dp(28);
layoutParams.bottomMargin = AndroidUtilities.dp(10);
layoutParams.gravity = Gravity.LEFT;
textView.setLayoutParams(layoutParams);
addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, 24, 28, 24, 10));
HashMap<String, String> languageMap = new HashMap<>();
try {
@ -517,6 +541,9 @@ public class ChangePhoneActivity extends BaseFragment {
countriesArray.add(0, args[2]);
countriesMap.put(args[2], args[0]);
codesMap.put(args[0], args[2]);
if (args.length > 3) {
phoneFormatMap.put(args[0], args[3]);
}
languageMap.put(args[1], args[2]);
}
reader.close();
@ -554,12 +581,14 @@ public class ChangePhoneActivity extends BaseFragment {
}
if (codeField.length() == 0) {
countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry));
phoneField.setHintText(null);
countryState = 1;
}
if (codeField.length() != 0) {
AndroidUtilities.showKeyboard(phoneField);
phoneField.requestFocus();
phoneField.setSelection(phoneField.length());
} else {
AndroidUtilities.showKeyboard(codeField);
codeField.requestFocus();
@ -570,39 +599,15 @@ public class ChangePhoneActivity extends BaseFragment {
int index = countriesArray.indexOf(name);
if (index != -1) {
ignoreOnTextChange = true;
codeField.setText(countriesMap.get(name));
String code = countriesMap.get(name);
codeField.setText(code);
countryButton.setText(name);
String hint = phoneFormatMap.get(code);
phoneField.setHintText(hint != null ? hint.replace('X', '') : null);
countryState = 0;
}
}
private void updatePhoneField() {
ignoreOnPhoneChange = true;
try {
String codeText = codeField.getText().toString();
String phone = PhoneFormat.getInstance().format("+" + codeText + phoneField.getText().toString());
int idx = phone.indexOf(" ");
if (idx != -1) {
String resultCode = PhoneFormat.stripExceptNumbers(phone.substring(0, idx));
if (!codeText.equals(resultCode)) {
phone = PhoneFormat.getInstance().format(phoneField.getText().toString()).trim();
phoneField.setText(phone);
int len = phoneField.length();
phoneField.setSelection(phoneField.length());
} else {
phoneField.setText(phone.substring(idx).trim());
int len = phoneField.length();
phoneField.setSelection(phoneField.length());
}
} else {
phoneField.setSelection(phoneField.length());
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
ignoreOnPhoneChange = false;
}
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if (ignoreSelection) {
@ -612,7 +617,6 @@ public class ChangePhoneActivity extends BaseFragment {
ignoreOnTextChange = true;
String str = countriesArray.get(i);
codeField.setText(countriesMap.get(str));
updatePhoneField();
}
@Override
@ -686,8 +690,14 @@ public class ChangePhoneActivity extends BaseFragment {
public void onShow() {
super.onShow();
if (phoneField != null) {
AndroidUtilities.showKeyboard(phoneField);
phoneField.setSelection(phoneField.length());
if (codeField.length() != 0) {
AndroidUtilities.showKeyboard(phoneField);
phoneField.requestFocus();
phoneField.setSelection(phoneField.length());
} else {
AndroidUtilities.showKeyboard(codeField);
codeField.requestFocus();
}
}
}
@ -713,6 +723,7 @@ public class ChangePhoneActivity extends BaseFragment {
private volatile int codeTime = 15000;
private double lastCurrentTime;
private double lastCodeTime;
private boolean ignoreOnTextChange;
private boolean waitingForSms = false;
private boolean nextPressed = false;
private String lastError = "";
@ -755,6 +766,27 @@ public class ChangePhoneActivity extends BaseFragment {
layoutParams.leftMargin = AndroidUtilities.dp(24);
layoutParams.rightMargin = AndroidUtilities.dp(24);
codeField.setLayoutParams(layoutParams);
codeField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (ignoreOnTextChange) {
return;
}
if (codeField.length() == 5) {
onNextPressed();
}
}
});
codeField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
@ -1051,6 +1083,7 @@ public class ChangePhoneActivity extends BaseFragment {
return;
}
if (codeField != null) {
ignoreOnTextChange = true;
codeField.setText("" + args[0]);
onNextPressed();
}

View File

@ -307,7 +307,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
result.add(user);
}
}
MessagesController.getInstance().addUsersToChannel(chatId, result);
MessagesController.getInstance().addUsersToChannel(chatId, result, null);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
Bundle args2 = new Bundle();
args2.putInt("chat_id", chatId);
@ -655,7 +655,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
actionBar.setTitle(LocaleController.getString("ChannelAddMembers", R.string.ChannelAddMembers));
actionBar.setSubtitle(LocaleController.formatPluralString("Members", selectedContacts.size()));
searchListViewAdapter = new SearchAdapter(context, null, false, false, false);
searchListViewAdapter = new SearchAdapter(context, null, false, false, false, false);
searchListViewAdapter.setCheckedMap(selectedContacts);
searchListViewAdapter.setUseUserCell(true);
listViewAdapter = new ContactsAdapter(context, 1, false, null, false);

View File

@ -118,7 +118,7 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
return false;
}
if (info == null) {
MessagesStorage.getInstance().loadChatInfo(chatId, semaphore, false);
MessagesStorage.getInstance().loadChatInfo(chatId, semaphore, false, false);
try {
semaphore.acquire();
} catch (Exception e) {
@ -132,7 +132,7 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
wasPrivate = currentChat.username == null || currentChat.username.length() == 0;
avatarUpdater.parentFragment = this;
avatarUpdater.delegate = this;
allowComments = (currentChat.flags & TLRPC.CHAT_FLAG_IS_BROADCAST) == 0;
allowComments = !currentChat.broadcast;
return super.onFragmentCreate();
}
@ -178,14 +178,16 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
AndroidUtilities.shakeView(nameTextView, 2, 0);
return;
}
if ((currentChat.username == null && userNameTextView.length() != 0) || (currentChat.username != null && !currentChat.username.equalsIgnoreCase(userNameTextView.getText().toString()))) {
if (userNameTextView.length() != 0 && !lastNameAvailable) {
Vibrator v = (Vibrator) getParentActivity().getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
v.vibrate(200);
if (userNameTextView != null) {
if ((currentChat.username == null && userNameTextView.length() != 0) || (currentChat.username != null && !currentChat.username.equalsIgnoreCase(userNameTextView.getText().toString()))) {
if (userNameTextView.length() != 0 && !lastNameAvailable) {
Vibrator v = (Vibrator) getParentActivity().getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
v.vibrate(200);
}
AndroidUtilities.shakeView(checkTextView, 2, 0);
return;
}
AndroidUtilities.shakeView(checkTextView, 2, 0);
return;
}
}
@ -211,7 +213,7 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
progressDialog.show();
return;
}
boolean currentAllowComments = (currentChat.flags & TLRPC.CHAT_FLAG_IS_BROADCAST) == 0;
boolean currentAllowComments = !currentChat.broadcast;
if (allowComments != currentAllowComments) {
MessagesController.getInstance().toogleChannelComments(chatId, allowComments);
}
@ -221,9 +223,11 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
if (info != null && !info.about.equals(descriptionTextView.getText().toString())) {
MessagesController.getInstance().updateChannelAbout(chatId, descriptionTextView.getText().toString(), info);
}
String oldUserName = currentChat.username != null ? currentChat.username : "";
if (!oldUserName.equals(userNameTextView.getText().toString())) {
MessagesController.getInstance().updateChannelUserName(chatId, userNameTextView.getText().toString());
if (userNameTextView != null) {
String oldUserName = currentChat.username != null ? currentChat.username : "";
if (!oldUserName.equals(userNameTextView.getText().toString())) {
MessagesController.getInstance().updateChannelUserName(chatId, userNameTextView.getText().toString());
}
}
if (uploadedAvatar != null) {
MessagesController.getInstance().changeChatAvatar(chatId, uploadedAvatar);
@ -299,7 +303,11 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
});
nameTextView = new EditText(context);
nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName));
if (currentChat.megagroup) {
nameTextView.setHint(LocaleController.getString("GroupName", R.string.GroupName));
} else {
nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName));
}
nameTextView.setMaxLines(4);
nameTextView.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT));
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
@ -382,90 +390,95 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
});
TextInfoPrivacyCell infoCell = new TextInfoPrivacyCell(context);
infoCell.setText(LocaleController.getString("DescriptionInfo", R.string.DescriptionInfo));
if (currentChat.megagroup) {
infoCell.setText(LocaleController.getString("DescriptionInfoMega", R.string.DescriptionInfoMega));
} else {
infoCell.setText(LocaleController.getString("DescriptionInfo", R.string.DescriptionInfo));
}
infoCell.setBackgroundResource(R.drawable.greydivider);
linearLayout.addView(infoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
if (!currentChat.megagroup) {
linearLayout2 = new LinearLayout(context);
linearLayout2.setOrientation(LinearLayout.VERTICAL);
linearLayout2.setBackgroundColor(0xffffffff);
linearLayout2.setPadding(0, 0, 0, AndroidUtilities.dp(7));
linearLayout.addView(linearLayout2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
linearLayout2 = new LinearLayout(context);
linearLayout2.setOrientation(LinearLayout.VERTICAL);
linearLayout2.setBackgroundColor(0xffffffff);
linearLayout2.setPadding(0, 0, 0, AndroidUtilities.dp(7));
linearLayout.addView(linearLayout2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
LinearLayout publicContainer = new LinearLayout(context);
publicContainer.setOrientation(LinearLayout.HORIZONTAL);
linearLayout2.addView(publicContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 17, 7, 17, 0));
LinearLayout publicContainer = new LinearLayout(context);
publicContainer.setOrientation(LinearLayout.HORIZONTAL);
linearLayout2.addView(publicContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 17, 7, 17, 0));
EditText editText = new EditText(context);
editText.setText("telegram.me/");
editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
editText.setHintTextColor(0xff979797);
editText.setTextColor(0xff212121);
editText.setMaxLines(1);
editText.setLines(1);
editText.setEnabled(false);
editText.setBackgroundDrawable(null);
editText.setPadding(0, 0, 0, 0);
editText.setSingleLine(true);
editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
publicContainer.addView(editText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36));
EditText editText = new EditText(context);
editText.setText("telegram.me/");
editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
editText.setHintTextColor(0xff979797);
editText.setTextColor(0xff212121);
editText.setMaxLines(1);
editText.setLines(1);
editText.setEnabled(false);
editText.setBackgroundDrawable(null);
editText.setPadding(0, 0, 0, 0);
editText.setSingleLine(true);
editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
publicContainer.addView(editText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36));
userNameTextView = new EditText(context);
userNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
userNameTextView.setHintTextColor(0xff979797);
userNameTextView.setTextColor(0xff212121);
userNameTextView.setMaxLines(1);
userNameTextView.setLines(1);
userNameTextView.setBackgroundDrawable(null);
userNameTextView.setPadding(0, 0, 0, 0);
userNameTextView.setSingleLine(true);
userNameTextView.setText(currentChat.username);
userNameTextView.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
userNameTextView.setImeOptions(EditorInfo.IME_ACTION_DONE);
userNameTextView.setHint(LocaleController.getString("ChannelUsernamePlaceholder", R.string.ChannelUsernamePlaceholder));
userNameTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (wasPrivate && hasFocus && !privateAlertShown) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setMessage(LocaleController.getString("ChannelWasPrivateAlert", R.string.ChannelWasPrivateAlert));
builder.setPositiveButton(LocaleController.getString("Close", R.string.Close), null);
showDialog(builder.create());
userNameTextView = new EditText(context);
userNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
userNameTextView.setHintTextColor(0xff979797);
userNameTextView.setTextColor(0xff212121);
userNameTextView.setMaxLines(1);
userNameTextView.setLines(1);
userNameTextView.setBackgroundDrawable(null);
userNameTextView.setPadding(0, 0, 0, 0);
userNameTextView.setSingleLine(true);
userNameTextView.setText(currentChat.username);
userNameTextView.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
userNameTextView.setImeOptions(EditorInfo.IME_ACTION_DONE);
userNameTextView.setHint(LocaleController.getString("ChannelUsernamePlaceholder", R.string.ChannelUsernamePlaceholder));
userNameTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (wasPrivate && hasFocus && !privateAlertShown) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setMessage(LocaleController.getString("ChannelWasPrivateAlert", R.string.ChannelWasPrivateAlert));
builder.setPositiveButton(LocaleController.getString("Close", R.string.Close), null);
showDialog(builder.create());
}
}
}
});
AndroidUtilities.clearCursorDrawable(userNameTextView);
publicContainer.addView(userNameTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36));
userNameTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
});
AndroidUtilities.clearCursorDrawable(userNameTextView);
publicContainer.addView(userNameTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36));
userNameTextView.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(userNameTextView.getText().toString(), false);
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
checkUserName(userNameTextView.getText().toString(), false);
}
@Override
public void afterTextChanged(Editable editable) {
@Override
public void afterTextChanged(Editable editable) {
}
});
}
});
checkTextView = new TextView(context);
checkTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
checkTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
checkTextView.setVisibility(View.GONE);
linearLayout2.addView(checkTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 17, 3, 17, 7));
checkTextView = new TextView(context);
checkTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
checkTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
checkTextView.setVisibility(View.GONE);
linearLayout2.addView(checkTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 17, 3, 17, 7));
infoCell = new TextInfoPrivacyCell(context);
infoCell.setBackgroundResource(R.drawable.greydivider);
infoCell.setText(LocaleController.getString("ChannelUsernameHelp", R.string.ChannelUsernameHelp));
linearLayout.addView(infoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
infoCell = new TextInfoPrivacyCell(context);
infoCell.setBackgroundResource(R.drawable.greydivider);
infoCell.setText(LocaleController.getString("ChannelUsernameHelp", R.string.ChannelUsernameHelp));
linearLayout.addView(infoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
/*frameLayout = new FrameLayoutFixed(context);
@ -496,13 +509,21 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
TextSettingsCell textCell = new TextSettingsCell(context);
textCell.setTextColor(0xffed3d39);
textCell.setBackgroundResource(R.drawable.list_selector);
textCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false);
if (currentChat.megagroup) {
textCell.setText(LocaleController.getString("DeleteMega", R.string.DeleteMega), false);
} else {
textCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false);
}
frameLayout.addView(textCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
textCell.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setMessage(LocaleController.getString("ChannelDeleteAlert", R.string.ChannelDeleteAlert));
if (currentChat.megagroup) {
builder.setMessage(LocaleController.getString("MegaDeleteAlert", R.string.MegaDeleteAlert));
} else {
builder.setMessage(LocaleController.getString("ChannelDeleteAlert", R.string.ChannelDeleteAlert));
}
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() {
@Override
@ -524,7 +545,11 @@ public class ChannelEditActivity extends BaseFragment implements AvatarUpdater.A
infoCell = new TextInfoPrivacyCell(context);
infoCell.setBackgroundResource(R.drawable.greydivider_bottom);
infoCell.setText(LocaleController.getString("ChannelDeleteInfo", R.string.ChannelDeleteInfo));
if (currentChat.megagroup) {
infoCell.setText(LocaleController.getString("MegaDeleteInfo", R.string.MegaDeleteInfo));
} else {
infoCell.setText(LocaleController.getString("ChannelDeleteInfo", R.string.ChannelDeleteInfo));
}
linearLayout.addView(infoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
nameTextView.setText(currentChat.title);

View File

@ -57,8 +57,10 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
private int chatId;
private int type;
private boolean loadingUsers;
private boolean firstLoaded;
private boolean isAdmin;
private boolean isPublic;
private boolean isMegagroup;
private int participantsStartRow;
public ChannelUsersActivity(Bundle args) {
@ -66,9 +68,12 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
chatId = arguments.getInt("chat_id");
type = arguments.getInt("type");
TLRPC.Chat chat = MessagesController.getInstance().getChat(chatId);
if (chat != null && (chat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0) {
isAdmin = true;
isPublic = (chat.flags & TLRPC.CHAT_FLAG_IS_PUBLIC) != 0;
if (chat != null) {
if (chat.creator) {
isAdmin = true;
isPublic = (chat.flags & TLRPC.CHAT_FLAG_IS_PUBLIC) != 0;
}
isMegagroup = chat.megagroup;
}
if (type == 0) {
participantsStartRow = 0;
@ -121,7 +126,11 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
emptyView = new EmptyTextProgressView(context);
if (type == 0) {
emptyView.setText(LocaleController.getString("NoBlocked", R.string.NoBlocked));
if (isMegagroup) {
emptyView.setText(LocaleController.getString("NoBlockedGroup", R.string.NoBlockedGroup));
} else {
emptyView.setText(LocaleController.getString("NoBlocked", R.string.NoBlocked));
}
}
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
@ -171,6 +180,9 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
args.putBoolean("returnAsResult", true);
args.putBoolean("needForwardCount", false);
args.putBoolean("allowUsernameSearch", true);
if (isMegagroup) {
args.putBoolean("allowBots", false);
}
args.putString("selectAlertString", LocaleController.getString("ChannelAddUserAdminAlert", R.string.ChannelAddUserAdminAlert));
ContactsActivity fragment = new ContactsActivity(args);
fragment.setDelegate(new ContactsActivity.ContactsActivityDelegate() {
@ -195,7 +207,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
}
});
if (isAdmin) {
if (isAdmin || isMegagroup && type == 0) {
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
@ -280,18 +292,19 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override
public void run(TLObject response, final TLRPC.TL_error error) {
if (response instanceof TLRPC.TL_boolTrue) {
if (error == null) {
MessagesController.getInstance().processUpdates((TLRPC.Updates) response, false);
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.getInstance().loadFullChat(chatId, 0, true);
}
}, 1000);
} else if (error != null) {
} else {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
AlertsCreator.showAddUserAlert(error.text, ChannelUsersActivity.this);
AlertsCreator.showAddUserAlert(error.text, ChannelUsersActivity.this, !isMegagroup);
}
});
}
@ -329,7 +342,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
return;
}
loadingUsers = true;
if (emptyView != null) {
if (emptyView != null && !firstLoaded) {
emptyView.showProgress();
}
if (listViewAdapter != null) {
@ -421,6 +434,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
}
}
loadingUsers = false;
firstLoaded = true;
if (emptyView != null) {
emptyView.showTextView();
}
@ -486,7 +500,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
@Override
public int getCount() {
if (participants.isEmpty() && type == 0 || loadingUsers) {
if (participants.isEmpty() && type == 0 || loadingUsers && !firstLoaded) {
return 0;
}
return participants.size() + participantsStartRow + 1;
@ -512,7 +526,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
int viewType = getItemViewType(i);
if (viewType == 0) {
if (view == null) {
view = new UserCell(mContext, 1);
view = new UserCell(mContext, 1, 0);
view.setBackgroundColor(0xffffffff);
}
UserCell userCell = (UserCell) view;
@ -540,19 +554,27 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe
view = new TextInfoPrivacyCell(mContext);
}
if (type == 0) {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("UnblockText", R.string.UnblockText));
((TextInfoPrivacyCell) view).setText(String.format("%1$s\n\n%2$s", LocaleController.getString("NoBlockedGroup", R.string.NoBlockedGroup), LocaleController.getString("UnblockText", R.string.UnblockText)));
view.setBackgroundResource(R.drawable.greydivider_bottom);
} else if (type == 1) {
if (i == 1 && isAdmin) {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("ChannelAdminsInfo", R.string.ChannelAdminsInfo));
if (isMegagroup) {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("MegaAdminsInfo", R.string.MegaAdminsInfo));
} else {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("ChannelAdminsInfo", R.string.ChannelAdminsInfo));
}
view.setBackgroundResource(R.drawable.greydivider);
} else {
((TextInfoPrivacyCell) view).setText("");
view.setBackgroundResource(R.drawable.greydivider_bottom);
}
} else if (type == 2) {
if ((!isPublic && i == 2 || i == 1) &&isAdmin) {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("ChannelMembersInfo", R.string.ChannelMembersInfo));
if ((!isPublic && i == 2 || i == 1) && isAdmin) {
if (isMegagroup) {
((TextInfoPrivacyCell) view).setText("");
} else {
((TextInfoPrivacyCell) view).setText(LocaleController.getString("ChannelMembersInfo", R.string.ChannelMembersInfo));
}
view.setBackgroundResource(R.drawable.greydivider);
} else {
((TextInfoPrivacyCell) view).setText("");

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,7 @@ public class AlertsCreator {
editor.putInt("notifyuntil_" + dialog_id, untilTime);
flags = ((long) untilTime << 32) | 1;
}
NotificationsController.getInstance().removeNotificationsForDialog(dialog_id);
MessagesStorage.getInstance().setDialogFlags(dialog_id, flags);
editor.commit();
TLRPC.Dialog dialog = MessagesController.getInstance().dialogs_dict.get(dialog_id);
@ -84,7 +85,7 @@ public class AlertsCreator {
return builder.create();
}
public static void showAddUserAlert(String error, final BaseFragment fragment) {
public static void showAddUserAlert(String error, final BaseFragment fragment, boolean isChannel) {
if (error == null || fragment == null || fragment.getParentActivity() == null) {
return;
}
@ -109,16 +110,39 @@ public class AlertsCreator {
case "USER_BLOCKED":
case "USER_BOT":
case "USER_ID_INVALID":
builder.setMessage(LocaleController.getString("ChannelUserCantAdd", R.string.ChannelUserCantAdd));
if (isChannel) {
builder.setMessage(LocaleController.getString("ChannelUserCantAdd", R.string.ChannelUserCantAdd));
} else {
builder.setMessage(LocaleController.getString("GroupUserCantAdd", R.string.GroupUserCantAdd));
}
break;
case "USERS_TOO_MUCH":
builder.setMessage(LocaleController.getString("ChannelUserAddLimit", R.string.ChannelUserAddLimit));
if (isChannel) {
builder.setMessage(LocaleController.getString("ChannelUserAddLimit", R.string.ChannelUserAddLimit));
} else {
builder.setMessage(LocaleController.getString("GroupUserAddLimit", R.string.GroupUserAddLimit));
}
break;
case "USER_NOT_MUTUAL_CONTACT":
builder.setMessage(LocaleController.getString("ChannelUserLeftError", R.string.ChannelUserLeftError));
if (isChannel) {
builder.setMessage(LocaleController.getString("ChannelUserLeftError", R.string.ChannelUserLeftError));
} else {
builder.setMessage(LocaleController.getString("GroupUserLeftError", R.string.GroupUserLeftError));
}
break;
case "ADMINS_TOO_MUCH":
builder.setMessage(LocaleController.getString("ChannelUserCantAdmin", R.string.ChannelUserCantAdmin));
if (isChannel) {
builder.setMessage(LocaleController.getString("ChannelUserCantAdmin", R.string.ChannelUserCantAdmin));
} else {
builder.setMessage(LocaleController.getString("GroupUserCantAdmin", R.string.GroupUserCantAdmin));
}
break;
case "BOTS_TOO_MUCH":
if (isChannel) {
builder.setMessage(LocaleController.getString("ChannelUserCantBot", R.string.ChannelUserCantBot));
} else {
builder.setMessage(LocaleController.getString("GroupUserCantBot", R.string.GroupUserCantBot));
}
break;
}
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);

View File

@ -30,7 +30,7 @@ public class AvatarDrawable extends Drawable {
private static Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private static TextPaint namePaint;
private static TextPaint namePaintSmall;
private static int[] arrColors = {0xffe56555, 0xfff28c48, 0xff549cdd, 0xff76c84d, 0xff5fbed5, 0xff549cdd, 0xff8e85ee, 0xfff2749a};
private static int[] arrColors = {0xffe56555, 0xfff28c48, 0xff8e85ee, 0xff76c84d, 0xff5fbed5, 0xff549cdd, 0xff8e85ee, 0xfff2749a};
private static int[] arrColorsProfiles = {0xffd86f65, 0xfff69d61, 0xff8c79d2, 0xff67b35d, 0xff56a2bb, 0xff5c98cd, 0xff8c79d2, 0xfff37fa6};
private static int[] arrColorsProfilesBack = {0xffca6056, 0xfff18944, 0xff7d6ac4, 0xff56a14c, 0xff4492ac, 0xff4c84b6, 0xff7d6ac4, 0xff4c84b6};
private static int[] arrColorsProfilesText = {0xfff9cbc5, 0xfffdddc8, 0xffcdc4ed, 0xffc0edba, 0xffb8e2f0, 0xffb3d7f7, 0xffcdc4ed, 0xffb3d7f7};
@ -92,6 +92,10 @@ public class AvatarDrawable extends Drawable {
}
}
public void setProfile(boolean value) {
isProfile = value;
}
public void setSmallStyle(boolean value) {
smallStyle = value;
}

View File

@ -88,7 +88,7 @@ public class BotKeyboardView extends LinearLayout {
buttonViews.clear();
if (buttons != null && botButtons.rows.size() != 0) {
isFullSize = (buttons.flags & 1) == 0;
isFullSize = !buttons.resize;
buttonHeight = !isFullSize ? 42 : (int) Math.max(42, (panelHeight - AndroidUtilities.dp(30) - (botButtons.rows.size() - 1) * AndroidUtilities.dp(10)) / botButtons.rows.size() / AndroidUtilities.density);
for (int a = 0; a < buttons.rows.size(); a++) {
TLRPC.TL_keyboardButtonRow row = buttons.rows.get(a);

View File

@ -690,7 +690,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
return isAsAdmin;
}
public void showTopView(boolean animated) {
public void showTopView(boolean animated, final boolean openKeyboard) {
if (topView == null || topViewShowed || getVisibility() != VISIBLE) {
return;
}
@ -713,7 +713,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
public void onAnimationEnd(Object animation) {
if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) {
setTopViewAnimation(1.0f);
if (!forceShowSendButton) {
if (!forceShowSendButton || openKeyboard) {
openKeyboard();
}
currentTopViewAnimation = null;
@ -724,7 +724,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
currentTopViewAnimation.start();
} else {
setTopViewAnimation(1.0f);
if (!forceShowSendButton) {
if (!forceShowSendButton || openKeyboard) {
openKeyboard();
}
}
@ -829,6 +829,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
public void onPause() {
isPaused = true;
closeKeyboard();
}
public void onResume() {
@ -849,8 +850,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
dialog_id = id;
if ((int) dialog_id < 0) {
TLRPC.Chat currentChat = MessagesController.getInstance().getChat(-(int) dialog_id);
isAsAdmin = ChatObject.isChannel(currentChat) && ((currentChat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0 || (currentChat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) != 0);
adminModeAvailable = isAsAdmin && (currentChat.flags & TLRPC.CHAT_FLAG_IS_BROADCAST) == 0;
isAsAdmin = ChatObject.isChannel(currentChat) && (currentChat.creator || currentChat.editor) && !currentChat.megagroup;
adminModeAvailable = isAsAdmin && !currentChat.broadcast;
if (adminModeAvailable) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
isAsAdmin = preferences.getBoolean("asadmin_" + dialog_id, true);
@ -865,8 +866,9 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
private void updateFieldHint() {
boolean isChannel = false;
if ((int) dialog_id < 0 && ChatObject.isChannel(MessagesController.getInstance().getChat(-(int) dialog_id))) {
isChannel = true;
if ((int) dialog_id < 0) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(-(int) dialog_id);
isChannel = ChatObject.isChannel(chat) && !chat.megagroup;
}
if (isChannel) {
messageEditText.setHint(isAsAdmin ? LocaleController.getString("ChannelBroadcast", R.string.ChannelBroadcast) : LocaleController.getString("ChannelComment", R.string.ChannelComment));
@ -946,9 +948,9 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
}
private String getTrimmedString(String src) {
String result = src.trim();
if (result.length() == 0) {
return result;
src = src.trim();
if (src.length() == 0) {
return src;
}
while (src.startsWith("\n")) {
src = src.substring(1);
@ -1240,13 +1242,18 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
this.delegate = delegate;
}
public void setCommand(MessageObject messageObject, String command, boolean longPress) {
public void setCommand(MessageObject messageObject, String command, boolean longPress, boolean username) {
if (command == null || getVisibility() != VISIBLE) {
return;
}
if (longPress) {
String text = messageEditText.getText().toString();
text = command + " " + text.replaceFirst("^/[a-zA-Z@\\d_]{1,255}(\\s|$)", "");
TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? MessagesController.getInstance().getUser(messageObject.messageOwner.from_id) : null;
if ((botCount != 1 || username) && user != null && user.bot && !command.contains("@")) {
text = String.format(Locale.US, "%s@%s", command, user.username) + " " + text.replaceFirst("^/[a-zA-Z@\\d_]{1,255}(\\s|$)", "");
} else {
text = command + " " + text.replaceFirst("^/[a-zA-Z@\\d_]{1,255}(\\s|$)", "");
}
ignoreTextChange = true;
messageEditText.setText(text);
messageEditText.setSelection(messageEditText.getText().length());
@ -1256,7 +1263,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
}
} else {
TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? MessagesController.getInstance().getUser(messageObject.messageOwner.from_id) : null;
if (botCount != 1 && user != null && (user.flags & TLRPC.USER_FLAG_BOT) != 0 && !command.contains("@")) {
if ((botCount != 1 || username) && user != null && user.bot && !command.contains("@")) {
SendMessagesHelper.getInstance().sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, null, null, false, asAdmin());
} else {
SendMessagesHelper.getInstance().sendMessage(command, dialog_id, null, null, false, asAdmin());
@ -1406,7 +1413,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
if (replyingMessageObject != null) {
openKeyboardInternal();
setButtons(botMessageObject, false);
} else if ((botButtonsMessageObject.messageOwner.reply_markup.flags & 2) != 0) {
} else if (botButtonsMessageObject.messageOwner.reply_markup.single_use) {
openKeyboardInternal();
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
preferences.edit().putInt("answered_" + dialog_id, botButtonsMessageObject.getId()).commit();
@ -1426,7 +1433,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
if (botReplyMarkup != null) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
boolean keyboardHidden = preferences.getInt("hidekeyboard_" + dialog_id, 0) == messageObject.getId();
if (botButtonsMessageObject != replyingMessageObject && (botReplyMarkup.flags & 2) != 0) {
if (botButtonsMessageObject != replyingMessageObject && botReplyMarkup.single_use) {
if (preferences.getInt("answered_" + dialog_id, 0) == messageObject.getId()) {
return;
}
@ -1594,6 +1601,10 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
AndroidUtilities.showKeyboard(messageEditText);
}
public void closeKeyboard() {
AndroidUtilities.hideKeyboard(messageEditText);
}
public boolean isPopupShowing() {
return emojiView != null && emojiView.getVisibility() == VISIBLE || botKeyboardView != null && botKeyboardView.getVisibility() == VISIBLE;
}

View File

@ -0,0 +1,222 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy;
public class CheckBoxSquare extends View {
private static Paint eraser;
private static Paint checkPaint;
private static Paint backgroundPaint;
private static RectF rectF;
private Bitmap drawBitmap;
private Canvas drawCanvas;
private float progress;
private ObjectAnimatorProxy checkAnimator;
private boolean isCheckAnimation = true;
private boolean attachedToWindow;
private boolean isChecked;
private boolean isDisabled;
private int color = 0xff43a0df;
private final static float progressBounceDiff = 0.2f;
public CheckBoxSquare(Context context) {
super(context);
if (checkPaint == null) {
checkPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
checkPaint.setColor(0xffffffff);
checkPaint.setStyle(Paint.Style.STROKE);
checkPaint.setStrokeWidth(AndroidUtilities.dp(2));
eraser = new Paint(Paint.ANTI_ALIAS_FLAG);
eraser.setColor(0);
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectF = new RectF();
}
drawBitmap = Bitmap.createBitmap(AndroidUtilities.dp(18), AndroidUtilities.dp(18), Bitmap.Config.ARGB_4444);
drawCanvas = new Canvas(drawBitmap);
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
if (visibility == VISIBLE && drawBitmap == null) {
}
}
public void setProgress(float value) {
if (progress == value) {
return;
}
progress = value;
invalidate();
}
public float getProgress() {
return progress;
}
public void setColor(int value) {
color = value;
}
private void cancelCheckAnimator() {
if (checkAnimator != null) {
checkAnimator.cancel();
}
}
private void animateToCheckedState(boolean newCheckedState) {
isCheckAnimation = newCheckedState;
checkAnimator = ObjectAnimatorProxy.ofFloatProxy(this, "progress", newCheckedState ? 1 : 0);
checkAnimator.setDuration(300);
checkAnimator.start();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
attachedToWindow = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
attachedToWindow = false;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
public void setChecked(boolean checked, boolean animated) {
if (checked == isChecked) {
return;
}
isChecked = checked;
if (attachedToWindow && animated) {
animateToCheckedState(checked);
} else {
cancelCheckAnimator();
setProgress(checked ? 1.0f : 0.0f);
}
}
public void setDisabled(boolean disabled) {
isDisabled = disabled;
invalidate();
}
public boolean isChecked() {
return isChecked;
}
@Override
protected void onDraw(Canvas canvas) {
if (getVisibility() != VISIBLE) {
return;
}
float checkProgress;
float bounceProgress;
if (progress <= 0.5f) {
bounceProgress = checkProgress = progress / 0.5f;
int rD = (int) ((Color.red(color) - 0x73) * checkProgress);
int gD = (int) ((Color.green(color) - 0x73) * checkProgress);
int bD = (int) ((Color.blue(color) - 0x73) * checkProgress);
int c = Color.rgb(0x73 + rD, 0x73 + gD, 0x73 + bD);
backgroundPaint.setColor(c);
} else {
bounceProgress = 2.0f - progress / 0.5f;
checkProgress = 1.0f;
backgroundPaint.setColor(color);
}
if (isDisabled) {
backgroundPaint.setColor(0xffb0b0b0);
}
float bounce = AndroidUtilities.dp(1) * bounceProgress;
rectF.set(bounce, bounce, AndroidUtilities.dp(18) - bounce, AndroidUtilities.dp(18) - bounce);
drawBitmap.eraseColor(0);
drawCanvas.drawRoundRect(rectF, AndroidUtilities.dp(2), AndroidUtilities.dp(2), backgroundPaint);
if (checkProgress != 1) {
float rad = Math.min(AndroidUtilities.dp(7), AndroidUtilities.dp(7) * checkProgress + bounce);
rectF.set(AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(2) + rad, AndroidUtilities.dp(16) - rad, AndroidUtilities.dp(16) - rad);
drawCanvas.drawRect(rectF, eraser);
}
if (progress > 0.5f) {
int endX = (int) (AndroidUtilities.dp(7.5f) - AndroidUtilities.dp(5) * (1.0f - bounceProgress)); //dp 2.5f
int endY = (int) (AndroidUtilities.dpf2(13.5f) - AndroidUtilities.dp(5) * (1.0f - bounceProgress)); //dpf2 8.5f
drawCanvas.drawLine(AndroidUtilities.dp(7.5f), (int) AndroidUtilities.dpf2(13.5f), endX, endY, checkPaint);
endX = (int) (AndroidUtilities.dpf2(6.5f) + AndroidUtilities.dp(9) * (1.0f - bounceProgress)); //dpf2 15.5f
endY = (int) (AndroidUtilities.dpf2(13.5f) - AndroidUtilities.dp(9) * (1.0f - bounceProgress)); //dpf2 4.5f
drawCanvas.drawLine((int) AndroidUtilities.dpf2(6.5f), (int) AndroidUtilities.dpf2(13.5f), endX, endY, checkPaint);
}
canvas.drawBitmap(drawBitmap, 0, 0, null);
/*eraser2.setStrokeWidth(AndroidUtilities.dp(size + 6));
drawBitmap.eraseColor(0);
float rad = getMeasuredWidth() / 2;
float roundProgress = progress >= 0.5f ? 1.0f : progress / 0.5f;
float checkProgress = progress < 0.5f ? 0.0f : (progress - 0.5f) / 0.5f;
float roundProgressCheckState = isCheckAnimation ? progress : (1.0f - progress);
if (roundProgressCheckState < progressBounceDiff) {
rad -= AndroidUtilities.dp(2) * roundProgressCheckState / progressBounceDiff;
} else if (roundProgressCheckState < progressBounceDiff * 2) {
rad -= AndroidUtilities.dp(2) - AndroidUtilities.dp(2) * (roundProgressCheckState - progressBounceDiff) / progressBounceDiff;
}
if (drawBackground) {
paint.setColor(0x44000000);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad - AndroidUtilities.dp(1), paint);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad - AndroidUtilities.dp(1), backgroundPaint);
}
paint.setColor(color);
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad, paint);
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad * (1 - roundProgress), eraser);
canvas.drawBitmap(drawBitmap, 0, 0, null);
checkBitmap.eraseColor(0);
int w = checkDrawable.getIntrinsicWidth();
int h = checkDrawable.getIntrinsicHeight();
int x = (getMeasuredWidth() - w) / 2;
int y = (getMeasuredHeight() - h) / 2;
checkDrawable.setBounds(x, y + checkOffset, x + w, y + h + checkOffset);
checkDrawable.draw(checkCanvas);
checkCanvas.drawCircle(getMeasuredWidth() / 2 - AndroidUtilities.dp(2.5f), getMeasuredHeight() / 2 + AndroidUtilities.dp(4), ((getMeasuredWidth() + AndroidUtilities.dp(6)) / 2) * (1 - checkProgress), eraser2);
canvas.drawBitmap(checkBitmap, 0, 0, null);*/
}
}

View File

@ -1166,7 +1166,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
ArrayList<TLRPC.TL_messages_stickerSet> packs = StickersQuery.getStickerSets();
for (int a = 0; a < packs.size(); a++) {
TLRPC.TL_messages_stickerSet pack = packs.get(a);
if ((pack.set.flags & 2) != 0 || pack.documents == null || pack.documents.isEmpty()) {
if (pack.set.disabled || pack.documents == null || pack.documents.isEmpty()) {
continue;
}
stickerSets.add(pack);

View File

@ -151,7 +151,11 @@ public class FrameLayoutFixed extends FrameLayout {
}
} catch (Exception e) {
FileLog.e("tmessages", e);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
try {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} catch (Exception e2) {
FileLog.e("tmessages", e2);
}
}
}
}

View File

@ -0,0 +1,73 @@
/*
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.widget.EditText;
import org.telegram.messenger.AndroidUtilities;
public class HintEditText extends EditText {
private String hintText;
private float textOffset;
private float spaceSize;
private float numberSize;
private Paint paint = new Paint();
private Rect rect = new Rect();
public HintEditText(Context context) {
super(context);
paint.setColor(0xff979797);
}
public String getHintText() {
return hintText;
}
public void setHintText(String value) {
hintText = value;
onTextChange();
setText(getText());
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
onTextChange();
}
public void onTextChange() {
textOffset = (length() > 0 ? getPaint().measureText(getText(), 0, length()) : 0);
spaceSize = getPaint().measureText(" ");
numberSize = getPaint().measureText("1");
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (hintText != null && length() < hintText.length()) {
int top = getMeasuredHeight() / 2;
float offsetX = textOffset;
for (int a = length(); a < hintText.length(); a++) {
if (hintText.charAt(a) == ' ') {
offsetX += spaceSize;
} else {
rect.set((int) offsetX + AndroidUtilities.dp(1), top, (int) (offsetX + numberSize) - AndroidUtilities.dp(1), top + AndroidUtilities.dp(2));
canvas.drawRect(rect, paint);
offsetX += numberSize;
}
}
}
}
}

View File

@ -11,6 +11,7 @@ package org.telegram.ui.Components;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import org.telegram.messenger.AndroidUtilities;
@ -23,6 +24,10 @@ public class LayoutHelper {
return (int) (size < 0 ? size : AndroidUtilities.dp(size));
}
public static FrameLayout.LayoutParams createScroll(int width, int height, int gravity) {
return new ScrollView.LayoutParams(getSize(width), getSize(height), gravity);
}
public static FrameLayout.LayoutParams createFrame(int width, float height, int gravity, float leftMargin, float topMargin, float rightMargin, float bottomMargin) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity);
layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin));
@ -100,7 +105,7 @@ public class LayoutHelper {
return layoutParams;
}
public static LinearLayout.LayoutParams createLinear(int width, int height, int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
public static LinearLayout.LayoutParams createLinear(int width, int height, float leftMargin, float topMargin, float rightMargin, float bottomMargin) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(getSize(width), getSize(height));
layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin));
return layoutParams;

View File

@ -47,23 +47,13 @@ public class PickerBottomLayout extends FrameLayout {
cancelButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0);
cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
cancelButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
addView(cancelButton);
LayoutParams layoutParams = (LayoutParams) cancelButton.getLayoutParams();
layoutParams.width = LayoutHelper.WRAP_CONTENT;
layoutParams.height = LayoutHelper.MATCH_PARENT;
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
cancelButton.setLayoutParams(layoutParams);
addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
doneButton = new LinearLayout(context);
doneButton.setOrientation(LinearLayout.HORIZONTAL);
doneButton.setBackgroundResource(isDarkTheme ? R.drawable.bar_selector_picker : R.drawable.bar_selector_audio);
doneButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0);
addView(doneButton);
layoutParams = (LayoutParams) doneButton.getLayoutParams();
layoutParams.width = LayoutHelper.WRAP_CONTENT;
layoutParams.height = LayoutHelper.MATCH_PARENT;
layoutParams.gravity = Gravity.TOP | Gravity.RIGHT;
doneButton.setLayoutParams(layoutParams);
addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT));
doneButtonBadgeTextView = new TextView(context);
doneButtonBadgeTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@ -73,13 +63,7 @@ public class PickerBottomLayout extends FrameLayout {
doneButtonBadgeTextView.setBackgroundResource(isDarkTheme ? R.drawable.photobadge : R.drawable.bluecounter);
doneButtonBadgeTextView.setMinWidth(AndroidUtilities.dp(23));
doneButtonBadgeTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1));
doneButton.addView(doneButtonBadgeTextView);
LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) doneButtonBadgeTextView.getLayoutParams();
layoutParams1.width = LayoutHelper.WRAP_CONTENT;
layoutParams1.height = AndroidUtilities.dp(23);
layoutParams1.rightMargin = AndroidUtilities.dp(10);
layoutParams1.gravity = Gravity.CENTER_VERTICAL;
doneButtonBadgeTextView.setLayoutParams(layoutParams1);
doneButton.addView(doneButtonBadgeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 23, Gravity.CENTER_VERTICAL, 0, 0, 10, 0));
doneButtonTextView = new TextView(context);
doneButtonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
@ -88,12 +72,7 @@ public class PickerBottomLayout extends FrameLayout {
doneButtonTextView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase());
doneButtonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
doneButton.addView(doneButtonTextView);
layoutParams1 = (LinearLayout.LayoutParams) doneButtonTextView.getLayoutParams();
layoutParams1.width = LayoutHelper.WRAP_CONTENT;
layoutParams1.gravity = Gravity.CENTER_VERTICAL;
layoutParams1.height = LayoutHelper.WRAP_CONTENT;
doneButtonTextView.setLayoutParams(layoutParams1);
doneButton.addView(doneButtonTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL));
}
public void updateSelectedCount(int count, boolean disable) {

View File

@ -19,6 +19,8 @@ import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
public class RadioButton extends View {
@ -50,8 +52,15 @@ public class RadioButton extends View {
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
bitmap = Bitmap.createBitmap(AndroidUtilities.dp(size), AndroidUtilities.dp(size), Bitmap.Config.ARGB_4444);
bitmapCanvas = new Canvas(bitmap);
try {
bitmap = Bitmap.createBitmap(AndroidUtilities.dp(size), AndroidUtilities.dp(size), Bitmap.Config.ARGB_4444);
if (ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackFree(bitmap.getRowBytes() * bitmap.getHeight());
}
bitmapCanvas = new Canvas(bitmap);
} catch (Throwable e) {
FileLog.e("tmessages", e);
}
}
public void setProgress(float value) {
@ -86,7 +95,7 @@ public class RadioButton extends View {
private void animateToCheckedState(boolean newCheckedState) {
checkAnimator = ObjectAnimatorProxy.ofFloatProxy(this, "progress", newCheckedState ? 1 : 0);
checkAnimator.setDuration(300);
checkAnimator.setDuration(200);
checkAnimator.start();
}
@ -100,6 +109,11 @@ public class RadioButton extends View {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
attachedToWindow = false;
if (bitmap != null && ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackAlloc(bitmap.getRowBytes() * bitmap.getHeight());
bitmap.recycle();
bitmap = null;
}
}
public void setChecked(boolean checked, boolean animated) {
@ -124,10 +138,20 @@ public class RadioButton extends View {
protected void onDraw(Canvas canvas) {
if (bitmap == null || bitmap.getWidth() != getMeasuredWidth()) {
if (bitmap != null) {
if (ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackAlloc(bitmap.getRowBytes() * bitmap.getHeight());
}
bitmap.recycle();
}
bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
try {
bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
if (ImageLoader.getInstance().runtimeHack != null) {
ImageLoader.getInstance().runtimeHack.trackFree(bitmap.getRowBytes() * bitmap.getHeight());
}
bitmapCanvas = new Canvas(bitmap);
} catch (Throwable e) {
FileLog.e("tmessages", e);
}
}
float circleProgress;
float innerRad;
@ -147,16 +171,18 @@ public class RadioButton extends View {
paint.setColor(c);
checkedPaint.setColor(c);
}
bitmap.eraseColor(0);
float rad = size / 2 - (1 + circleProgress) * AndroidUtilities.density;
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad, paint);
if (progress <= 0.5f) {
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)), checkedPaint);
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)) * (1.0f - circleProgress), eraser);
} else {
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size / 4 + (rad - AndroidUtilities.dp(1) - size / 4) * circleProgress, checkedPaint);
}
if (bitmap != null) {
bitmap.eraseColor(0);
float rad = size / 2 - (1 + circleProgress) * AndroidUtilities.density;
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad, paint);
if (progress <= 0.5f) {
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)), checkedPaint);
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)) * (1.0f - circleProgress), eraser);
} else {
bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size / 4 + (rad - AndroidUtilities.dp(1) - size / 4) * circleProgress, checkedPaint);
}
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
}

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