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

update to 1.3.2

This commit is contained in:
DrKLO 2013-12-20 23:25:49 +04:00
parent 90d8e8a370
commit d52ade4855
969 changed files with 20183 additions and 14775 deletions

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />

View File

@ -3,10 +3,10 @@
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="Debug" />
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebug" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleTest" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
@ -26,37 +26,37 @@
<output url="file://$MODULE_DIR$/build/classes/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test/debug" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test/debug" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test/debug" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test/debug" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/test/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/assets" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/res" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/resources" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/instrumentTest/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/build/apk" />
<excludeFolder url="file://$MODULE_DIR$/build/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/bundles" />
@ -65,16 +65,17 @@
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/res" />
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android 4.3 Platform" jdkType="Android SDK" />
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="support-v4-18.0.0" level="project" />
<orderEntry type="library" exported="" name="ComGoogleAndroidGmsPlayServices3159.aar" level="project" />
<orderEntry type="library" exported="" name="HockeySDK-3.0.0" level="project" />
<orderEntry type="library" exported="" name="HockeySDK-3.0.1" level="project" />
<orderEntry type="library" exported="" name="ComGoogleAndroidGmsPlayServices4030.aar" level="project" />
<orderEntry type="library" exported="" name="native-libs" level="project" />
<orderEntry type="library" exported="" name="ComActionbarsherlockActionbarsherlock440.aar" level="project" />
<orderEntry type="library" exported="" name="support-v4-19.0.0" level="project" />
<orderEntry type="library" exported="" name="ComAndroidSupportAppcompatV71900.aar" level="project" />
</component>
</module>

View File

@ -3,7 +3,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.+'
classpath 'com.android.tools.build:gradle:0.7.+'
}
}
apply plugin: 'android'
@ -22,25 +22,49 @@ task nativeLibsToJar(
into 'lib/'
}
tasks.withType(Compile) {
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
tasks.withType(Compile) {
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
dependencies {
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.google.android.gms:play-services:4.0.+'
compile 'net.hockeyapp.android:HockeySDK:3.0.1'
compile 'com.android.support:support-v4:19.0.+'
compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
compile 'com.android.support:appcompat-v7:19.0.+'
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
buildToolsVersion '19.0.0'
signingConfigs {
debug {
storeFile file("debug.keystore")
}
release {
storeFile file("release.keystore")
}
}
buildTypes {
debug {
debuggable true
jniDebugBuild true
signingConfig signingConfigs.debug
}
release {
debuggable false
jniDebugBuild false
signingConfig signingConfigs.release
}
}
defaultConfig {
minSdkVersion 8

View File

@ -1,10 +1,11 @@
NDK_TOOLCHAIN_VERSION := 4.8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tmessages
LOCAL_CFLAGS = -w
LOCAL_MODULE := tmessages
LOCAL_CFLAGS = -w -std=gnu99 -O3
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := \
./aes_core.c \
./aes_ige.c \
@ -15,5 +16,6 @@ LOCAL_SRC_FILES := \
./org_telegram_SQLite_SQLiteDatabase.c \
./org_telegram_SQLite_SQLitePreparedStatement.c \
./org_telegram_SQLite.c
include $(BUILD_SHARED_LIBRARY)

View File

@ -1,2 +1,2 @@
APP_PLATFORM := android-8
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM := android-9
APP_ABI := armeabi armeabi-v7a x86

View File

@ -0,0 +1,128 @@
#!/bin/bash
function build_one {
echo "Cleaning..."
make clean
echo "Configuring..."
./configure --target-os=linux \
--prefix=$PREFIX \
--enable-cross-compile \
--extra-libs="-lgcc" \
--arch=$ARCH \
--cc=$CC \
--cross-prefix=$CROSS_PREFIX \
--nm=$NM \
--sysroot=$PLATFORM \
--extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -fasm -Wno-psabi -fno-short-enums -Dipv6mr_interface=ipv6mr_ifindex -fno-strict-aliasing -finline-limit=300 $OPTIMIZE_CFLAGS " \
--disable-shared \
--enable-static \
--extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl" \
\
--disable-everything \
--disable-network \
--enable-small \
--enable-zlib \
--disable-avfilter \
--disable-avdevice \
--disable-programs \
--disable-doc \
--disable-lsp \
--disable-dwt \
--disable-dct \
--enable-stripping \
--disable-postproc \
--disable-fft \
--disable-lzo \
--disable-rdft \
--disable-mdct \
--disable-debug \
\
--enable-muxer='mp4' \
--enable-protocol='file' \
--enable-encoder='aac,mpeg4' \
--enable-decoder='aac,amrnb,amrwb,flv,h263,h264' \
--enable-demuxer='flv,mpegvideo,mov' \
--enable-hwaccel='mpeg4_vaapi,mpeg4_vdpau' \
--enable-swresample \
--enable-swscale \
--enable-asm \
$ADDITIONAL_CONFIGURE_FLAG
echo "continue?"
read
make -j8 install
#$AR d libavcodec/libavcodec.a inverse.o
#$LD -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -soname libffmpeg.a -static -nostdlib -z noexecstack -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a -lc -lm -lz -ldl --dynamic-linker=/system/bin/linker $GCCLIB
}
NDK=/Users/DrKLO/ndk9
#arm platform
PLATFORM=$NDK/platforms/android-8/arch-arm
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64
LD=$PREBUILT/bin/arm-linux-androideabi-ld
AR=$PREBUILT/bin/arm-linux-androideabi-ar
NM=$PREBUILT/bin/arm-linux-androideabi-nm
GCCLIB=$PREBUILT/lib/gcc/arm-linux-androideabi/4.8/libgcc.a
ARCH=arm
CC=$PREBUILT/bin/arm-linux-androideabi-gcc
CROSS_PREFIX=$PREBUILT/bin/arm-linux-androideabi-
#arm v6
CPU=armv6
OPTIMIZE_CFLAGS="-marm -march=$CPU"
PREFIX=/Users/DrKLO/ndk9/platforms/android-9/arch-$ARCH/usr
ADDITIONAL_CONFIGURE_FLAG=
build_one
#arm v7vfpv3
#CPU=armv7-a
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU "
#PREFIX=./android/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#arm v7vfp
#CPU=armv7-a
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
#PREFIX=./android/$CPU-vfp
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#arm v7n
#CPU=armv7-a
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"
#PREFIX=./android/$CPU
#ADDITIONAL_CONFIGURE_FLAG=--enable-neon
#build_one
#arm v6+vfp
#CPU=armv6
#OPTIMIZE_CFLAGS="-DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU"
#PREFIX=./android/${CPU}_vfp
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#x86 platform
PLATFORM=$NDK/platforms/android-9/arch-x86
PREBUILT=$NDK/toolchains/x86-4.8/prebuilt/darwin-x86_64
LD=$PREBUILT/bin/i686-linux-android-ld
AR=$PREBUILT/bin/i686-linux-android-ar
NM=$PREBUILT/bin/i686-linux-android-nm
GCCLIB=$PREBUILT/lib/gcc/i686-linux-android/4.8/libgcc.a
ARCH=x86
CC=$PREBUILT/bin/i686-linux-android-gcc
CROSS_PREFIX=$PREBUILT/bin/i686-linux-android-
CPU=i686
OPTIMIZE_CFLAGS="-march=$CPU"
PREFIX=/Users/DrKLO/ndk9/platforms/android-9/arch-$ARCH/usr
ADDITIONAL_CONFIGURE_FLAG="--disable-mmx --disable-yasm"
build_one

View File

@ -5,12 +5,7 @@
#include <inttypes.h>
#include <android/log.h>
#include "aes.h"
#define LOG_TAG "tmessages_native"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#include "log.h"
JNIEXPORT jbyteArray Java_org_telegram_messenger_Utilities_aesIgeEncryption(JNIEnv *env, jclass class, jbyteArray _what, jbyteArray _key, jbyteArray _iv, jboolean encrypt, jboolean changeIv) {
unsigned char *what = (unsigned char *)(*env)->GetByteArrayElements(env, _what, NULL);
@ -84,100 +79,3 @@ JNIEXPORT jlong Java_org_telegram_messenger_Utilities_doPQNative(JNIEnv* env, jc
}
return g;
}
//sqlite
/*JNIEXPORT void Java_org_telegram_messenger_Utilities_beginTransaction(JNIEnv* env, jobject object, int dbHandle) {
sqlite3 *db = (sqlite3 *)dbHandle;
if (db == NULL) {
return;
}
sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
JNIEXPORT void Java_org_telegram_messenger_Utilities_commitTransaction(JNIEnv* env, jobject object, int dbHandle) {
sqlite3 *db = (sqlite3 *)dbHandle;
if (db == NULL) {
return;
}
sqlite3_exec(db, "COMMIT", 0, 0, 0);
}
int Java_org_telegram_messenger_Utilities_step(JNIEnv* env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int errcode = 0 ;
errcode = sqlite3_step(handle);
if (errcode == SQLITE_ROW) {
return 0;
} else if(errcode == SQLITE_DONE) {
return 1;
} else if(errcode == SQLITE_BUSY) {
return -1;
}
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
int Java_org_telegram_messenger_Utilities_columnType(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
return sqlite3_column_type(handle, columnIndex);
}
int Java_org_telegram_messenger_Utilities_columnIsNull(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
return SQLITE_NULL == valType;
}
int Java_org_telegram_messenger_Utilities_columnIntValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_int(handle, columnIndex);
}
jdouble Java_org_telegram_messenger_Utilities_columnDoubleValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
int valType = sqlite3_column_type(handle, columnIndex);
if (SQLITE_NULL == valType) {
return 0;
}
return sqlite3_column_double(handle, columnIndex);
}
jstring Java_org_telegram_messenger_Utilities_columnStringValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
const char* str = sqlite3_column_text(handle, columnIndex);
if (str != 0) {
return (*env)->NewStringUTF(env, str);
}
return 0;
}
jbyteArray Java_org_telegram_messenger_Utilities_columnByteArrayValue(JNIEnv* env, jobject object, int statementHandle, int columnIndex) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle;
void *buf = sqlite3_column_blob(handle, columnIndex);
int length = sqlite3_column_bytes(handle, columnIndex);
if (buf != 0 && length > 0) {
jbyteArray result = (*env)->NewByteArray(env, length);
(*env)->SetByteArrayRegion(env, result, 0, length, buf);
return result;
}
return 0;
}*/

12
TMessagesProj/jni/log.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef log_h
#define log_h
#include <android/log.h>
#define LOG_TAG "tmessages_native"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#endif

View File

@ -18,8 +18,15 @@ void Java_org_telegram_SQLite_SQLiteDatabase_commitTransaction(JNIEnv *env, jobj
sqlite3_exec(handle, "COMMIT", 0, 0, 0);
}
int Java_org_telegram_SQLite_SQLiteDatabase_opendb(JNIEnv *env, jobject object, jstring fileName) {
int Java_org_telegram_SQLite_SQLiteDatabase_opendb(JNIEnv *env, jobject object, jstring fileName, jstring tempDir) {
char const *fileNameStr = (*env)->GetStringUTFChars(env, fileName, 0);
char const *tempDirStr = (*env)->GetStringUTFChars(env, tempDir, 0);
if (sqlite3_temp_directory != 0) {
sqlite3_free(sqlite3_temp_directory);
}
sqlite3_temp_directory = sqlite3_mprintf("%s", tempDirStr);
sqlite3 *handle = 0;
int err = sqlite3_open(fileNameStr, &handle);
if (SQLITE_OK != err) {
@ -28,5 +35,8 @@ int Java_org_telegram_SQLite_SQLiteDatabase_opendb(JNIEnv *env, jobject object,
if (fileNameStr != 0) {
(*env)->ReleaseStringUTFChars(env, fileName, fileNameStr);
}
if (tempDirStr != 0) {
(*env)->ReleaseStringUTFChars(env, tempDir, tempDirStr);
}
return (int)handle;
}

File diff suppressed because it is too large Load Diff

View File

@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.7.17"
#define SQLITE_VERSION_NUMBER 3007017
#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
#define SQLITE_VERSION "3.8.1"
#define SQLITE_VERSION_NUMBER 3008001
#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -478,11 +478,15 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
#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_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@ -499,6 +503,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
@ -1612,27 +1617,27 @@ struct sqlite3_mem_methods {
** function must be threadsafe. </dd>
**
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
** <dd> This option takes a single argument of type int. If non-zero, then
** <dd>^(This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
** is globally disabled. If URI handling is globally enabled, all filenames
** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
** connection is opened. If it is globally disabled, filenames are
** connection is opened. ^If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** database connection is opened. ^(By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
** [SQLITE_USE_URI] symbol defined.)^
**
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
** <dd> This option takes a single integer argument which is interpreted as
** <dd>^This option takes a single integer argument which is interpreted as
** a boolean in order to enable or disable the use of covering indices for
** full table scans in the query optimizer. The default setting is determined
** full table scans in the query optimizer. ^The default setting is determined
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
** if that compile-time option is omitted.
** The ability to disable the use of covering indices for full table scans
** is because some incorrectly coded legacy applications might malfunction
** malfunction when the optimization is enabled. Providing the ability to
** when the optimization is enabled. Providing the ability to
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
@ -1661,16 +1666,16 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_MMAP_SIZE]]
** <dt>SQLITE_CONFIG_MMAP_SIZE
** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** that are the default mmap size limit (the default setting for
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
** The default setting can be overridden by each database connection using
** ^The default setting can be overridden by each database connection using
** either the [PRAGMA mmap_size] command, or by using the
** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
** cannot be changed at run-time. Nor may the maximum allowed mmap size
** exceed the compile-time maximum mmap size set by the
** [SQLITE_MAX_MMAP_SIZE] compile-time option.
** If either argument to this option is negative, then that argument is
** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
** ^If either argument to this option is negative, then that argument is
** changed to its compile-time default.
** </dl>
*/
@ -2557,9 +2562,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the
** callback function X. ^The parameter N is the number of
** callback function X. ^The parameter N is the approximate number of
** [virtual machine instructions] that are evaluated between successive
** invocations of the callback X.
** invocations of the callback X. ^If N is less than one then the progress
** handler is disabled.
**
** ^Only a single progress handler may be defined at one time per
** [database connection]; setting a new progress handler cancels the
@ -4179,41 +4185,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
**
** The following two functions may be used by scalar SQL functions to
** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
** some circumstances the associated metadata may be preserved. This may
** be used, for example, to add a regular-expression matching scalar
** function. The compiled version of the regular expression is stored as
** metadata associated with the SQL value passed as the regular expression
** pattern. The compiled regular expression can be reused on multiple
** invocations of the same function so that the original pattern string
** does not need to be recompiled on each invocation.
** some circumstances the associated metadata may be preserved. An example
** of where this might be useful is in a regular-expression matching
** function. The compiled version of the regular expression can be stored as
** metadata associated with the pattern string.
** Then as long as the pattern string remains the same,
** the compiled regular expression can be reused on multiple
** invocations of the same function.
**
** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
** associated by the sqlite3_set_auxdata() function with the Nth argument
** value to the application-defined function. ^If no metadata has been ever
** been set for the Nth argument of the function, or if the corresponding
** function parameter has changed since the meta-data was set,
** then sqlite3_get_auxdata() returns a NULL pointer.
** value to the application-defined function. ^If there is no metadata
** associated with the function argument, this sqlite3_get_auxdata() interface
** returns a NULL pointer.
**
** ^The sqlite3_set_auxdata() interface saves the metadata
** pointed to by its 3rd parameter as the metadata for the N-th
** argument of the application-defined function. Subsequent
** calls to sqlite3_get_auxdata() might return this data, if it has
** not been destroyed.
** ^If it is not NULL, SQLite will invoke the destructor
** function given by the 4th parameter to sqlite3_set_auxdata() on
** the metadata when the corresponding function parameter changes
** or when the SQL statement completes, whichever comes first.
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
** argument of the application-defined function. ^Subsequent
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
** NULL if the metadata has been discarded.
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
** SQLite will invoke the destructor function X with parameter P exactly
** once, when the metadata is discarded.
** SQLite is free to discard the metadata at any time, including: <ul>
** <li> when the corresponding function parameter changes, or
** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
** SQL statement, or
** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
** <li> during the original sqlite3_set_auxdata() call when a memory
** allocation error occurs. </ul>)^
**
** SQLite is free to call the destructor and drop metadata on any
** parameter of any function at any time. ^The only guarantee is that
** the destructor will be called before the metadata is dropped.
** Note the last bullet in particular. The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.
**
** ^(In practice, metadata is preserved between function calls for
** expressions that are constant at compile time. This includes literal
** values and [parameters].)^
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
@ -4518,6 +4532,11 @@ SQLITE_API int sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
SQLITE_API int sqlite3_key_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The key */
);
/*
** Change the key on an open database. If the current database is not
@ -4531,6 +4550,11 @@ SQLITE_API int sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
SQLITE_API int sqlite3_rekey_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The new key */
);
/*
** Specify the activation key for a SEE database. Unless
@ -5116,10 +5140,23 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
** See also: [sqlite3_reset_auto_extension()].
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/
SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Cancel Automatic Extension Loading
**
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
** initialization routine X that was registered using a prior call to
** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
** routine returns 1 if initialization routine X was successfully
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Reset Automatic Extension Loading
**
@ -6232,6 +6269,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
** <dd>This parameter returns zero for the current value if and only if
** all foreign key constraints (deferred or immediate) have been
** resolved.)^ ^The highwater mark is always 0.
** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@ -6244,7 +6287,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_HIT 7
#define SQLITE_DBSTATUS_CACHE_MISS 8
#define SQLITE_DBSTATUS_CACHE_WRITE 9
#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */
/*
@ -6298,11 +6342,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
**
** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
** <dd>^This is the number of virtual machine operations executed
** by the prepared statement if that number is less than or equal
** to 2147483647. The number of virtual machine operations can be
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
#define SQLITE_STMTSTATUS_VM_STEP 4
/*
** CAPI3REF: Custom Page Cache Object
@ -7181,7 +7235,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
#endif
#endif /* _SQLITE3_H_ */
/*
** 2010 August 30

View File

@ -474,11 +474,14 @@ struct sqlite3_api_routines {
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* _SQLITE3EXT_H_ */

18
TMessagesProj/jni/video.c Normal file
View File

@ -0,0 +1,18 @@
#include <jni.h>
#include "video.h"
JNIEXPORT void Java_org_telegram_messenger_VideoTools_initialize(JNIEnv* env, jclass class) {
av_register_all();
}
JNIEXPORT void Java_org_telegram_messenger_VideoTools_convert(JNIEnv* env, jclass class, jstring in, jstring out, int bitr) {
char const *in_str = (*env)->GetStringUTFChars(env, in, 0);
char const *out_str = (*env)->GetStringUTFChars(env, out, 0);
convertFile(in_str, out_str, bitr);
if (in_str != 0) {
(*env)->ReleaseStringUTFChars(env, in, in_str);
}
if (out_str != 0) {
(*env)->ReleaseStringUTFChars(env, out, out_str);
}
}

17
TMessagesProj/jni/video.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef video_h
#define video_h
#include <libavformat/avformat.h>
int prepare_for_video_conversion(const char *dst_filename, AVCodecContext *video_dec_ctx, AVCodecContext *audio_dec_ctx, AVFormatContext *fmt_ctx, AVStream *src_video_stream, AVStream *src_audio_stream, int bitr);
int write_video_frame(AVFrame *src_frame);
int write_audio_frame(AVFrame *src_frame, AVCodecContext *src_codec);
void post_video_conversion();
void cleanup_out();
void onError();
void onProgress();
void onDone();
void convertFile(const char *src_filename, const char *dst_filename, int bitr);
#endif

View File

@ -0,0 +1,243 @@
#include "video.h"
#include <stdio.h>
#include <libavutil/timestamp.h>
#include <libavutil/imgutils.h>
#include "log.h"
AVPacket pkt;
int video_stream_idx = -1, audio_stream_idx = -1;
AVCodecContext *video_dec_ctx = NULL, *audio_dec_ctx = NULL;
AVFrame *frame = NULL;
AVStream *video_stream = NULL, *audio_stream = NULL;
AVFormatContext *fmt_ctx = NULL;
int64_t total_duration;
int64_t current_duration;
char *src = NULL;
char *dest = NULL;
int lastLog = 10;
void cleanup_in() {
if (video_dec_ctx) {
avcodec_close(video_dec_ctx);
video_dec_ctx = NULL;
}
if (audio_dec_ctx) {
avcodec_close(audio_dec_ctx);
audio_dec_ctx = NULL;
}
if (fmt_ctx) {
avformat_close_input(&fmt_ctx);
fmt_ctx = NULL;
}
if (frame) {
av_frame_free(&frame);
frame = NULL;
}
if (src) {
free(src);
src = NULL;
}
if (dest) {
free(dest);
dest = NULL;
}
total_duration = 0;
current_duration = 0;
video_stream_idx = -1;
audio_stream_idx = -1;
video_stream = NULL;
audio_stream = NULL;
lastLog = 10;
}
void onError() {
cleanup_in();
cleanup_out();
}
void onDone() {
LOGD("OK\n");
cleanup_in();
cleanup_out();
}
void onProgress() {
float progress = (float)current_duration / (float)total_duration * 100;
if (progress > lastLog) {
lastLog += 10;
LOGD("progress %.2f\n", progress);
}
}
int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) {
int ret;
AVStream *st;
AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL;
AVDictionary *opts = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) {
LOGD("Could not find %s stream in input file\n", av_get_media_type_string(type));
return ret;
} else {
*stream_idx = ret;
st = fmt_ctx->streams[*stream_idx];
dec_ctx = st->codec;
dec = avcodec_find_decoder(dec_ctx->codec_id);
if (!dec) {
LOGD("Failed to find %s codec\n", av_get_media_type_string(type));
return ret;
}
av_dict_set(&opts, "refcounted_frames", "1", 0);
if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) {
LOGD("Failed to open %s codec\n", av_get_media_type_string(type));
return ret;
}
}
return 0;
}
int decode_packet(int *got_frame, int cached) {
int ret = 0;
int decoded = pkt.size;
*got_frame = 0;
if (pkt.stream_index == video_stream_idx) {
ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt);
if (ret < 0) {
LOGD("Error decoding video frame\n");
return ret;
}
if (*got_frame) {
ret = write_video_frame(frame);
if (ret < 0) {
return ret;
}
}
} else if (pkt.stream_index == audio_stream_idx) {
ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
if (ret < 0) {
LOGD("Error decoding audio frame\n");
return ret;
}
decoded = FFMIN(ret, pkt.size);
if (*got_frame) {
ret = write_audio_frame(frame, audio_dec_ctx);
if (ret < 0) {
return -1;
}
}
frame->pts = AV_NOPTS_VALUE;
}
if (*got_frame) {
av_frame_unref(frame);
}
return decoded;
}
void convertFile(const char *src_filename, const char *dst_filename, int bitr) {
int ret = 0;
int got_frame;
src = malloc(strlen(src_filename) + 1);
memcpy(src, src_filename, strlen(src_filename));
src[strlen(src_filename)] = '\0';
dest = malloc(strlen(dst_filename) + 1);
memcpy(dest, dst_filename, strlen(dst_filename));
dest[strlen(dst_filename)] = '\0';
if ((ret = avformat_open_input(&fmt_ctx, src, NULL, NULL)) < 0) {
LOGD("Could not open source file %s, %s\n", src, av_err2str(ret));
onError();
return;
}
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
LOGD("Could not find stream information\n");
onError();
return;
}
if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) {
video_stream = fmt_ctx->streams[video_stream_idx];
video_dec_ctx = video_stream->codec;
}
if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
audio_stream = fmt_ctx->streams[audio_stream_idx];
audio_dec_ctx = audio_stream->codec;
}
av_dump_format(fmt_ctx, 0, src, 0);
if (!audio_stream && !video_stream) {
LOGD("Could not find audio or video stream in the input, aborting\n");
onError();
return;
}
frame = av_frame_alloc();
if (!frame) {
LOGD("Could not allocate frame\n");
onError();
return;
}
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
if (video_stream) {
LOGD("Demuxing video from file '%s'\n", src);
}
if (audio_stream) {
LOGD("Demuxing audio from file '%s'\n", src);
}
ret = prepare_for_video_conversion(dest, video_dec_ctx, audio_dec_ctx, fmt_ctx, video_stream, audio_stream, bitr);
if (ret < 0) {
return;
}
if (video_stream) {
total_duration = video_stream->duration;
}
if (audio_stream) {
total_duration += audio_stream->duration;
}
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
AVPacket orig_pkt = pkt;
do {
ret = decode_packet(&got_frame, 0);
if (ret < 0) {
onError();
return;
}
pkt.data += ret;
pkt.size -= ret;
current_duration += pkt.duration;
onProgress();
} while (pkt.size > 0);
av_free_packet(&orig_pkt);
}
pkt.data = NULL;
pkt.size = 0;
do {
decode_packet(&got_frame, 1);
} while (got_frame);
post_video_conversion();
onDone();
}

View File

@ -0,0 +1,366 @@
#include "video.h"
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include "log.h"
AVFrame *out_frame = NULL;
struct SwsContext *sws_ctx = NULL;
AVStream *video_st = NULL, *audio_st = NULL;
AVFormatContext *oc = NULL;
AVOutputFormat *fmt = NULL;
AVPicture dst_picture;
uint8_t **dst_samples_data = NULL;
SwrContext *swr_ctx = NULL;
int current_n_out = 0;
int current_in_buff = 0;
uint8_t buff[4096 * 2];
int min(int val1, int val2) {
return val1 < val2 ? val1 : val2;
}
int prepare_for_video_conversion(const char *dst_filename, AVCodecContext *video_dec_ctx, AVCodecContext *audio_dec_ctx, AVFormatContext *fmt_ctx, AVStream *src_video_stream, AVStream *src_audio_stream, int bitr) {
if (!video_dec_ctx && !audio_dec_ctx) {
onError();
return -1;
}
avformat_alloc_output_context2(&oc, NULL, "mp4", dst_filename);
if (!oc) {
onError();
return -1;
}
fmt = oc->oformat;
av_dict_copy(&oc->metadata, fmt_ctx->metadata, 0);
int ret = 0;
if (!(fmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&oc->pb, dst_filename, AVIO_FLAG_WRITE);
if (ret < 0) {
LOGD("Could not open '%s': %s\n", dst_filename, av_err2str(ret));
onError();
return -1;
}
}
AVCodecContext *c;
if (video_dec_ctx && src_video_stream && fmt_ctx) {
//calculate video resolution
int dst_width = video_dec_ctx->width, dst_height = video_dec_ctx->height;
if (video_dec_ctx->width > video_dec_ctx->height) {
if (video_dec_ctx->width > 480) {
float scale = video_dec_ctx->width / 480.0f;
dst_width = 480;
dst_height = ceilf(video_dec_ctx->height / scale);
}
} else {
if (video_dec_ctx->width > 480) {
float scale = video_dec_ctx->height / 480.0f;
dst_height = 480;
dst_width = ceilf(video_dec_ctx->width / scale);
}
}
if (video_dec_ctx->height != dst_height || video_dec_ctx->width != dst_width || video_dec_ctx->pix_fmt != AV_PIX_FMT_YUV420P) {
sws_ctx = sws_getContext(video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt, dst_width, dst_height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
LOGD("Could not initialize the conversion context\n");
onError();
return -1;
}
}
//create video stream
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
if (!codec) {
LOGD("Could not find encoder for '%s'\n", avcodec_get_name(AV_CODEC_ID_MPEG4));
onError();
return -1;
}
video_st = avformat_new_stream(oc, codec);
if (!video_st) {
LOGD("Could not allocate stream\n");
onError();
return -1;
}
video_st->id = oc->nb_streams - 1;
av_dict_copy(&video_st->metadata, src_video_stream->metadata, 0);
c = video_st->codec;
c->codec_id = AV_CODEC_ID_MPEG4;
c->bit_rate = bitr;
c->width = dst_width;
c->height = dst_height;
double fps = (double)src_video_stream->avg_frame_rate.num / (double)src_video_stream->avg_frame_rate.den;
c->time_base.den = 65535;
c->time_base.num = floor(65635 / fps);
c->gop_size = 12;
c->pix_fmt = AV_PIX_FMT_YUV420P;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
ret = avcodec_open2(c, codec, NULL);
if (ret < 0) {
LOGD("Could not open video codec: %s\n", av_err2str(ret));
onError();
return -1;
}
out_frame = avcodec_alloc_frame();
if (!out_frame) {
LOGD("Could not allocate video frame\n");
onError();
return -1;
}
ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
if (ret < 0) {
LOGD("Could not allocate picture: %s\n", av_err2str(ret));
onError();
return -1;
}
*((AVPicture *)out_frame) = dst_picture;
}
//create audio stream
if (audio_dec_ctx && src_audio_stream) {
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec) {
LOGD("Could not find encoder for '%s'\n", avcodec_get_name(AV_CODEC_ID_AAC));
onError();
return -1;
}
audio_st = avformat_new_stream(oc, codec);
if (!audio_st) {
LOGD("Could not allocate stream\n");
onError();
return -1;
}
audio_st->id = oc->nb_streams - 1;
av_dict_copy(&audio_st->metadata, src_audio_stream->metadata, 0);
c = audio_st->codec;
c->sample_fmt = AV_SAMPLE_FMT_FLTP;
c->bit_rate = 40000;
c->sample_rate = min(audio_dec_ctx->sample_rate, 44100);
c->channels = 1;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
c = audio_st->codec;
c->strict_std_compliance = -2;
swr_ctx = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_MONO, c->sample_fmt, c->sample_rate, audio_dec_ctx->channel_layout, audio_dec_ctx->sample_fmt, audio_dec_ctx->sample_rate, 0, NULL);
if (!swr_ctx) {
LOGD("Could not allocate resampler context\n");
onError();
return -1;
}
if ((ret = swr_init(swr_ctx)) < 0) {
LOGD("Failed to initialize the resampling context\n");
onError();
return -1;
}
ret = avcodec_open2(c, codec, NULL);
if (ret < 0) {
LOGD("Could not open audio codec: %s\n", av_err2str(ret));
onError();
return -1;
}
av_dump_format(oc, 0, dst_filename, 1);
ret = avformat_write_header(oc, NULL);
if (ret < 0) {
LOGD("Error occurred when opening output file: %s\n", av_err2str(ret));
onError();
return -1;
}
if (out_frame) {
out_frame->pts = 0;
}
}
return 0;
}
void cleanup_out() {
if (video_st) {
avcodec_close(video_st->codec);
if (dst_picture.data) {
av_free(dst_picture.data[0]);
}
if (out_frame) {
av_free(out_frame);
out_frame = NULL;
}
video_st = NULL;
}
if (audio_st) {
avcodec_close(audio_st->codec);
if (dst_samples_data) {
av_free(dst_samples_data[0]);
dst_samples_data = NULL;
}
audio_st = NULL;
}
if (fmt && !(fmt->flags & AVFMT_NOFILE)) {
avio_close(oc->pb);
fmt = NULL;
}
if (oc) {
avformat_free_context(oc);
oc = NULL;
}
if (sws_ctx) {
sws_freeContext(sws_ctx);
sws_ctx = NULL;
}
if (swr_ctx) {
swr_free(&swr_ctx);
swr_ctx = NULL;
}
current_n_out = 0;
current_in_buff = 0;
}
int write_video_frame(AVFrame *src_frame) {
int ret;
if (sws_ctx) {
ret = sws_scale(sws_ctx, (const uint8_t * const *)src_frame->data, src_frame->linesize, 0, src_frame->height, out_frame->data, out_frame->linesize);
if (ret < 0) {
LOGD("scale error: %s\n", av_err2str(ret));
onError();
return -1;
}
} else {
for (int i = 0; i < 4; i++){
out_frame->data[i] = src_frame->data[i];
out_frame->linesize[i] = src_frame->linesize[i];
}
}
AVPacket pkt = { 0 };
int got_packet;
av_init_packet(&pkt);
ret = avcodec_encode_video2(video_st->codec, &pkt, out_frame, &got_packet);
if (ret < 0) {
LOGD("Error encoding video frame: %s\n", av_err2str(ret));
onError();
return -1;
}
if (!ret && got_packet && pkt.size) {
pkt.stream_index = video_st->index;
ret = av_interleaved_write_frame(oc, &pkt);
} else {
ret = 0;
}
if (ret != 0) {
LOGD("Error while writing video frame: %s\n", av_err2str(ret));
onError();
return -1;
}
int64_t val = av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
out_frame->pts += val;
return 0;
}
int check_write_packet(int flush) {
int got_packet, ret;
int writed = 0;
int dst_samples_size = av_samples_get_buffer_size(NULL, audio_st->codec->channels, audio_st->codec->frame_size, audio_st->codec->sample_fmt, 1);
while (current_n_out > audio_st->codec->frame_size || (flush && current_n_out)) {
AVFrame *frame = avcodec_alloc_frame();
AVPacket pkt2 = { 0 };
av_init_packet(&pkt2);
frame->nb_samples = min(audio_st->codec->frame_size, current_n_out);
int nb_samples_size = min(dst_samples_size, current_in_buff);
ret = avcodec_fill_audio_frame(frame, audio_st->codec->channels, audio_st->codec->sample_fmt, buff + writed, nb_samples_size, 1);
if (ret < 0) {
LOGD("Error fill frame: %s\n", av_err2str(ret));
onError();
return -1;
}
ret = avcodec_encode_audio2(audio_st->codec, &pkt2, frame, &got_packet);
if (ret < 0) {
LOGD("Error encoding audio frame: %s\n", av_err2str(ret));
onError();
return -1;
}
if (got_packet) {
pkt2.stream_index = audio_st->index;
ret = av_interleaved_write_frame(oc, &pkt2);
if (ret != 0) {
LOGD("Error while writing audio frame: %s\n", av_err2str(ret));
onError();
return -1;
}
}
writed += dst_samples_size;
current_n_out -= frame->nb_samples;
current_in_buff -= nb_samples_size;
avcodec_free_frame(&frame);
}
if (current_in_buff != 0 && writed != 0) {
memcpy(buff, buff + writed, current_in_buff);
}
return 0;
}
int write_audio_frame(AVFrame *src_frame, AVCodecContext *src_codec) {
const int n_in = src_frame->nb_samples;
double ratio = (double)audio_st->codec->sample_rate / src_frame->sample_rate;
int n_out = n_in * ratio + 32;
int64_t delay = swr_get_delay(swr_ctx, audio_st->codec->sample_rate);
if (delay > 0) {
n_out += delay;
}
if (!dst_samples_data) {
int ret = av_samples_alloc_array_and_samples(&dst_samples_data, NULL, audio_st->codec->channels, n_out, audio_st->codec->sample_fmt, 0);
if (ret < 0) {
LOGD("Could not allocate destination samples\n");
onError();
return -1;
}
}
n_out = swr_convert(swr_ctx, dst_samples_data, n_out, (const uint8_t **)src_frame->extended_data, src_frame->nb_samples);
if (n_out <= 0) {
LOGD("Error while converting\n");
onError();
return -1;
}
int total_size = av_samples_get_buffer_size(NULL, audio_st->codec->channels, n_out, audio_st->codec->sample_fmt, 1);
memcpy(buff + current_in_buff, dst_samples_data[0], total_size);
current_n_out += n_out;
current_in_buff += total_size;
return check_write_packet(0);
}
void post_video_conversion() {
check_write_packet(1);
av_write_trailer(oc);
}

View File

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.telegram.messenger"
android:versionCode="98"
android:versionName="1.2.7">
android:versionCode="122"
android:versionName="1.3.2">
<supports-screens android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:resizeable="true"
android:xlargeScreens="true"/>
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:resizeable="true"
android:xlargeScreens="true"/>
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
@ -22,7 +22,8 @@
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false" />
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
<uses-feature android:name="android.hardware.screen.PORTRAIT" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@ -48,24 +49,25 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<permission android:name="org.telegram.messenger.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
android:theme="@style/Theme.Sherlock.Light"
android:theme="@style/Theme.TMessages.Start"
android:name="org.telegram.ui.ApplicationLoader"
android:hardwareAccelerated="true">
android:hardwareAccelerated="true"
android:largeHeap="true">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="your-google-maps-api-key-here" />
<activity
android:name="org.telegram.ui.LaunchActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
android:name="org.telegram.ui.LaunchActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -92,68 +94,78 @@
</intent-filter>
</activity>
<activity
android:name="org.telegram.ui.LoginActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
android:name="org.telegram.ui.LoginActivity"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait">
</activity>
<activity
android:name="org.telegram.ui.CountrySelectActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.TMessages"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait">
</activity>
<activity
android:name="org.telegram.ui.IntroActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait">
</activity>
<activity
android:name="org.telegram.ui.ApplicationActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.TMessages"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.ApplicationActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.TMessages"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
android:name="org.telegram.ui.GalleryImageViewer"
android:theme="@style/Theme.TMessages.Gallery"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.GalleryImageViewer"
android:theme="@style/Theme.TMessages.Gallery"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity android:name="net.hockeyapp.android.UpdateActivity" />
<receiver android:name="org.telegram.messenger.SmsListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<receiver
android:name="org.telegram.messenger.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
android:name="org.telegram.messenger.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="org.telegram.messenger" />
</intent-filter>
</receiver>
<service android:name="org.telegram.messenger.AuthenticatorService"
android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/auth"/>
android:resource="@xml/auth"/>
</service>
<service android:name="org.telegram.messenger.ContactsSyncAdapterService"
android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/sync_contacts" />
android:resource="@xml/sync_contacts" />
<meta-data android:name="android.provider.CONTACTS_STRUCTURE"
android:resource="@xml/contacts" />
android:resource="@xml/contacts" />
</service>
<uses-library android:name="com.google.android.maps" android:required="false"/>
</application>
</manifest>

View File

@ -1,28 +1,21 @@
6723;NF;Norfolk Island
5999;CW;Curaçao
1939;PR;Puerto Rico
1876;JM;Jamaica
1869;KN;Saint Kitts and Nevis
1868;TT;Trinidad and Tobago
1849;DO;Dominican Republic
1829;DO;Dominican Republic
1809;DO;Dominican Republic
1787;PR;Puerto Rico
1784;VC;Saint Vincent and the Grenadines
1869;KN;Saint Kitts & Nevis
1868;TT;Trinidad & Tobago
1784;VC;Saint Vincent & the Grenadines
1767;DM;Dominica
1758;LC;Saint Lucia
1721;SX;Bonaire, Sint Eustatius and Saba
1721;SX;Sint Maarten
1684;AS;American Samoa
1671;GU;Guam
1670;MP;Northern Mariana Islands
1664;MS;Montserrat
1649;TC;Turks and Caicos Islands
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 and Barbuda
1268;AG;Antigua & Barbuda
1264;AI;Anguilla
1246;BB;Barbados
1242;BS;Bahamas
@ -45,7 +38,7 @@
966;SA;Saudi Arabia
965;KW;Kuwait
964;IQ;Iraq
963;SY;Syria
963;SY;Syrian Arab Republic
962;JO;Jordan
961;LB;Lebanon
960;MV;Maldives
@ -66,7 +59,7 @@
685;WS;Samoa
683;NU;Niue
682;CK;Cook Islands
681;WF;Wallis and Futuna
681;WF;Wallis & Futuna
680;PW;Palau
679;FJ;Fiji
678;VU;Vanuatu
@ -75,9 +68,10 @@
675;PG;Papua New Guinea
674;NR;Nauru
673;BN;Brunei Darussalam
672;AU;Australia
670;TL;East Timor
599;BQ;Sint Maarten
672;NF;Norfolk Island
670;TL;Timor-Leste
599;BQ;Bonaire, Sint Eustatius & Saba
599;CW;Curaçao
598;UY;Uruguay
597;SR;Suriname
596;MQ;Martinique
@ -88,7 +82,7 @@
591;BO;Bolivia
590;GP;Guadeloupe
509;HT;Haiti
508;PM;Saint Pierre and Miquelon
508;PM;Saint Pierre & Miquelon
507;PA;Panama
506;CR;Costa Rica
505;NI;Nicaragua
@ -101,7 +95,7 @@
421;SK;Slovakia
420;CZ;Czech Republic
389;MK;Macedonia
387;BA;Bosnia and Herzegovina
387;BA;Bosnia & Herzegovina
386;SI;Slovenia
385;HR;Croatia
382;ME;Montenegro
@ -153,17 +147,17 @@
249;SD;Sudan
248;SC;Seychelles
247;SH;Saint Helena
246;IO;United Kingdom
246;IO;Diego Garcia
245;GW;Guinea-Bissau
244;AO;Angola
243;CD;Congo, Democratic Republic
242;CG;Congo
243;CD;Congo (Dem. Rep.)
242;CG;Congo (Rep.)
241;GA;Gabon
240;GQ;Equatorial Guinea
239;ST;São Tomé and Príncipe
239;ST;São Tomé & Príncipe
238;CV;Cape Verde
237;CM;Cameroon
236;CF;Central African Republic
236;CF;Central African Rep.
235;TD;Chad
234;NG;Nigeria
233;GH;Ghana
@ -228,8 +222,10 @@
31;NL;Netherlands
30;GR;Greece
27;ZA;South Africa
20;EG;Egypt
7;KZ;Kazakhstan
7;RU;Russia
1;US;USA
1;CA;Canada
20;EG;Egypt
7;KZ;Kazakhstan
7;RU;Russian Federation
1;PR;Puerto Rico
1;DO;Dominican Rep.
1;CA;Canada
1;US;USA

Binary file not shown.

View File

@ -16,7 +16,7 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
package jawnae.pyronet;
import java.nio.ByteBuffer;
import java.util.ArrayList;

View File

@ -31,14 +31,9 @@ import java.nio.channels.SocketChannel;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import jawnae.pyronet.events.PyroClientListener;
import jawnae.pyronet.traffic.ByteStream;
public class PyroClient {
private final PyroSelector selector;
final PyroServer server;
private final SelectionKey key;
private final ByteStream outbound;
@ -46,18 +41,17 @@ public class PyroClient {
// called by PyroSelector.connect()
PyroClient(PyroSelector selector, InetSocketAddress bind,
InetSocketAddress host) throws IOException {
this(selector, null, PyroClient.bindAndConfigure(selector,
this(selector, PyroClient.bindAndConfigure(selector,
SocketChannel.open(), bind));
((SocketChannel) this.key.channel()).connect(host);
}
// called by PyroClient and PyroServer
PyroClient(PyroSelector selector, PyroServer server, SelectionKey key) {
PyroClient(PyroSelector selector, SelectionKey key) {
this.selector = selector;
this.selector.checkThread();
this.server = server;
this.key = key;
this.key.attach(this);
@ -163,20 +157,6 @@ public class PyroClient {
//
/**
* Returns the server that accepted this client.
*
* @throws PyroException
* if this client was not accepted by a server (it connected to
* a server)
*/
public final PyroServer getServer() throws PyroException {
if (this.server == null)
throw new PyroException("this client was not accepted by a server");
return this.server;
}
//
//
@ -425,7 +405,7 @@ public class PyroClient {
private int onReadyToWrite(long now) throws IOException {
this.selector.checkThread();
this.lastEventTime = now;
//this.lastEventTime = now;
int sent = 0;
@ -479,13 +459,9 @@ public class PyroClient {
return;
}
if (this.server != null) {
this.server.onDisconnect(this);
}
if (cause instanceof ConnectException) {
for (PyroClientListener listener: this.listeners)
listener.unconnectableClient(this);
listener.unconnectableClient(this, (Exception)cause);
} else if (cause instanceof EOFException) // after read=-1
{
for (PyroClientListener listener: this.listeners)
@ -495,7 +471,7 @@ public class PyroClient {
listener.droppedClient(this, (IOException) cause);
} else if (!(cause instanceof String)) {
for (PyroClientListener listener: this.listeners)
listener.unconnectableClient(this);
listener.unconnectableClient(this, null);
} else if (cause.equals("local")) {
for (PyroClientListener listener: this.listeners)
listener.disconnectedClient(this);
@ -551,7 +527,7 @@ public class PyroClient {
// channel.socket().setSoLinger(false, 0); // this will b0rk your
// connections
channel.socket().setSoLinger(true, 4);
channel.socket().setReuseAddress(true);
channel.socket().setReuseAddress(false);
channel.socket().setKeepAlive(false);
channel.socket().setTcpNoDelay(true);
channel.socket().setReceiveBufferSize(PyroSelector.BUFFER_SIZE);

View File

@ -16,19 +16,17 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
package jawnae.pyronet;
import java.io.IOException;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public class PyroClientAdapter implements PyroClientListener {
public void connectedClient(PyroClient client) {
//
}
public void unconnectableClient(PyroClient client) {
public void unconnectableClient(PyroClient client, Exception cause) {
System.out.println("unconnectable");
}

View File

@ -16,7 +16,7 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
package jawnae.pyronet;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -26,7 +26,7 @@ import jawnae.pyronet.PyroClient;
public interface PyroClientListener {
public void connectedClient(PyroClient client);
public void unconnectableClient(PyroClient client);
public void unconnectableClient(PyroClient client, Exception cause);
public void droppedClient(PyroClient client, IOException cause);

View File

@ -19,7 +19,6 @@
package jawnae.pyronet;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
@ -27,14 +26,11 @@ import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import jawnae.pyronet.events.PyroSelectorListener;
public class PyroSelector {
public static boolean DO_NOT_CHECK_NETWORK_THREAD = true;
@ -46,14 +42,7 @@ public class PyroSelector {
final ByteBuffer networkBuffer;
final PyroSelectorListener listener;
public PyroSelector() {
this(null);
}
public PyroSelector(PyroSelectorListener listener) {
this.listener = listener;
this.networkBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
try {
@ -111,28 +100,6 @@ public class PyroSelector {
}
}
public PyroServer listen(InetSocketAddress end, int backlog)
throws IOException {
try {
return new PyroServer(this, nioSelector, end, backlog);
} catch (IOException exc) {
if (this.listener == null)
throw exc;
this.listener.serverBindFailed(exc);
return null;
}
}
public PyroServer listen(InetSocketAddress end) throws IOException {
return this.listen(end, 50);
}
public PyroServer listen(int port) throws IOException {
return this.listen(new InetSocketAddress(InetAddress.getLocalHost(),
port));
}
public PyroClient connect(InetSocketAddress host) throws IOException {
return this.connect(host, null);
}
@ -142,11 +109,7 @@ public class PyroSelector {
try {
return new PyroClient(this, bind, host);
} catch (IOException exc) {
if (this.listener == null)
throw exc;
this.listener.clientBindFailed(exc);
return null;
throw exc;
}
}
@ -173,16 +136,10 @@ public class PyroSelector {
if (task == null)
break;
if (this.listener != null)
this.listener.executingTask(task);
try {
task.run();
} catch (Throwable cause) {
if (this.listener != null)
this.listener.taskCrashed(task, cause);
else
cause.printStackTrace();
cause.printStackTrace();
}
}
}
@ -192,15 +149,9 @@ public class PyroSelector {
try {
selected = nioSelector.select(timeout);
} catch (IOException exc) {
if (this.listener != null)
this.listener.selectFailure(exc);
else
exc.printStackTrace();
exc.printStackTrace();
return;
}
if (this.listener != null)
this.listener.selectedKeys(selected);
}
private final void handleSelectedKeys(long now) {
@ -210,17 +161,8 @@ public class PyroSelector {
SelectionKey key = keys.next();
keys.remove();
if (key.channel() instanceof ServerSocketChannel) {
PyroServer server = (PyroServer) key.attachment();
if (this.listener != null)
this.listener.serverSelected(server);
server.onInterestOp();
}
if (key.channel() instanceof SocketChannel) {
PyroClient client = (PyroClient) key.attachment();
if (this.listener != null)
this.listener.clientSelected(client, key.readyOps());
client.onInterestOp(now);
}
}

View File

@ -1,224 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import jawnae.pyronet.addon.PyroSelectorProvider;
import jawnae.pyronet.events.PyroServerListener;
public class PyroServer implements Iterable<PyroClient> {
private final PyroSelector selector;
public final SelectionKey serverKey;
final List<PyroClient> clients;
PyroServer(PyroSelector selector, Selector nioSelector,
InetSocketAddress endpoint, int backlog) throws IOException {
this.selector = selector;
this.selector.checkThread();
ServerSocketChannel ssc;
ssc = ServerSocketChannel.open();
ssc.socket().bind(endpoint, backlog);
ssc.configureBlocking(false);
this.serverKey = ssc.register(nioSelector, SelectionKey.OP_ACCEPT);
this.serverKey.attach(this);
this.clients = new ArrayList<PyroClient>();
this.listeners = new CopyOnWriteArrayList<PyroServerListener>();
}
//
private final List<PyroServerListener> listeners;
public void addListener(PyroServerListener listener) {
this.selector.checkThread();
this.listeners.add(listener);
}
public void removeListener(PyroServerListener listener) {
this.selector.checkThread();
this.listeners.remove(listener);
}
public void removeListeners() {
this.selector.checkThread();
this.listeners.clear();
}
/**
* Returns the network that created this server
*/
public PyroSelector selector() {
return this.selector;
}
private PyroSelectorProvider selectorProvider;
/**
* By installing a PyroSelectorProvider you alter the PyroSelector used to
* do the I/O of a PyroClient. This can be used for multi-threading your
* network code
*/
public void installSelectorProvider(PyroSelectorProvider selectorProvider) {
this.selector().checkThread();
this.selectorProvider = selectorProvider;
}
void onInterestOp() {
if (!serverKey.isValid())
throw new PyroException("invalid selection key");
try {
if (serverKey.isAcceptable()) {
this.onReadyToAccept();
}
} catch (IOException exc) {
throw new IllegalStateException(exc);
}
}
/**
* Returns an iterator to access all connected clients of this server
*/
@Override
public Iterator<PyroClient> iterator() {
this.selector.checkThread();
List<PyroClient> copy = new ArrayList<PyroClient>();
copy.addAll(this.clients);
return copy.iterator();
}
/**
* Closes the server socket. Any current connections will continue.
*/
public void close() throws IOException {
this.selector.checkThread();
this.serverKey.channel().close();
}
/**
* Closes the server socket. Any current connections will be closed.
*/
public void terminate() throws IOException {
this.close();
for (PyroClient client: this) {
client.dropConnection();
}
}
private void onReadyToAccept() throws IOException {
this.selector.checkThread();
final SocketChannel channel = ((ServerSocketChannel) serverKey
.channel()).accept();
final PyroSelector acceptedClientSelector;
{
if (this.selectorProvider == null)
acceptedClientSelector = this.selector;
else
acceptedClientSelector = this.selectorProvider
.provideFor(channel);
}
if (acceptedClientSelector == this.selector) {
SelectionKey clientKey = PyroClient.configure(
acceptedClientSelector, channel, false);
PyroClient client = new PyroClient(acceptedClientSelector, this,
clientKey);
this.fireAcceptedClient(client);
this.clients.add(client);
} else {
// create client in PyroClient-selector thread
acceptedClientSelector.scheduleTask(new Runnable() {
@Override
public void run() {
SelectionKey clientKey;
try {
clientKey = PyroClient.configure(
acceptedClientSelector, channel, false);
} catch (IOException exc) {
throw new IllegalStateException(exc);
}
final PyroClient client = new PyroClient(
acceptedClientSelector, PyroServer.this, clientKey);
PyroServer.this.fireAcceptedClient(client);
// add client to list in PyroServer-selector thread
PyroServer.this.selector().scheduleTask(new Runnable() {
@Override
public void run() {
PyroServer.this.clients.add(client);
}
});
PyroServer.this.selector().wakeup();
}
});
acceptedClientSelector.wakeup();
}
}
void fireAcceptedClient(PyroClient client) {
for (PyroServerListener listener: this.listeners) {
listener.acceptedClient(client);
}
}
void onDisconnect(final PyroClient client) {
if (this.selector().isNetworkThread()) {
this.clients.remove(client);
} else {
// we are in the PyroClient-selector thread
this.selector().scheduleTask(new Runnable() {
@Override
public void run() {
// call again from the PyroServer-selector thread
PyroServer.this.onDisconnect(client);
}
});
this.selector().wakeup();
}
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import jawnae.pyronet.PyroSelector;
public class PyroRoundrobinSelectorProvider implements PyroSelectorProvider {
private final PyroSelector[] selectors;
private int index;
public PyroRoundrobinSelectorProvider(PyroSelector[] selectors) {
this.selectors = Arrays.copyOf(selectors, selectors.length);
}
@Override
public PyroSelector provideFor(SocketChannel channel) {
// this is called from the PyroServer-selector thread
return this.selectors[this.index++ % this.selectors.length];
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import jawnae.pyronet.PyroSelector;
public interface PyroSelectorProvider {
public PyroSelector provideFor(SocketChannel channel);
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.addon;
import java.nio.channels.SocketChannel;
import jawnae.pyronet.PyroSelector;
public class PyroSingletonSelectorProvider implements PyroSelectorProvider {
private final PyroSelector selector;
public PyroSingletonSelectorProvider(PyroSelector selector) {
this.selector = selector;
}
@Override
public PyroSelector provideFor(SocketChannel channel) {
return this.selector;
}
}

View File

@ -1,111 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public class PyroLazyBastardAdapter implements PyroSelectorListener,
PyroServerListener, PyroClientListener {
// --------------- PyroSelectorListener
public void executingTask(Runnable task) {
//
}
public void taskCrashed(Runnable task, Throwable cause) {
System.out.println(this.getClass().getSimpleName()
+ ".taskCrashed() caught exception:");
cause.printStackTrace();
}
public void selectedKeys(int count) {
//
}
public void selectFailure(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".selectFailure() caught exception:");
cause.printStackTrace();
}
public void serverSelected(PyroServer server) {
//
}
public void clientSelected(PyroClient client, int readyOps) {
//
}
// ------------- PyroServerListener
public void acceptedClient(PyroClient client) {
//
}
// ------------- PyroClientListener
public void connectedClient(PyroClient client) {
//
}
public void unconnectableClient(PyroClient client) {
System.out.println(this.getClass().getSimpleName()
+ ".unconnectableClient()");
}
public void droppedClient(PyroClient client, IOException cause) {
if (cause != null && !(cause instanceof EOFException)) {
System.out.println(this.getClass().getSimpleName()
+ ".droppedClient() caught exception: " + cause);
}
}
public void disconnectedClient(PyroClient client) {
//
}
//
public void receivedData(PyroClient client, ByteBuffer data) {
//
}
public void sentData(PyroClient client, int bytes) {
//
}
@Override
public void serverBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception:");
cause.printStackTrace();
}
@Override
public void clientBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception:");
cause.printStackTrace();
}
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public class PyroSelectorAdapter implements PyroSelectorListener {
public void executingTask(Runnable task) {
//
}
public void taskCrashed(Runnable task, Throwable cause) {
System.out.println(this.getClass().getSimpleName()
+ " caught exception: " + cause);
}
//
public void selectedKeys(int count) {
//
}
public void selectFailure(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ " caught exception: " + cause);
}
//
public void serverSelected(PyroServer server) {
//
}
public void clientSelected(PyroClient client, int readyOps) {
//
}
//
@Override
public void serverBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception: " + cause);
}
@Override
public void clientBindFailed(IOException cause) {
System.out.println(this.getClass().getSimpleName()
+ ".serverBindFailed() caught exception: " + cause);
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import java.io.IOException;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroServer;
public interface PyroSelectorListener {
public void executingTask(Runnable task);
public void taskCrashed(Runnable task, Throwable cause);
//
public void selectedKeys(int count);
public void selectFailure(IOException cause);
//
public void serverSelected(PyroServer server);
public void clientSelected(PyroClient client, int readyOps);
//
public void serverBindFailed(IOException cause);
public void clientBindFailed(IOException cause);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import jawnae.pyronet.PyroClient;
public class PyroServerAdapter implements PyroServerListener {
@Override
public void acceptedClient(PyroClient client) {
//
}
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.events;
import jawnae.pyronet.PyroClient;
public interface PyroServerListener {
/**
* Note: invoked from the PyroSelector-thread that created this PyroClient
*/
public void acceptedClient(PyroClient client);
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public interface ByteSink {
public static int FEED_ACCEPTED = 1;
public static int FEED_ACCEPTED_LAST = 2;
public static int FEED_REJECTED = 3;
/**
* determines what to do with the specified byte: accept, accept as final
* byte, reject
*/
public int feed(byte b);
/**
* Resets the state of this ByteSink, allowing it to be enqueued again
*/
public void reset();
/**
* Called by the client when this ByteSink is complete
*/
public void onReady(ByteBuffer buffer);
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public abstract class ByteSinkEndsWith implements ByteSink {
private final ByteBuffer result;
private final byte[] endsWith;
private final boolean includeEndsWith;
private int matchCount;
private int filled;
public ByteSinkEndsWith(byte[] endsWith, int capacity,
boolean includeEndsWith) {
if (endsWith == null || endsWith.length == 0)
throw new IllegalStateException();
this.result = ByteBuffer.allocate(capacity);
this.endsWith = endsWith;
this.includeEndsWith = includeEndsWith;
this.reset();
}
@Override
public void reset() {
this.result.clear();
this.matchCount = 0;
this.filled = 0;
}
@Override
public int feed(byte b) {
if (this.endsWith[this.matchCount] == b) {
this.matchCount++;
} else {
this.matchCount = 0;
}
this.result.put(this.filled, b);
this.filled += 1;
if (this.matchCount == this.endsWith.length) {
int len = this.filled
- (this.includeEndsWith ? 0 : this.endsWith.length);
this.result.limit(len);
this.onReady(this.result);
return FEED_ACCEPTED_LAST;
}
return ByteSink.FEED_ACCEPTED;
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
public abstract class ByteSinkLength implements ByteSink {
private final ByteBuffer result;
private int filled;
public ByteSinkLength(int size) {
if (size == 0)
throw new IllegalArgumentException();
this.result = ByteBuffer.allocate(size);
this.reset();
}
@Override
public void reset() {
this.result.clear();
this.filled = 0;
}
@Override
public int feed(byte b) {
this.result.put(this.filled, b);
this.filled += 1;
if (this.filled == this.result.capacity()) {
this.onReady(this.result);
return FEED_ACCEPTED_LAST;
}
return ByteSink.FEED_ACCEPTED;
}
}

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket16 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
if (payload.length > 0x0000FFFF) {
throw new IllegalStateException("packet bigger than 64K-1 bytes");
}
byte[] wrapped = new byte[2 + payload.length];
wrapped[0] = (byte) (payload.length >> 8);
wrapped[1] = (byte) (payload.length >> 0);
System.arraycopy(payload, 0, wrapped, 2, payload.length);
client.write(client.selector().malloc(wrapped));
}
//
ByteSinkLength current;
public ByteSinkPacket16() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(2) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = buffer.getShort(0) & 0xFFFF;
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket16.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket16.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
}
else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View File

@ -1,94 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket24 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
if (payload.length > 0x00FFFFFF) {
throw new IllegalStateException("packet bigger than 16M-1 bytes");
}
byte[] wrapped = new byte[3 + payload.length];
wrapped[0] = (byte) (payload.length >> 16);
wrapped[1] = (byte) (payload.length >> 8);
wrapped[2] = (byte) (payload.length >> 0);
System.arraycopy(payload, 0, wrapped, 3, payload.length);
client.write(client.selector().malloc(wrapped));
}
//
ByteSinkLength current;
public ByteSinkPacket24() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(3) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = ((buffer.getShort(0) & 0xFFFF) << 8)
| (buffer.get(3) & 0xFF);
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket24.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket24.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
} else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import jawnae.pyronet.PyroClient;
public abstract class ByteSinkPacket32 implements ByteSink {
public static void sendTo(PyroClient client, byte[] payload) {
boolean isExtreme = (payload.length > 0xFFFFFFFF - 4);
byte[] wrapped = new byte[4 + (isExtreme ? 0 : payload.length)];
wrapped[0] = (byte) (payload.length >> 24);
wrapped[1] = (byte) (payload.length >> 16);
wrapped[2] = (byte) (payload.length >> 8);
wrapped[3] = (byte) (payload.length >> 0);
if (!isExtreme) {
System.arraycopy(payload, 0, wrapped, 4, payload.length);
}
client.write(client.selector().malloc(wrapped));
if (isExtreme) {
client.write(client.selector().malloc(payload));
}
}
//
ByteSinkLength current;
public ByteSinkPacket32() {
this.reset();
}
@Override
public void reset() {
this.current = new ByteSinkLength(4) {
@Override
public void onReady(ByteBuffer buffer) {
// header is received
int len = buffer.getInt(0);
current = new ByteSinkLength(len) {
@Override
public void onReady(ByteBuffer buffer) {
// sometime we want do reset in
// ByteSinkPacket24.this.onReady, then add the sink back
// to feeder, in such process, onReady should be execute
// at last.
current = null;
// content is received
ByteSinkPacket32.this.onReady(buffer);
}
};
}
};
}
@Override
public int feed(byte b) {
if (this.current == null) {
throw new IllegalStateException();
}
int result = this.current.feed(b);
if (result == FEED_ACCEPTED) {
return result;
}
// 'current' will be replaced by now
if (this.current == null) {
return result;
}
else {
return FEED_ACCEPTED;
}
// return this.current.feed(b);
}
}

View File

@ -1,119 +0,0 @@
/*
* Copyright (c) 2008, https://code.google.com/p/pyronet/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jawnae.pyronet.traffic;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroSelector;
import jawnae.pyronet.events.PyroClientAdapter;
public class PyroByteSinkFeeder extends PyroClientAdapter {
private final PyroSelector selector;
private final ByteStream inbound;
private final LinkedList<ByteSink> sinks;
public PyroByteSinkFeeder(PyroClient client) {
this(client.selector());
}
public PyroByteSinkFeeder(PyroSelector selector) {
this(selector, 8 * 1024);
}
public PyroByteSinkFeeder(PyroSelector selector, int bufferSize) {
this.selector = selector;
this.inbound = new ByteStream();
this.sinks = new LinkedList<ByteSink>();
}
//
@Override
public void receivedData(PyroClient client, ByteBuffer data) {
this.feed(data);
}
//
public ByteBuffer shutdown() {
int bytes = this.inbound.getByteCount();
ByteBuffer tmp = this.selector.malloc(bytes);
this.inbound.get(tmp);
this.inbound.discard(bytes);
tmp.flip();
return tmp;
}
public void addByteSink(ByteSink sink) {
this.selector.checkThread();
this.register(sink);
}
public void feed(ByteBuffer data) {
ByteBuffer copy = this.selector.copy(data);
this.inbound.append(copy);
this.fill();
}
final void register(ByteSink sink) {
this.sinks.addLast(sink);
this.fill();
}
private final void fill() {
if (this.sinks.isEmpty()) {
return;
}
ByteSink currentSink = this.sinks.removeFirst();
while (currentSink != null && inbound.hasData()) {
switch (currentSink.feed(inbound.read())) {
case ByteSink.FEED_ACCEPTED:
continue; // continue to next feed
case ByteSink.FEED_ACCEPTED_LAST:
break; // break out switch, not while
case ByteSink.FEED_REJECTED:
break; // break out switch, not while
}
if (this.sinks.isEmpty()) {
currentSink = null;
break;
}
currentSink = this.sinks.removeFirst();
}
if (currentSink != null) {
this.sinks.addFirst(currentSink);
}
}
}

View File

@ -36,6 +36,7 @@ import java.util.Locale;
public class PhoneFormat {
public byte[] data;
private boolean initialzed = false;
public ByteBuffer buffer;
public String defaultCountry;
public String defaultCallingCode;
@ -90,6 +91,7 @@ public class PhoneFormat {
buffer.order(ByteOrder.LITTLE_ENDIAN);
} catch (Exception e) {
e.printStackTrace();
return;
}
if (countryCode != null && countryCode.length() != 0) {
@ -104,6 +106,7 @@ public class PhoneFormat {
countryCallingCode = new HashMap<String, String>(255);
parseDataHeader();
initialzed = true;
}
public String defaultCallingCode() {
@ -139,6 +142,9 @@ public class PhoneFormat {
}
public String format(String orig) {
if (!initialzed) {
return orig;
}
String str = strip(orig);
if (str.startsWith("+")) {
@ -177,6 +183,9 @@ public class PhoneFormat {
}
public boolean isPhoneNumberValid(String phoneNumber) {
if (!initialzed) {
return true;
}
String str = strip(phoneNumber);
if (str.startsWith("+")) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,7 +8,7 @@
package org.telegram.SQLite;
import android.util.Log;
import org.telegram.messenger.FileLog;
public class SQLiteCursor {
@ -83,14 +83,14 @@ public class SQLiteCursor {
int repeatCount = 6;
while (repeatCount-- != 0) {
try {
Log.e("tmessages", "sqlite busy, waiting...");
FileLog.e("tmessages", "sqlite busy, waiting...");
Thread.sleep(500);
res = preparedStatement.step();
if (res == 0) {
break;
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
if (res == -1) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,11 +8,12 @@
package org.telegram.SQLite;
import org.telegram.messenger.FileLog;
import org.telegram.ui.ApplicationLoader;
import java.util.HashMap;
import java.util.Map;
import android.util.Log;
public class SQLiteDatabase {
private final int sqliteHandle;
@ -25,7 +26,7 @@ public class SQLiteDatabase {
}
public SQLiteDatabase(String fileName) throws SQLiteException {
sqliteHandle = opendb(fileName);
sqliteHandle = opendb(fileName, ApplicationLoader.applicationContext.getFilesDir().getPath());
isOpen = true;
preparedMap = new HashMap<String, SQLitePreparedStatement>();
}
@ -111,7 +112,7 @@ public class SQLiteDatabase {
}
closedb(sqliteHandle);
} catch (SQLiteException e) {
Log.e("tmessages", e.getMessage(), e);
FileLog.e("tmessages", e.getMessage(), e);
}
isOpen = false;
}
@ -142,7 +143,7 @@ public class SQLiteDatabase {
commitTransaction(sqliteHandle);
}
native int opendb(String fileName) throws SQLiteException;
native int opendb(String fileName, String tempDir) throws SQLiteException;
native void closedb(int sqliteHandle) throws SQLiteException;
native void beginTransaction(int sqliteHandle);
native void commitTransaction(int sqliteHandle);

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,7 +8,7 @@
package org.telegram.SQLite;
import android.util.Log;
import org.telegram.messenger.FileLog;
public class SQLitePreparedStatement {
private boolean isFinalized = false;
@ -90,7 +90,7 @@ public class SQLitePreparedStatement {
isFinalized = true;
finalize(sqliteStatementHandle);
} catch (SQLiteException e) {
Log.e("tmessages", e.getMessage(), e);
FileLog.e("tmessages", e.getMessage(), e);
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,9 +8,7 @@
package org.telegram.TL;
import android.util.Log;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.SerializedData;
import java.util.HashMap;
@ -373,6 +371,10 @@ public class TLClassStore {
classStore.put(TLRPC.TL_messages_sendEncryptedFile.constructor, TLRPC.TL_messages_sendEncryptedFile.class);
classStore.put(TLRPC.TL_messages_sendEncryptedService.constructor, TLRPC.TL_messages_sendEncryptedService.class);
classStore.put(TLRPC.TL_messages_receivedQueue.constructor, TLRPC.TL_messages_receivedQueue.class);
classStore.put(TLRPC.TL_upload_saveBigFilePart.constructor, TLRPC.TL_upload_saveBigFilePart.class);
classStore.put(TLRPC.TL_inputEncryptedFileBigUploaded.constructor, TLRPC.TL_inputEncryptedFileBigUploaded.class);
classStore.put(TLRPC.TL_inputFileBig.constructor, TLRPC.TL_inputFileBig.class);
classStore.put(TLRPC.TL_messageMediaUnsupported.constructor, TLRPC.TL_messageMediaUnsupported.class);
classStore.put(TLRPC.TL_msg_container.constructor, TLRPC.TL_msg_container.class);
classStore.put(TLRPC.TL_fileEncryptedLocation.constructor, TLRPC.TL_fileEncryptedLocation.class);
@ -381,6 +383,9 @@ public class TLClassStore {
classStore.put(TLRPC.TL_gzip_packed.constructor, TLRPC.TL_gzip_packed.class);
classStore.put(TLRPC.Vector.constructor, TLRPC.Vector.class);
classStore.put(TLRPC.TL_userProfilePhotoOld.constructor, TLRPC.TL_userProfilePhotoOld.class);
classStore.put(TLRPC.TL_messageActionUserUpdatedPhoto.constructor, TLRPC.TL_messageActionUserUpdatedPhoto.class);
classStore.put(TLRPC.TL_messageActionUserJoined.constructor, TLRPC.TL_messageActionUserJoined.class);
classStore.put(TLRPC.TL_messageActionLoginUnknownLocation.constructor, TLRPC.TL_messageActionLoginUnknownLocation.class);
}
static TLClassStore store = null;
@ -419,16 +424,14 @@ public class TLClassStore {
}
return response;
} catch (IllegalAccessException e) {
Log.e("tmessages", "can't create class");
FileLog.e("tmessages", "can't create class");
return null;
} catch (InstantiationException e2) {
Log.e("tmessages", "can't create class");
FileLog.e("tmessages", "can't create class");
return null;
}
} else {
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", String.format("unknown class %x", constructor));
}
FileLog.e("tmessages", String.format("unknown class %x", constructor));
return null;
//throw new RuntimeException(String.format("unknown class %x", constructor));
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -813,6 +813,7 @@ public class TLRPC {
public String phone_number;
public String first_name;
public String last_name;
public byte[] bytes;
public int user_id;
}
@ -887,6 +888,19 @@ public class TLRPC {
}
}
public static class TL_messageMediaUnsupported extends MessageMedia {
public static int constructor = 0x29632a36;
public void readParams(SerializedData stream) {
bytes = stream.readByteArray();
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeByteArray(bytes);
}
}
public static class TL_auth_sentCode extends TLObject {
public static int constructor = 0x2215bcbd;
@ -2011,7 +2025,6 @@ public class TLRPC {
public static class TL_messageActionChatEditPhoto extends MessageAction {
public static int constructor = 0x7fcb13a8;
public void readParams(SerializedData stream) {
photo = (Photo)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
@ -2463,12 +2476,12 @@ public class TLRPC {
}
public static class InputMedia extends TLObject {
public TL_inputFile file;
public InputFile file;
public InputGeoPoint geo_point;
public String phone_number;
public String first_name;
public String last_name;
public TL_inputFile thumb;
public InputFile thumb;
public int duration;
public int w;
public int h;
@ -2479,7 +2492,7 @@ public class TLRPC {
public void readParams(SerializedData stream) {
file = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
file = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(SerializedData stream) {
@ -2540,8 +2553,8 @@ public class TLRPC {
public void readParams(SerializedData stream) {
file = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
thumb = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
file = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
thumb = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
duration = stream.readInt32();
w = stream.readInt32();
h = stream.readInt32();
@ -2562,7 +2575,7 @@ public class TLRPC {
public void readParams(SerializedData stream) {
file = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
file = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
duration = stream.readInt32();
w = stream.readInt32();
h = stream.readInt32();
@ -3408,6 +3421,24 @@ public class TLRPC {
}
}
public static class TL_inputEncryptedFileBigUploaded extends InputEncryptedFile {
public static int constructor = 0x2dc173c8;
public void readParams(SerializedData stream) {
id = stream.readInt64();
parts = stream.readInt32();
key_fingerprint = stream.readInt32();
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(id);
stream.writeInt32(parts);
stream.writeInt32(key_fingerprint);
}
}
public static class TL_inputEncryptedFileEmpty extends InputEncryptedFile {
public static int constructor = 0x1837c364;
@ -3437,6 +3468,34 @@ public class TLRPC {
}
}
public static class TL_upload_saveBigFilePart extends TLObject {
public static int constructor = 0xde7b673d;
public long file_id;
public int file_part;
public int file_total_parts;
public byte[] bytes;
public Class responseClass () {
return Bool.class;
}
public void readParams(SerializedData stream) {
file_id = stream.readInt64();
file_part = stream.readInt32();
file_total_parts = stream.readInt32();
bytes = stream.readByteArray();
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(file_id);
stream.writeInt32(file_part);
stream.writeInt32(file_total_parts);
stream.writeByteArray(bytes);
}
}
public static class contacts_MyLink extends TLObject {
public boolean contact;
}
@ -4582,13 +4641,15 @@ public class TLRPC {
}
}
public static class TL_inputFile extends TLObject {
public static int constructor = 0xf52ff27f;
public static class InputFile extends TLObject {
public long id;
public int parts;
public String name;
public String md5_checksum;
}
public static class TL_inputFile extends InputFile {
public static int constructor = 0xf52ff27f;
public void readParams(SerializedData stream) {
id = stream.readInt64();
@ -4606,6 +4667,24 @@ public class TLRPC {
}
}
public static class TL_inputFileBig extends InputFile {
public static int constructor = 0xfa4f0bb5;
public void readParams(SerializedData stream) {
id = stream.readInt64();
parts = stream.readInt32();
name = stream.readString();
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(id);
stream.writeInt32(parts);
stream.writeString(name);
}
}
public static class messages_StatedMessage extends TLObject {
public Message message;
public ArrayList<Chat> chats = new ArrayList<Chat>();
@ -5139,7 +5218,7 @@ public class TLRPC {
public static class InputChatPhoto extends TLObject {
public InputPhoto id;
public InputPhotoCrop crop;
public TL_inputFile file;
public InputFile file;
}
public static class TL_inputChatPhoto extends InputChatPhoto {
@ -5172,7 +5251,7 @@ public class TLRPC {
public void readParams(SerializedData stream) {
file = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
file = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
crop = (InputPhotoCrop)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
@ -6661,7 +6740,7 @@ public class TLRPC {
public static class TL_photos_uploadProfilePhoto extends TLObject {
public static int constructor = 0xd50f9c88;
public TL_inputFile file;
public InputFile file;
public String caption;
public InputGeoPoint geo_point;
public InputPhotoCrop crop;
@ -6671,7 +6750,7 @@ public class TLRPC {
}
public void readParams(SerializedData stream) {
file = (TL_inputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
file = (InputFile)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
caption = stream.readString();
geo_point = (InputGeoPoint)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
crop = (InputPhotoCrop)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -7949,6 +8028,7 @@ public class TLRPC {
public int unread_count;
public int last_message_date;
public long id;
public int last_read;
public void readParams(SerializedData stream) {
peer = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
@ -8032,6 +8112,7 @@ public class TLRPC {
public static class MessageAction extends TLObject {
public Photo photo;
public UserProfilePhoto newUserPhoto;
public int user_id;
public String title;
public ArrayList<Integer> users = new ArrayList<Integer>();
@ -8090,6 +8171,46 @@ public class TLRPC {
}
}
public static class TL_messageActionUserUpdatedPhoto extends MessageAction {
public static int constructor = 0x55555551;
public void readParams(SerializedData stream) {
newUserPhoto = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
newUserPhoto.serializeToStream(stream);
}
}
public static class TL_messageActionUserJoined extends MessageAction {
public static int constructor = 0x55555550;
public void readParams(SerializedData stream) {
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
}
}
public static class TL_messageActionLoginUnknownLocation extends MessageAction {
public static int constructor = 0x555555F5;
public void readParams(SerializedData stream) {
title = stream.readString();
address = stream.readString();
}
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(title);
stream.writeString(address);
}
}
public static class invokeWithLayer8 extends TLObject {
public static int constructor = 0xe9abd9fd;
@ -8101,6 +8222,38 @@ public class TLRPC {
}
}
public static class invokeWithLayer9 extends TLObject {
public static int constructor = 0x76715a63;
public TLObject query;
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
query.serializeToStream(stream);
}
}
public static class initConnection extends TLObject {
public static int constructor = 0x69796de9;
public int api_id;
public String device_model;
public String system_version;
public String app_version;
public String lang_code;
public TLObject query;
public void serializeToStream(SerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(api_id);
stream.writeString(device_model);
stream.writeString(system_version);
stream.writeString(app_version);
stream.writeString(lang_code);
query.serializeToStream(stream);
}
}
public static class decryptedMessageLayer extends TLObject {
public static int constructor = 0x99a438cf;

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -13,13 +13,11 @@ import android.accounts.OperationCanceledException;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class ContactsSyncAdapterService extends Service {
private static SyncAdapterImpl sSyncAdapter = null;
@ -41,7 +39,7 @@ public class ContactsSyncAdapterService extends Service {
try {
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
}
@ -60,6 +58,6 @@ public class ContactsSyncAdapterService extends Service {
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
Log.i("telegram", "performSync: " + account.toString());
FileLog.d("telegram", "performSync: " + account.toString());
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,24 +8,32 @@
package org.telegram.messenger;
import android.util.Log;
import android.content.Context;
import android.content.SharedPreferences;
import org.telegram.TL.TLRPC;
import org.telegram.ui.ApplicationLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
public class Datacenter {
private final int DATA_VERSION = 2;
public int datacenterId;
public String address;
public int port;
public ArrayList<String> addresses = new ArrayList<String>();
public HashMap<String, Integer> ports = new HashMap<String, Integer>();
public int[] defaultPorts = new int[] {-1, 80, -1, 88, -1, 443, -1, 80, -1, 443, -1};
public boolean authorized;
public long authSessionId;
public long authDownloadSessionId;
public long authUploadSessionId;
public byte[] authKey;
public byte[] authKeyId;
private volatile int currentPortNum = 0;
private volatile int currentAddressNum = 0;
public TcpConnection connection;
public TcpConnection downloadConnection;
@ -37,39 +45,148 @@ public class Datacenter {
authServerSaltSet = new ArrayList<ServerSalt>();
}
public Datacenter(SerializedData data) {
datacenterId = data.readInt32();
address = data.readString();
port = data.readInt32();
if (port == 25) {
port = 443;
}
int len = data.readInt32();
if (len != 0) {
authKey = data.readData(len);
}
len = data.readInt32();
if (len != 0) {
authKeyId = data.readData(len);
}
authorized = data.readInt32() != 0;
len = data.readInt32();
for (int a = 0; a < len; a++) {
ServerSalt salt = new ServerSalt();
salt.validSince = data.readInt32();
salt.validUntil = data.readInt32();
salt.value = data.readInt64();
if (authServerSaltSet == null) {
authServerSaltSet = new ArrayList<ServerSalt>();
public Datacenter(SerializedData data, int version) {
if (version == 0) {
datacenterId = data.readInt32();
String address = data.readString();
addresses.add(address);
int port = data.readInt32();
ports.put(address, port);
int len = data.readInt32();
if (len != 0) {
authKey = data.readData(len);
}
authServerSaltSet.add(salt);
len = data.readInt32();
if (len != 0) {
authKeyId = data.readData(len);
}
authorized = data.readInt32() != 0;
len = data.readInt32();
for (int a = 0; a < len; a++) {
ServerSalt salt = new ServerSalt();
salt.validSince = data.readInt32();
salt.validUntil = data.readInt32();
salt.value = data.readInt64();
if (authServerSaltSet == null) {
authServerSaltSet = new ArrayList<ServerSalt>();
}
authServerSaltSet.add(salt);
}
} else if (version == 1) {
int currentVersion = data.readInt32();
if (currentVersion == 2) {
datacenterId = data.readInt32();
int len = data.readInt32();
for (int a = 0; a < len; a++) {
String address = data.readString();
addresses.add(address);
ports.put(address, data.readInt32());
}
len = data.readInt32();
if (len != 0) {
authKey = data.readData(len);
}
len = data.readInt32();
if (len != 0) {
authKeyId = data.readData(len);
}
authorized = data.readInt32() != 0;
len = data.readInt32();
for (int a = 0; a < len; a++) {
ServerSalt salt = new ServerSalt();
salt.validSince = data.readInt32();
salt.validUntil = data.readInt32();
salt.value = data.readInt64();
if (authServerSaltSet == null) {
authServerSaltSet = new ArrayList<ServerSalt>();
}
authServerSaltSet.add(salt);
}
}
}
readCurrentAddressAndPortNum();
}
public String getCurrentAddress() {
if (addresses.isEmpty()) {
return null;
}
if (currentAddressNum >= addresses.size()) {
currentAddressNum = 0;
}
return addresses.get(currentAddressNum);
}
public int getCurrentPort() {
if (ports.isEmpty()) {
return 443;
}
if (currentPortNum >= defaultPorts.length) {
currentPortNum = 0;
}
int port = defaultPorts[currentPortNum];
if (port == -1) {
String address = getCurrentAddress();
return ports.get(address);
}
return port;
}
public void addAddressAndPort(String address, int port) {
if (addresses.contains(address)) {
return;
}
addresses.add(address);
ports.put(address, port);
}
public void nextAddressOrPort() {
if (currentPortNum + 1 < defaultPorts.length) {
currentPortNum++;
} else {
if (currentAddressNum + 1 < addresses.size()) {
currentAddressNum++;
} else {
currentAddressNum = 0;
}
currentPortNum = 0;
}
}
public void storeCurrentAddressAndPortNum() {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("dc" + datacenterId + "port", currentPortNum);
editor.putInt("dc" + datacenterId + "address", currentAddressNum);
editor.commit();
}
});
}
private void readCurrentAddressAndPortNum() {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE);
currentPortNum = preferences.getInt("dc" + datacenterId + "port", 0);
currentAddressNum = preferences.getInt("dc" + datacenterId + "address", 0);
}
public void replaceAddressesAndPorts(ArrayList<String> newAddresses, HashMap<String, Integer> newPorts) {
addresses = newAddresses;
ports = newPorts;
}
public void SerializeToStream(SerializedData stream) {
stream.writeInt32(DATA_VERSION);
stream.writeInt32(datacenterId);
stream.writeString(address);
stream.writeInt32(port);
stream.writeInt32(addresses.size());
for (String address : addresses) {
stream.writeString(address);
stream.writeInt32(ports.get(address));
}
if (authKey != null) {
stream.writeInt32(authKey.length);
stream.writeRaw(authKey);
@ -129,10 +246,8 @@ public class Datacenter {
}
}
if (ConnectionsManager.DEBUG_VERSION) {
if (result == 0) {
Log.e("tmessages", "Valid salt not found", null);
}
if (result == 0) {
FileLog.e("tmessages", "Valid salt not found");
}
return result;

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -22,7 +22,6 @@ import android.text.Spannable;
import android.text.Spanned;
import android.text.style.DynamicDrawableSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@ -364,7 +363,7 @@ public class Emoji {
return color;
} catch(Throwable x) {
Log.e("tmessages", "Error loading emoji", x);
FileLog.e("tmessages", "Error loading emoji", x);
}
return null;
}
@ -396,7 +395,7 @@ public class Emoji {
public static Drawable getEmojiDrawable(long code){
DrawableInfo info = rects.get(code);
if(info == null){
Log.e("tmessages", "No emoji drawable for code " + String.format("%016X", code));
FileLog.e("tmessages", "No emoji drawable for code " + String.format("%016X", code));
return null;
}
EmojiDrawable ed = new EmojiDrawable(info);

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -961,20 +961,15 @@ public class FastDateFormat extends Format {
* @return <code>true</code> if equal
*/
public boolean equals(Object obj) {
if (obj instanceof FastDateFormat == false) {
if (!(obj instanceof FastDateFormat)) {
return false;
}
FastDateFormat other = (FastDateFormat) obj;
if (
(mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
(mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
(mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
(mTimeZoneForced == other.mTimeZoneForced) &&
(mLocaleForced == other.mLocaleForced)
) {
return true;
}
return false;
return (mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
(mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
(mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
(mTimeZoneForced == other.mTimeZoneForced) &&
(mLocaleForced == other.mLocaleForced);
}
/**

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -10,6 +10,7 @@ package org.telegram.messenger;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
@ -26,7 +27,7 @@ public class FileLoadOperation {
private int downloadChunkSize = 1024 * 32;
public int datacenter_id;
private TLRPC.InputFileLocation location;
public TLRPC.InputFileLocation location;
public volatile int state = 0;
private int downloadedBytes;
public int totalBytesCount;
@ -39,12 +40,14 @@ public class FileLoadOperation {
private File cacheFileTemp;
private File cacheFileFinal;
private File cacheIvTemp;
private String httpUrl;
private URLConnection httpConnection;
public boolean needBitmapCreate = true;
private InputStream httpConnectionStream;
private RandomAccessFile fileOutputStream;
RandomAccessFile fiv;
public static interface FileLoadOperationDelegate {
public abstract void didFinishLoadingFile(FileLoadOperation operation);
@ -98,10 +101,20 @@ public class FileLoadOperation {
return;
}
state = 1;
if (location == null && httpUrl == null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
return;
}
boolean ignoreCache = false;
boolean onlyCache = false;
String fileNameFinal;
String fileNameTemp;
String fileNameFinal = null;
String fileNameTemp = null;
String fileNameIv = null;
if (httpUrl != null) {
fileNameFinal = Utilities.MD5(httpUrl);
fileNameTemp = fileNameFinal + "_temp.jpg";
@ -109,6 +122,9 @@ public class FileLoadOperation {
} else if (location.volume_id != 0 && location.local_id != 0) {
fileNameTemp = location.volume_id + "_" + location.local_id + "_temp.jpg";
fileNameFinal = location.volume_id + "_" + location.local_id + ".jpg";
if (key != null) {
fileNameIv = location.volume_id + "_" + location.local_id + ".iv";
}
if (datacenter_id == Integer.MIN_VALUE || location.volume_id == Integer.MIN_VALUE) {
onlyCache = true;
}
@ -117,6 +133,9 @@ public class FileLoadOperation {
needBitmapCreate = false;
fileNameTemp = datacenter_id + "_" + location.id + "_temp.mp4";
fileNameFinal = datacenter_id + "_" + location.id + ".mp4";
if (key != null) {
fileNameIv = datacenter_id + "_" + location.id + ".iv";
}
}
boolean exist;
@ -174,7 +193,9 @@ public class FileLoadOperation {
float scaleFactor = bitmapW / w_filter;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int)w_filter, (int)(bitmapH / scaleFactor), true);
if (image != scaledBitmap) {
image.recycle();
if (Build.VERSION.SDK_INT < 11) {
image.recycle();
}
image = scaledBitmap;
}
}
@ -193,12 +214,13 @@ public class FileLoadOperation {
});
} catch (Exception e) {
cacheFileFinal.delete();
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
} else {
if (onlyCache) {
cleanup();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -212,6 +234,21 @@ public class FileLoadOperation {
downloadedBytes = (int)cacheFileTemp.length();
downloadedBytes = downloadedBytes / 1024 * 1024;
}
if (fileNameIv != null) {
cacheIvTemp = new File(Utilities.getCacheDir(), fileNameIv);
try {
fiv = new RandomAccessFile(cacheIvTemp, "rws");
long len = cacheIvTemp.length();
if (len > 0 && len % 32 == 0) {
fiv.read(iv, 0, 32);
} else {
downloadedBytes = 0;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
downloadedBytes = 0;
}
}
if (exist) {
cacheFileFinal.delete();
}
@ -221,15 +258,17 @@ public class FileLoadOperation {
fileOutputStream.seek(downloadedBytes);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
if (fileOutputStream == null) {
cleanup();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
return;
}
if (httpUrl != null) {
startDownloadHTTPRequest();
@ -244,28 +283,41 @@ public class FileLoadOperation {
return;
}
state = 2;
cleanup();
if (httpUrl == null && requestToken != 0) {
ConnectionsManager.Instance.cancelRpc(requestToken, true);
}
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
private void cleanup() {
if (httpUrl != null) {
try {
httpConnectionStream.close();
httpConnection = null;
httpConnectionStream = null;
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
} else {
if (fileOutputStream != null) {
try {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
fileOutputStream = null;
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
if (requestToken != 0) {
ConnectionsManager.Instance.cancelRpc(requestToken, true);
try {
if (fiv != null) {
fiv.close();
fiv = null;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
private void onFinishLoadingFile() throws Exception {
@ -273,8 +325,10 @@ public class FileLoadOperation {
return;
}
state = 3;
fileOutputStream.close();
fileOutputStream = null;
cleanup();
if (cacheIvTemp != null) {
cacheIvTemp.delete();
}
final boolean renamed = cacheFileTemp.renameTo(cacheFileFinal);
if (needBitmapCreate) {
@ -289,7 +343,7 @@ public class FileLoadOperation {
try {
Thread.sleep(delay);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
BitmapFactory.Options opts = new BitmapFactory.Options();
@ -328,7 +382,9 @@ public class FileLoadOperation {
float scaleFactor = bitmapW / w_filter;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true);
if (image != scaledBitmap) {
image.recycle();
if (Build.VERSION.SDK_INT < 11) {
image.recycle();
}
image = scaledBitmap;
}
}
@ -338,7 +394,7 @@ public class FileLoadOperation {
FileLoader.Instance.runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
delegate.didFinishLoadingFile(FileLoadOperation.this);
}
@ -361,7 +417,8 @@ public class FileLoadOperation {
httpConnection.connect();
httpConnectionStream = httpConnection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
cleanup();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -384,6 +441,7 @@ public class FileLoadOperation {
}
});
} else if (readed == -1) {
cleanup();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -395,6 +453,7 @@ public class FileLoadOperation {
}
});
} else {
cleanup();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -403,18 +462,14 @@ public class FileLoadOperation {
});
}
} catch (Exception e) {
e.printStackTrace();
cleanup();
FileLog.e("tmessages", e);
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
});
try {
httpConnectionStream.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
@ -424,8 +479,13 @@ public class FileLoadOperation {
}
TLRPC.TL_upload_getFile req = new TLRPC.TL_upload_getFile();
req.location = location;
req.offset = downloadedBytes;
req.limit = downloadChunkSize;
if (totalBytesCount == -1) {
req.offset = 0;
req.limit = 0;
} else {
req.offset = downloadedBytes;
req.limit = downloadChunkSize;
}
requestToken = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
@ -443,19 +503,24 @@ public class FileLoadOperation {
if (fileOutputStream != null) {
fileOutputStream.write(res.bytes);
}
if (fiv != null) {
fiv.seek(0);
fiv.write(iv);
}
downloadedBytes += res.bytes.length;
res.bytes = null;
if (totalBytesCount != 0) {
if (totalBytesCount > 0) {
delegate.didChangedLoadProgress(FileLoadOperation.this, Math.min(1.0f, (float)downloadedBytes / (float)totalBytesCount));
}
if (downloadedBytes % downloadChunkSize == 0 || totalBytesCount != 0 && totalBytesCount != downloadedBytes) {
if (downloadedBytes % downloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount != downloadedBytes) {
startDownloadRequest();
} else {
onFinishLoadingFile();
}
} catch (Exception e) {
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this);
e.printStackTrace();
FileLog.e("tmessages", e);
}
} else {
if (error.text.contains("FILE_MIGRATE_")) {
@ -469,6 +534,7 @@ public class FileLoadOperation {
val = null;
}
if (val == null) {
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this);
} else {
datacenter_id = val;
@ -479,13 +545,16 @@ public class FileLoadOperation {
try {
onFinishLoadingFile();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
} else {
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
} else {
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this);
}
}
@ -493,7 +562,11 @@ public class FileLoadOperation {
}, new RPCRequest.RPCProgressDelegate() {
@Override
public void progress(int length, int progress) {
if (totalBytesCount > 0) {
delegate.didChangedLoadProgress(FileLoadOperation.this, Math.min(1.0f, (float)(downloadedBytes + progress) / (float)totalBytesCount));
} else if (totalBytesCount == -1) {
delegate.didChangedLoadProgress(FileLoadOperation.this, Math.min(1.0f, (float)(progress) / (float)length));
}
}
}, null, true, RPCRequest.RPCRequestClassDownloadMedia, datacenter_id);
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,12 +8,13 @@
package org.telegram.messenger;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@ -37,16 +38,16 @@ public class FileLoader {
public LruCache memCache;
private String ignoreRemoval = null;
private HashMap<String, CacheImage> imageLoading;
private ConcurrentHashMap<String, CacheImage> imageLoading;
private HashMap<Integer, CacheImage> imageLoadingByKeys;
private Queue<FileLoadOperation> operationsQueue;
private Queue<FileLoadOperation> runningOperation;
private final int maxConcurentLoadingOpertaionsCount = 2;
private Queue<FileUploadOperation> uploadOperationQueue;
private HashMap<String, FileUploadOperation> uploadOperationPaths;
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPaths;
private int currentUploadOperationsCount = 0;
private Queue<FileLoadOperation> loadOperationQueue;
private HashMap<String, FileLoadOperation> loadOperationPaths;
private ConcurrentHashMap<String, FileLoadOperation> loadOperationPaths;
private int currentLoadOperationsCount = 0;
public static long lastCacheOutTime = 0;
public ConcurrentHashMap<String, Float> fileProgresses = new ConcurrentHashMap<String, Float>();
@ -109,20 +110,19 @@ public class FileLoader {
trackFree = cl.getMethod("trackExternalFree", new Class[] {long.class});
success = true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} catch (SecurityException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} catch (NoSuchMethodException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} catch (IllegalArgumentException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} catch (IllegalAccessException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} catch (InvocationTargetException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
if (!success) {
Log.i("tmessages", "VMRuntime hack does not work!");
runtime = null;
trackAllocation = null;
trackFree = null;
@ -216,6 +216,11 @@ public class FileLoader {
return false;
}
public void removeImage(String key) {
BitmapUseCounts.remove(key);
memCache.remove(key);
}
/*class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private CacheImage cacheImage;
private Bitmap bitmap;
@ -246,8 +251,8 @@ public class FileLoader {
}*/
public FileLoader() {
int maxMemory = (int)Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 10;
int cacheSize = Math.min(15, ((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass() / 7) * 1024 * 1024;
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (Build.VERSION.SDK_INT < 11) {
runtimeHack = new VMRuntimeHack();
@ -272,17 +277,21 @@ public class FileLoader {
if (runtimeHack != null) {
runtimeHack.trackAlloc(oldBitmap.getRowBytes() * oldBitmap.getHeight());
}
oldBitmap.recycle();
if (Build.VERSION.SDK_INT < 11) {
if (!oldBitmap.isRecycled()) {
oldBitmap.recycle();
}
}
}
}
};
imageLoading = new HashMap<String, CacheImage>();
imageLoading = new ConcurrentHashMap<String, CacheImage>();
imageLoadingByKeys = new HashMap<Integer, CacheImage>();
operationsQueue = new LinkedList<FileLoadOperation>();
runningOperation = new LinkedList<FileLoadOperation>();
uploadOperationQueue = new LinkedList<FileUploadOperation>();
uploadOperationPaths = new HashMap<String, FileUploadOperation>();
loadOperationPaths = new HashMap<String, FileLoadOperation>();
uploadOperationPaths = new ConcurrentHashMap<String, FileUploadOperation>();
loadOperationPaths = new ConcurrentHashMap<String, FileLoadOperation>();
loadOperationQueue = new LinkedList<FileLoadOperation>();
}
@ -311,8 +320,9 @@ public class FileLoader {
uploadOperationPaths.put(location, operation);
operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() {
@Override
public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.TL_inputFile inputFile, final TLRPC.TL_inputEncryptedFileUploaded inputEncryptedFile) {
public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile) {
NotificationCenter.Instance.postNotificationName(FileDidUpload, location, inputFile, inputEncryptedFile);
fileProgresses.remove(location);
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -400,6 +410,10 @@ public class FileLoader {
});
}
public boolean isLoadingFile(String fileName) {
return loadOperationPaths.containsKey(fileName);
}
public void loadFile(final TLRPC.Video video, final TLRPC.PhotoSize photo) {
Utilities.fileUploadQueue.postRunnable(new Runnable() {
@Override
@ -454,6 +468,7 @@ public class FileLoader {
}
}
});
fileProgresses.remove(arg1);
}
@Override
@ -628,14 +643,18 @@ public class FileLoader {
}
public void loadImage(final String url, final View imageView, final String filter, final boolean cancel) {
loadImage(null, url, imageView, filter, cancel);
loadImage(null, url, imageView, filter, cancel, 0);
}
public void loadImage(final TLRPC.FileLocation url, final View imageView, final String filter, final boolean cancel) {
loadImage(url, null, imageView, filter, cancel);
loadImage(url, null, imageView, filter, cancel, 0);
}
public void loadImage(final TLRPC.FileLocation url, final String httpUrl, final View imageView, final String filter, final boolean cancel) {
public void loadImage(final TLRPC.FileLocation url, final View imageView, final String filter, final boolean cancel, final int size) {
loadImage(url, null, imageView, filter, cancel, size);
}
public void loadImage(final TLRPC.FileLocation url, final String httpUrl, final View imageView, final String filter, final boolean cancel, final int size) {
if ((url == null && httpUrl == null) || imageView == null || (url != null && !(url instanceof TLRPC.TL_fileLocation) && !(url instanceof TLRPC.TL_fileEncryptedLocation))) {
return;
}
@ -700,20 +719,32 @@ public class FileLoader {
} else {
loadOperation = new FileLoadOperation(url);
}
loadOperation.totalBytesCount = size;
loadOperation.filter = filter;
loadOperation.delegate = new FileLoadOperation.FileLoadOperationDelegate() {
@Override
public void didFinishLoadingFile(final FileLoadOperation operation) {
enqueueImageProcessingOperationWithImage(operation.image, filter, arg2, img);
if (operation.totalBytesCount != 0) {
final String arg1 = operation.location.volume_id + "_" + operation.location.local_id + ".jpg";
fileProgresses.remove(arg1);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileLoadProgressChanged, arg1, 1.0f);
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileDidLoaded, arg1);
}
});
}
}
@Override
public void didFailedLoadingFile(final FileLoadOperation operation) {
if (url != null) {
if (url.volume_id != 0 && url.local_id != 0) {
fileProgresses.remove(url.volume_id + "_" + url.local_id + ".jpg");
}
}
Utilities.imageLoadQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -731,13 +762,36 @@ public class FileLoader {
img.callAndClear(null);
}
});
if (operation.totalBytesCount != 0) {
final String arg1 = operation.location.volume_id + "_" + operation.location.local_id + ".jpg";
fileProgresses.remove(arg1);
if (operation.state != 2) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileDidFailedLoad, arg1);
}
});
}
}
}
@Override
public void didChangedLoadProgress(FileLoadOperation operation, float progress) {
if (url != null) {
if (url.volume_id != 0 && url.local_id != 0) {
fileProgresses.put(url.volume_id + "_" + url.local_id + ".jpg", progress);
public void didChangedLoadProgress(FileLoadOperation operation, final float progress) {
if (operation.totalBytesCount != 0) {
final String arg1 = operation.location.volume_id + "_" + operation.location.local_id + ".jpg";
if (operation.state != 2) {
fileProgresses.put(arg1, progress);
}
long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 50) {
lastProgressUpdateTime = currentTime;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(FileLoadProgressChanged, arg1, progress);
}
});
}
}
}
@ -842,31 +896,7 @@ public class FileLoader {
}
});
}
/*AsyncTask
NSBlockOperation *processingOperation = [NSBlockOperation blockOperationWithBlock:^(void) {
if (countCores() == 1)
[NSThread sleepForTimeInterval:0.1];
UIImage *filterImage = [UIImage decodedImageWithImage:image andFilter:filter];
if (!filterImage)
filterImage = image;
dispatch_async(dispatch_get_main_queue(), ^{
if (filterImage) {
if (![memCache objectForKey:key]) {
[memCache setObject:filterImage forKey:key];
[memArray addObject:key];
}
}
for (UIView *view in img.imageViewArray) {
NSNumber *num = objc_getAssociatedObject(view, &VIEW_CACHE_KEY);
[imageLoadingByKeys removeObjectForKey:num];
}
[img callAndClear:filterImage];
[imageLoading removeObjectForKey:key];
});
}];
[imageProcessingQueue addOperation:processingOperation];
*/
public static Bitmap loadBitmap(String path, float maxWidth, float maxHeight) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
@ -898,7 +928,7 @@ public class FileLoader {
break;
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
Bitmap b;
@ -908,7 +938,7 @@ public class FileLoader {
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
FileLoader.Instance.memCache.evictAll();
b = BitmapFactory.decodeFile(path, bmOptions);
if (b != null && matrix != null) {
@ -959,8 +989,10 @@ public class FileLoader {
size.bytes = stream.toByteArray();
size.size = size.bytes.length;
}
if (scaledBitmap != bitmap) {
scaledBitmap.recycle();
if (Build.VERSION.SDK_INT < 11) {
if (scaledBitmap != bitmap) {
scaledBitmap.recycle();
}
}
return size;
} catch (Exception e) {

View File

@ -0,0 +1,158 @@
/*
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.net.Uri;
import android.util.Log;
import org.telegram.ui.ApplicationLoader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Locale;
public class FileLog {
public static boolean DEBUG_VERSION = true;
public static FileLog Instance = new FileLog();
private OutputStreamWriter streamWriter = null;
private FastDateFormat dateFormat = null;
private DispatchQueue logQueue = null;
private File currentFile = null;
public FileLog() {
if (!DEBUG_VERSION) {
return;
}
dateFormat = FastDateFormat.getInstance("dd_MM_yyyy_HH_mm_ss", Locale.US);
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
if (sdCard == null) {
return;
}
File dir = new File(sdCard.getAbsolutePath() + "/logs");
if (dir == null) {
return;
}
dir.mkdirs();
currentFile = new File(dir, dateFormat.format(System.currentTimeMillis()) + ".txt");
if (currentFile == null) {
return;
}
try {
currentFile.createNewFile();
FileOutputStream stream = new FileOutputStream(currentFile);
streamWriter = new OutputStreamWriter(stream);
streamWriter.write("-----start log " + dateFormat.format(System.currentTimeMillis()) + "-----\n");
streamWriter.flush();
logQueue = new DispatchQueue("logQueue");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void e(final String tag, final String message, final Throwable exception) {
if (!DEBUG_VERSION) {
return;
}
Log.e(tag, message, exception);
if (Instance.streamWriter != null) {
Instance.logQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
Instance.streamWriter.write(Instance.dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "" + message + "\n");
Instance.streamWriter.write(exception.toString());
Instance.streamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public static void e(final String tag, final String message) {
if (!DEBUG_VERSION) {
return;
}
Log.e(tag, message);
if (Instance.streamWriter != null) {
Instance.logQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
Instance.streamWriter.write(Instance.dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "" + message + "\n");
Instance.streamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public static void e(final String tag, final Exception e) {
if (!DEBUG_VERSION) {
return;
}
e.printStackTrace();
if (Instance.streamWriter != null) {
Instance.logQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
Instance.streamWriter.write(Instance.dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "" + e + "\n");
StackTraceElement[] stack = e.getStackTrace();
for (StackTraceElement el : stack) {
Instance.streamWriter.write(Instance.dateFormat.format(System.currentTimeMillis()) + " E/" + tag + "" + el + "\n");
}
Instance.streamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public static void d(final String tag, final String message) {
if (!DEBUG_VERSION) {
return;
}
Log.d(tag, message);
if (Instance.streamWriter != null) {
Instance.logQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
Instance.streamWriter.write(Instance.dateFormat.format(System.currentTimeMillis()) + " D/" + tag + "" + message + "\n");
Instance.streamWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public static void cleanupLogs() {
ArrayList<Uri> uris = new ArrayList<Uri>();
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
File dir = new File (sdCard.getAbsolutePath() + "/logs");
File[] files = dir.listFiles();
for (File file : files) {
if (Instance.currentFile != null && file.getAbsolutePath().equals(Instance.currentFile.getAbsolutePath())) {
continue;
}
file.delete();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -29,15 +29,17 @@ public class FileUploadOperation {
private long currentFileId;
private boolean isLastPart = false;
private long totalFileSize = 0;
private int totalPartsCount = 0;
private long currentUploaded = 0;
private byte[] key;
private byte[] iv;
private int fingerprint;
private boolean isBigFile = false;
FileInputStream stream;
MessageDigest mdEnc = null;
public static interface FileUploadOperationDelegate {
public abstract void didFinishUploadingFile(FileUploadOperation operation, TLRPC.TL_inputFile inputFile, TLRPC.TL_inputEncryptedFileUploaded inputEncryptedFile);
public abstract void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile);
public abstract void didFailedUploadingFile(FileUploadOperation operation);
public abstract void didChangedUploadProgress(FileUploadOperation operation, float progress);
}
@ -60,14 +62,14 @@ public class FileUploadOperation {
}
fingerprint = Utilities.bytesToInt(fingerprintBytes);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
currentFileId = (long)(MessagesController.random.nextDouble() * Long.MAX_VALUE);
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -95,18 +97,23 @@ public class FileUploadOperation {
return;
}
TLRPC.TL_upload_saveFilePart req = new TLRPC.TL_upload_saveFilePart();
req.file_part = currentPartNum;
req.file_id = currentFileId;
TLObject finalRequest;
try {
if (stream == null) {
File cacheFile = new File(uploadingFilePath);
stream = new FileInputStream(cacheFile);
totalFileSize = cacheFile.length();
if (totalFileSize > 10 * 1024 * 1024) {
FileLog.e("tmessages", "file is big!");
isBigFile = true;
}
uploadChunkSize = (int)Math.max(32, Math.ceil(totalFileSize / (1024.0f * 3000))) * 1024;
totalPartsCount = (int)Math.ceil((float)totalFileSize / (float)uploadChunkSize);
readBuffer = new byte[uploadChunkSize];
}
int readed = stream.read(readBuffer);
int toAdd = 0;
if (key != null && readed % 16 != 0) {
@ -121,14 +128,27 @@ public class FileUploadOperation {
sendBuffer = Utilities.aesIgeEncryption(sendBuffer, key, iv, true, true);
}
mdEnc.update(sendBuffer, 0, readed + toAdd);
req.bytes = sendBuffer;
if (isBigFile) {
TLRPC.TL_upload_saveBigFilePart req = new TLRPC.TL_upload_saveBigFilePart();
req.file_part = currentPartNum;
req.file_id = currentFileId;
req.file_total_parts = totalPartsCount;
req.bytes = sendBuffer;
finalRequest = req;
} else {
TLRPC.TL_upload_saveFilePart req = new TLRPC.TL_upload_saveFilePart();
req.file_part = currentPartNum;
req.file_id = currentFileId;
req.bytes = sendBuffer;
finalRequest = req;
}
currentUploaded += readed;
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
delegate.didFailedUploadingFile(this);
return;
}
requestToken = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
requestToken = ConnectionsManager.Instance.performRpc(finalRequest, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
requestToken = 0;
@ -139,15 +159,25 @@ public class FileUploadOperation {
if (isLastPart) {
state = 3;
if (key == null) {
TLRPC.TL_inputFile result = new TLRPC.TL_inputFile();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
TLRPC.InputFile result;
if (isBigFile) {
result = new TLRPC.TL_inputFileBig();
} else {
result = new TLRPC.TL_inputFile();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
}
result.parts = currentPartNum;
result.id = currentFileId;
result.name = uploadingFilePath.substring(uploadingFilePath.lastIndexOf("/") + 1);
delegate.didFinishUploadingFile(FileUploadOperation.this, result, null);
} else {
TLRPC.TL_inputEncryptedFileUploaded result = new TLRPC.TL_inputEncryptedFileUploaded();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
TLRPC.InputEncryptedFile result;
if (isBigFile) {
result = new TLRPC.TL_inputEncryptedFileBigUploaded();
} else {
result = new TLRPC.TL_inputEncryptedFileUploaded();
result.md5_checksum = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
}
result.parts = currentPartNum;
result.id = currentFileId;
result.key_fingerprint = fingerprint;

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -9,43 +9,28 @@
package org.telegram.messenger;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.json.JSONObject;
import org.telegram.ui.ApplicationLoader;
import org.telegram.ui.LaunchActivity;
public class GcmBroadcastReceiver extends BroadcastReceiver {
public static final int NOTIFICATION_ID = 1;
@Override
public void onReceive(final Context context, final Intent intent) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.i("tmessages", "GCM received intent: " + intent);
}
FileLog.d("tmessages", "GCM received intent: " + intent);
setResultCode(Activity.RESULT_OK);
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
SharedPreferences preferences = context.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
boolean globalEnabled = preferences.getBoolean("EnableAll", true);
if (!globalEnabled) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.i("tmessages", "GCM disabled");
}
FileLog.d("tmessages", "GCM disabled");
return;
}
@ -59,26 +44,22 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
if (ConnectionsManager.DEBUG_VERSION) {
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
Log.e("tmessages", "Registration failed, should try again later.");
} else if (intent.getStringExtra("unregistered") != null) {
Log.e("tmessages", "unregistration done, new messages from the authorized sender will be rejected");
} else if (registration != null) {
Log.e("tmessages", "registration id = " + registration);
}
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
FileLog.e("tmessages", "Registration failed, should try again later.");
} else if (intent.getStringExtra("unregistered") != null) {
FileLog.e("tmessages", "unregistration done, new messages from the authorized sender will be rejected");
} else if (registration != null) {
FileLog.e("tmessages", "registration id = " + registration);
}
}
}
private void sendNotification(Context context, Bundle extras) {
if (!UserConfig.clientActivated || context == null || extras == null) {
ConnectionsManager.Instance.resumeNetworkMaybe();
/*if (!UserConfig.clientActivated || context == null || extras == null) {
return;
}
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "received push " + extras);
}
SharedPreferences preferences = context.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
boolean groupEnabled = preferences.getBoolean("EnableGroup", true);
@ -112,7 +93,7 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
return;
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
int chat_id = 0;
@ -144,7 +125,7 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
if (user_id != 0) {
@ -224,6 +205,6 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
notification.ledOnMS = 1000;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
mNotificationManager.notify(NOTIFICATION_ID, notification);
mNotificationManager.notify(NOTIFICATION_ID, notification);*/
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,8 +8,6 @@
package org.telegram.messenger;
import android.util.Log;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
@ -50,15 +48,14 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
public void execute(HashMap params) {
Log.d("tmessages", String.format("Begin handshake with DC%d", datacenter.datacenterId));
FileLog.d("tmessages", String.format(Locale.US, "Begin handshake with DC%d", datacenter.datacenterId));
beginHandshake(true);
}
void beginHandshake(boolean dropConnection) {
if (datacenter.connection == null) {
datacenter.connection = new TcpConnection(datacenter.address, datacenter.port);
datacenter.connection = new TcpConnection(datacenter.datacenterId);
datacenter.connection.delegate = this;
datacenter.connection.datacenterId = datacenter.datacenterId;
datacenter.connection.transportRequestClass = RPCRequest.RPCRequestClassGeneric;
}
@ -168,7 +165,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
if (Arrays.equals(authNonce, resPq.nonce)) {
final HashMap<String, Object> publicKey = selectPublicKey(resPq.server_public_key_fingerprints);
if (publicKey == null) {
Log.e("tmessages", "***** Couldn't find valid server public key");
FileLog.e("tmessages", "***** Couldn't find valid server public key");
beginHandshake(false);
return;
}
@ -222,8 +219,10 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
SerializedData dataWithHash = new SerializedData();
dataWithHash.writeRaw(Utilities.computeSHA1(innerDataBytes));
dataWithHash.writeRaw(innerDataBytes);
byte[] b = new byte[1];
while (dataWithHash.length() < 255) {
dataWithHash.writeByte(0);
MessagesController.random.nextBytes(b);
dataWithHash.writeByte(b[0]);
}
byte[] encryptedBytes = Utilities.encryptWithRSA((BigInteger[])publicKey.get("key"), dataWithHash.toByteArray());
@ -251,7 +250,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
});
} else {
Log.e("tmessages", "***** Error: invalid handshake nonce");
FileLog.e("tmessages", "***** Error: invalid handshake nonce");
beginHandshake(false);
}
} else if (message instanceof TLRPC.Server_DH_Params) {
@ -309,7 +308,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
if (!hashVerified) {
Log.e("tmessages", "***** Couldn't decode DH params");
FileLog.e("tmessages", "***** Couldn't decode DH params");
beginHandshake(false);
return;
}
@ -319,18 +318,18 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
TLRPC.TL_server_DH_inner_data dhInnerData = (TLRPC.TL_server_DH_inner_data)TLClassStore.Instance().TLdeserialize(answerIs, constructor);
if (!(dhInnerData instanceof TLRPC.TL_server_DH_inner_data)) {
Log.e("tmessages", "***** Couldn't parse decoded DH params");
FileLog.e("tmessages", "***** Couldn't parse decoded DH params");
beginHandshake(false);
return;
}
if (!Arrays.equals(authNonce, dhInnerData.nonce)) {
Log.e("tmessages", "***** Invalid DH nonce");
FileLog.e("tmessages", "***** Invalid DH nonce");
beginHandshake(false);
return;
}
if (!Arrays.equals(authServerNonce, dhInnerData.server_nonce)) {
Log.e("tmessages", "***** Invalid DH server nonce");
FileLog.e("tmessages", "***** Invalid DH server nonce");
beginHandshake(false);
return;
}
@ -380,9 +379,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
serverSalt.validUntil = (int)(System.currentTimeMillis() / 1000) + timeDifference + 30 * 60;
serverSalt.value = saltBuffer.getLong();
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(Locale.US, "===== Time difference: %d", timeDifference));
}
FileLog.d("tmessages", String.format(Locale.US, "===== Time difference: %d", timeDifference));
TLRPC.TL_client_DH_inner_data clientInnerData = new TLRPC.TL_client_DH_inner_data();
clientInnerData.nonce = authNonce;
@ -396,8 +393,10 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
SerializedData clientDataWithHash = new SerializedData();
clientDataWithHash.writeRaw(Utilities.computeSHA1(clientInnerDataBytes));
clientDataWithHash.writeRaw(clientInnerDataBytes);
byte[] bb = new byte[1];
while (clientDataWithHash.length() % 16 != 0) {
clientDataWithHash.writeByte(0);
MessagesController.random.nextBytes(bb);
clientDataWithHash.writeByte(bb[0]);
}
TLRPC.TL_set_client_DH_params setClientDhParams = new TLRPC.TL_set_client_DH_params();
@ -413,19 +412,19 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
reqDHMsgData = null;
setClientDHParamsMsgData = sendMessageData(setClientDhParams, generateMessageId());
} else {
Log.e("tmessages", "***** Couldn't set DH params");
FileLog.e("tmessages", "***** Couldn't set DH params");
beginHandshake(false);
}
} else if (message instanceof TLRPC.Set_client_DH_params_answer) {
TLRPC.Set_client_DH_params_answer dhAnswer = (TLRPC.Set_client_DH_params_answer)message;
if (!Arrays.equals(authNonce, dhAnswer.nonce)) {
Log.e("tmessages", "***** Invalid DH answer nonce");
FileLog.e("tmessages", "***** Invalid DH answer nonce");
beginHandshake(false);
return;
}
if (!Arrays.equals(authServerNonce, dhAnswer.server_nonce)) {
Log.e("tmessages", "***** Invalid DH answer server nonce");
FileLog.e("tmessages", "***** Invalid DH answer server nonce");
beginHandshake(false);
return;
}
@ -468,12 +467,12 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
if (message instanceof TLRPC.TL_dh_gen_ok) {
TLRPC.TL_dh_gen_ok dhGenOk = (TLRPC.TL_dh_gen_ok)message;
if (!Arrays.equals(newNonceHash1, dhGenOk.new_nonce_hash1)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 1");
FileLog.e("tmessages", "***** Invalid DH answer nonce hash 1");
beginHandshake(false);
return;
}
Log.d("tmessages", String.format("Handshake with DC%d completed", datacenter.datacenterId));
FileLog.d("tmessages", String.format("Handshake with DC%d completed", datacenter.datacenterId));
datacenter.connection.delegate = null;
final Action parent = this;
@ -493,23 +492,23 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
} else if (message instanceof TLRPC.TL_dh_gen_retry) {
TLRPC.TL_dh_gen_retry dhRetry = (TLRPC.TL_dh_gen_retry)message;
if (!Arrays.equals(newNonceHash2, dhRetry.new_nonce_hash2)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 2");
FileLog.e("tmessages", "***** Invalid DH answer nonce hash 2");
beginHandshake(false);
return;
}
Log.d("tmessages", "***** Retry DH");
FileLog.d("tmessages", "***** Retry DH");
beginHandshake(false);
} else if (message instanceof TLRPC.TL_dh_gen_fail) {
TLRPC.TL_dh_gen_fail dhFail = (TLRPC.TL_dh_gen_fail)message;
if (!Arrays.equals(newNonceHash3, dhFail.new_nonce_hash3)) {
Log.e("tmessages", "***** Invalid DH answer nonce hash 3");
FileLog.e("tmessages", "***** Invalid DH answer nonce hash 3");
beginHandshake(false);
return;
}
Log.d("tmessages", "***** Server declined DH params");
FileLog.d("tmessages", "***** Server declined DH params");
beginHandshake(false);
} else {
Log.e("tmessages", "***** Unknown DH params response");
FileLog.e("tmessages", "***** Unknown DH params response");
beginHandshake(false);
}
} else {
@ -520,6 +519,11 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
}
@Override
public void tcpConnectionProgressChanged(TcpConnection connection, long messageId, int currentSize, int length) {
}
@Override
public void tcpConnectionClosed(TcpConnection connection) {
wasDisconnect = true;
@ -553,7 +557,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
if (keyId == 0) {
long messageId = is.readInt64();
if (processedMessageIds.contains(messageId)) {
Log.d("tmessages", String.format("===== Duplicate message id %d received, ignoring", messageId));
FileLog.d("tmessages", String.format("===== Duplicate message id %d received, ignoring", messageId));
return;
}
int messageLength = is.readInt32();
@ -566,7 +570,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
processMessage(object, messageId);
} else {
Log.d("tmessages", "***** Received encrypted message while in handshake, restarting");
FileLog.d("tmessages", "***** Received encrypted message while in handshake, restarting");
beginHandshake(true);
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -144,7 +144,7 @@ public class LruCache {
evictionCount++;
}
String[] args = key.split("$");
String[] args = key.split("@");
if (args.length > 1) {
ArrayList<String> arr = mapFilters.get(args[0]);
if (arr != null) {
@ -178,7 +178,7 @@ public class LruCache {
}
if (previous != null) {
String[] args = key.split("$");
String[] args = key.split("@");
if (args.length > 1) {
ArrayList<String> arr = mapFilters.get(args[0]);
if (arr != null) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -9,6 +9,7 @@
package org.telegram.messenger;
import android.text.Html;
import android.util.Log;
import android.util.SparseArray;
import org.telegram.SQLite.SQLiteCursor;
@ -70,15 +71,20 @@ public class MessagesStorage {
database.executeFast("CREATE TABLE enc_tasks(date INTEGER, data BLOB)").stepThis().dispose();
database.executeFast("CREATE TABLE params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB)").stepThis().dispose();
database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose();
database.executeFast("CREATE TABLE user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_dialogs ON dialogs(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_enc_tasks ON enc_tasks(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS last_mid_idx_dialogs ON dialogs(last_mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_idx_messages ON messages(uid, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_messages ON messages(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_idx_media ON media(uid, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS ttl_idx_messages ON messages(ttl);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS read_state_out_idx_messages ON messages(read_state, out);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_idx_media ON media(mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_media ON media(uid, date, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_idx_messages ON messages(uid, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state);").stepThis().dispose();
} else {
SQLiteCursor cursor = database.queryFinalized("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='params'");
boolean create = false;
@ -114,9 +120,21 @@ public class MessagesStorage {
}
cursor.dispose();
}
database.executeFast("CREATE TABLE IF NOT EXISTS user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_idx_media ON media(mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_media ON media(uid, date, mid);").stepThis().dispose();
database.executeFast("DROP INDEX IF EXISTS read_state_out_idx_messages;").stepThis().dispose();
database.executeFast("DROP INDEX IF EXISTS ttl_idx_messages;").stepThis().dispose();
database.executeFast("DROP INDEX IF EXISTS date_idx_messages;").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid);").stepThis().dispose();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -153,7 +171,7 @@ public class MessagesStorage {
old.delete();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
openDatabase();
}
@ -176,7 +194,7 @@ public class MessagesStorage {
state.step();
state.dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -195,7 +213,7 @@ public class MessagesStorage {
state.step();
state.dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -222,7 +240,7 @@ public class MessagesStorage {
state.dispose();
database.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -246,7 +264,7 @@ public class MessagesStorage {
cursor.dispose();
NotificationCenter.Instance.postNotificationName(wallpapersDidLoaded, wallPapers);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -265,7 +283,71 @@ public class MessagesStorage {
database.executeFast("DELETE FROM messages WHERE uid = " + did).stepThis().dispose();
database.executeFast("DELETE FROM media WHERE uid = " + did).stepThis().dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
}
public void getUserPhotos(final int uid, final int offset, final int count, final long max_id, final int classGuid) {
try {
SQLiteCursor cursor;
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d AND id < %d ORDER BY id DESC LIMIT %d", uid, max_id, count));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d ORDER BY id DESC LIMIT %d,%d", uid, offset, count));
}
final TLRPC.photos_Photos res = new TLRPC.photos_Photos();
while (cursor.next()) {
byte[] messageData = cursor.byteArrayValue(0);
if (messageData != null) {
SerializedData data = new SerializedData(messageData);
TLRPC.Photo photo = (TLRPC.Photo)TLClassStore.Instance().TLdeserialize(data, data.readInt32());
res.photos.add(photo);
}
}
cursor.dispose();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
MessagesController.Instance.processLoadedUserPhotos(res, uid, offset, count, max_id, true, classGuid);
}
});
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void putUserPhotos(final int uid, final TLRPC.photos_Photos photos) {
if (photos == null || photos.photos.isEmpty()) {
return;
}
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
SQLitePreparedStatement state = database.executeFast("REPLACE INTO user_photos VALUES(?, ?, ?)");
for (TLRPC.Photo photo : photos.photos) {
if (photo instanceof TLRPC.TL_photoEmpty) {
continue;
}
state.requery();
SerializedData data = new SerializedData();
photo.serializeToStream(data);
state.bindInteger(1, uid);
state.bindLong(2, photo.id);
byte[] bytes = data.toByteArray();
state.bindByteArray(3, bytes);
state.step();
}
state.dispose();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
});
@ -297,7 +379,7 @@ public class MessagesStorage {
cursor.dispose();
MessagesController.Instance.processLoadedDeleteTask(taskId, date, arr);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -311,7 +393,7 @@ public class MessagesStorage {
int minDate = Integer.MAX_VALUE;
SparseArray<ArrayList<Integer>> messages = new SparseArray<ArrayList<Integer>>();
String mids = "";
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, ttl FROM messages WHERE uid = %d AND out = %d AND read_state = 1 AND ttl > 0 AND date <= %d", ((long)chat_id) << 32, isOut, time));
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, ttl FROM messages WHERE uid = %d AND out = %d AND read_state = 1 AND ttl > 0 AND date <= %d AND send_state = 0", ((long)chat_id) << 32, isOut, time));
while (cursor.next()) {
int mid = cursor.intValue(0);
int ttl = cursor.intValue(1);
@ -358,7 +440,7 @@ public class MessagesStorage {
MessagesController.Instance.didAddedNewTask(minDate);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -557,7 +639,7 @@ public class MessagesStorage {
MessagesController.Instance.processDialogsUpdate(dialogs, encryptedChats);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -601,7 +683,7 @@ public class MessagesStorage {
state.step();
state.dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -650,7 +732,7 @@ public class MessagesStorage {
}
MessagesController.Instance.processChatInfo(chat_id, info, loadedUsers, true);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -662,15 +744,15 @@ public class MessagesStorage {
public void run() {
try {
if (delete) {
database.executeFast("DELETE FROM pending_read WHERE uid = " + dialog_id).stepThis().dispose();
//database.executeFast("DELETE FROM pending_read WHERE uid = " + dialog_id).stepThis().dispose();
} else {
database.beginTransaction();
SQLitePreparedStatement state = database.executeFast("REPLACE INTO pending_read VALUES(?, ?)");
SQLitePreparedStatement state;/*) = database.executeFast("REPLACE INTO pending_read VALUES(?, ?)");
state.requery();
state.bindLong(1, dialog_id);
state.bindInteger(2, max_id);
state.step();
state.dispose();
state.dispose();*/
int lower_id = (int)dialog_id;
@ -699,7 +781,7 @@ public class MessagesStorage {
database.commitTransaction();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -711,13 +793,13 @@ public class MessagesStorage {
public void run() {
try {
ArrayList<TLRPC.User> encUsers = new ArrayList<TLRPC.User>();
if (query.length() == 0) {
String q = query.trim().toLowerCase();
if (q.length() == 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.reloadSearchResults, token, new ArrayList<TLObject>(), new ArrayList<CharSequence>(), new ArrayList<CharSequence>());
return;
}
ArrayList<TLObject> resultArray = new ArrayList<TLObject>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<CharSequence>();
String q = query.toLowerCase();
SQLiteCursor cursor = database.queryFinalized("SELECT u.data, u.status, u.name FROM users as u INNER JOIN contacts as c ON u.uid = c.uid");
while (cursor.next()) {
@ -797,7 +879,7 @@ public class MessagesStorage {
cursor.dispose();
NotificationCenter.Instance.postNotificationName(MessagesController.reloadSearchResults, token, resultArray, resultArrayNames, encUsers);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -825,7 +907,7 @@ public class MessagesStorage {
state.dispose();
database.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -873,7 +955,7 @@ public class MessagesStorage {
}
MessagesController.Instance.processLoadedContacts(contacts, users, 1);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -891,7 +973,7 @@ public class MessagesStorage {
state2.step();
state2.dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -921,7 +1003,7 @@ public class MessagesStorage {
}
MessagesController.Instance.processLoadedMediaCount(count, uid, classGuid, true);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -938,7 +1020,6 @@ public class MessagesStorage {
SQLiteCursor cursor;
if ((int)uid != 0) {
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media WHERE uid = %d AND mid < %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, count));
@ -996,7 +1077,7 @@ public class MessagesStorage {
res.messages.clear();
res.chats.clear();
res.users.clear();
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
MessagesController.Instance.processLoadedMedia(res, uid, offset, count, max_id, true, classGuid);
}
@ -1021,55 +1102,112 @@ public class MessagesStorage {
state2.bindInteger(3, message.date);
state2.bindByteArray(4, data.toByteArray());
state2.step();
} else {
Log.e("tmessages", "test");
}
}
state2.dispose();
database.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
}
public void getMessages(final long dialog_id, final int offset, final int count, final int max_id, final int minDate, final int classGuid) {
public void getMessages(final long dialog_id, final int offset, final int count, final int max_id, final int minDate, final int classGuid, final boolean from_unread, final boolean forward) {
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages();
int count_unread = 0;
int count_query = count;
int offset_query = offset;
int min_unread_id = 0;
int max_unread_id = 0;
int max_unread_date = 0;
try {
ArrayList<Integer> loadedUsers = new ArrayList<Integer>();
ArrayList<Integer> fromUser = new ArrayList<Integer>();
SQLiteCursor cursor;
int lower_id = (int)dialog_id;
if (lower_id != 0) {
if (minDate != 0) {
if (forward) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid > %d ORDER BY date ASC, mid ASC LIMIT %d", dialog_id, max_id, count_query));
} else if (minDate != 0) {
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid < %d AND date < %d ORDER BY date DESC, mid DESC LIMIT %d", dialog_id, max_id, minDate, count));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND date < %d AND mid < %d ORDER BY date DESC, mid DESC LIMIT %d", dialog_id, minDate, max_id, count_query));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND date < %d ORDER BY date DESC, mid DESC LIMIT %d,%d", dialog_id, minDate, offset, count));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND date < %d ORDER BY date DESC, mid DESC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query));
}
} else {
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid < %d ORDER BY date DESC, mid DESC LIMIT %d", dialog_id, max_id, count));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", dialog_id, offset, count));
if (from_unread) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid), max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state = 0 AND mid > 0", dialog_id));
if (cursor.next()) {
min_unread_id = cursor.intValue(0);
max_unread_id = cursor.intValue(1);
max_unread_date = cursor.intValue(2);
}
cursor.dispose();
if (min_unread_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid >= %d AND out = 0 AND read_state = 0", dialog_id, min_unread_id));
if (cursor.next()) {
count_unread = cursor.intValue(0);
}
cursor.dispose();
}
}
if (count_query > count_unread || count_unread < 4) {
count_query = Math.max(count_query, count_unread + 10);
if (count_unread < 4) {
count_unread = 0;
min_unread_id = 0;
max_unread_id = 0;
}
} else {
offset_query = count_unread - count_query;
count_query += 10;
}
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", dialog_id, offset_query, count_query));
}
} else {
if (minDate != 0) {
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid < %d AND date < %d ORDER BY date DESC LIMIT %d", dialog_id, max_id, minDate, count));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND date < %d ORDER BY date DESC LIMIT %d,%d", dialog_id, minDate, offset, count));
}
if (forward) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid < %d ORDER BY mid DESC LIMIT %d", dialog_id, max_id, count_query));
} else if (minDate != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND date < %d ORDER BY mid ASC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query));
} else {
if (max_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d AND mid < %d ORDER BY date DESC LIMIT %d", dialog_id, max_id, count));
} else {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d ORDER BY date DESC LIMIT %d,%d", dialog_id, offset, count));
if (from_unread) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid), min(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state = 0 AND mid < 0", dialog_id));
if (cursor.next()) {
min_unread_id = cursor.intValue(0);
max_unread_id = cursor.intValue(1);
max_unread_date = cursor.intValue(2);
}
cursor.dispose();
if (min_unread_id != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state = 0", dialog_id, min_unread_id));
if (cursor.next()) {
count_unread = cursor.intValue(0);
}
cursor.dispose();
}
}
if (count_query > count_unread || count_unread < 4) {
count_query = Math.max(count_query, count_unread + 10);
if (count_unread < 4) {
count_unread = 0;
min_unread_id = 0;
max_unread_id = 0;
}
} else {
offset_query = count_unread - count_query;
count_query += 10;
}
cursor = database.queryFinalized(String.format(Locale.US, "SELECT read_state, data, send_state, mid, date FROM messages WHERE uid = %d ORDER BY mid ASC LIMIT %d,%d", dialog_id, offset_query, count_query));
}
}
while (cursor.next()) {
@ -1131,9 +1269,9 @@ public class MessagesStorage {
res.messages.clear();
res.chats.clear();
res.users.clear();
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
MessagesController.Instance.processLoadedMessages(res, dialog_id, offset, count, max_id, true, classGuid);
MessagesController.Instance.processLoadedMessages(res, dialog_id, offset, count_query, max_id, true, classGuid, min_unread_id, max_unread_id, count_unread, max_unread_date, forward);
}
}
});
@ -1147,7 +1285,7 @@ public class MessagesStorage {
try {
database.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -1155,7 +1293,7 @@ public class MessagesStorage {
try {
database.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
}
@ -1187,7 +1325,7 @@ public class MessagesStorage {
state.bindInteger(2, chat.id);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1224,7 +1362,7 @@ public class MessagesStorage {
state.bindInteger(5, chat.id);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1278,7 +1416,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
semaphore.release();
}
@ -1330,7 +1468,7 @@ public class MessagesStorage {
state.dispose();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -1389,7 +1527,7 @@ public class MessagesStorage {
database.commitTransaction();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -1546,7 +1684,7 @@ public class MessagesStorage {
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -1575,7 +1713,7 @@ public class MessagesStorage {
state.bindInteger(2, newId);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1592,7 +1730,7 @@ public class MessagesStorage {
oldId = cursor.intValue(0);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (cursor != null) {
cursor.dispose();
@ -1602,7 +1740,7 @@ public class MessagesStorage {
// try {
// database.executeFast(String.format(Locale.US, "DELETE FROM randoms WHERE random_id = %d", random_id)).stepThis().dispose();
// } catch (Exception e) {
// e.printStackTrace();
// FileLog.e("tmessages", e);
// }
// }
}
@ -1617,7 +1755,7 @@ public class MessagesStorage {
state.bindInteger(2, oldId);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1630,7 +1768,7 @@ public class MessagesStorage {
state.bindInteger(2, oldId);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1643,7 +1781,7 @@ public class MessagesStorage {
state.bindLong(2, oldId);
state.step();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
} finally {
if (state != null) {
state.dispose();
@ -1754,7 +1892,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -1802,7 +1940,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -1836,7 +1974,7 @@ public class MessagesStorage {
database.executeFast("DELETE FROM media_counts WHERE 1").stepThis().dispose();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -2010,7 +2148,7 @@ public class MessagesStorage {
MessagesController.Instance.processDialogsUpdate(dialogs, encryptedChats);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -2129,7 +2267,7 @@ public class MessagesStorage {
database.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -2228,7 +2366,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
cursor.dispose();
@ -2254,7 +2392,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
cursor.dispose();
@ -2283,7 +2421,7 @@ public class MessagesStorage {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
cursor.dispose();
@ -2294,11 +2432,11 @@ public class MessagesStorage {
dialogs.users.clear();
dialogs.chats.clear();
encryptedChats.clear();
e.printStackTrace();
FileLog.e("tmessages", e);
/*try {
database.executeFast("DELETE FROM dialogs WHERE 1").stepThis().dispose();
} catch (Exception e2) {
e.printStackTrace();
FileLog.e("tmessages", e);
}*/
MessagesController.Instance.processLoadedDialogs(dialogs, encryptedChats, 0, 0, 100, true, true);
}
@ -2412,7 +2550,7 @@ public class MessagesStorage {
database.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,8 +8,6 @@
package org.telegram.messenger;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@ -30,6 +28,11 @@ public class SerializedData {
out = new DataOutputStream(outbuf);
}
public SerializedData(int size) {
outbuf = new ByteArrayOutputStream(size);
out = new DataOutputStream(outbuf);
}
public SerializedData(byte[] data){
isOut = false;
inbuf = new ByteArrayInputStream(data);
@ -57,7 +60,7 @@ public class SerializedData {
out.write(x >> (i * 8));
}
} catch(IOException gfdsgd) {
Log.e("tmessages", "write int32 error");
FileLog.e("tmessages", "write int32 error");
}
}
@ -71,7 +74,7 @@ public class SerializedData {
out.write((int)(x >> (i * 8)));
}
} catch(IOException gfdsgd) {
Log.e("tmessages", "write int64 error");
FileLog.e("tmessages", "write int64 error");
}
}
@ -82,7 +85,7 @@ public class SerializedData {
} else if (consructor == 0xbc799737) {
return false;
}
Log.e("tmessages", "Not bool value!");
FileLog.e("tmessages", "Not bool value!");
return false;
}
@ -94,28 +97,48 @@ public class SerializedData {
}
}
public int readInt32(){
public int readInt32() {
return readInt32(null);
}
public int readInt32(boolean[] error) {
try {
int i = 0;
for(int j = 0; j < 4; j++){
i |= (in.read() << (j * 8));
}
if (error != null) {
error[0] = false;
}
return i;
} catch(IOException x) {
Log.e("tmessages", "read int32 error");
if (error != null) {
error[0] = true;
}
FileLog.e("tmessages", "read int32 error");
}
return 0;
}
public long readInt64(){
public long readInt64() {
return readInt64(null);
}
public long readInt64(boolean[] error) {
try {
long i = 0;
for(int j = 0; j < 8; j++){
i |= ((long)in.read() << (j * 8));
}
if (error != null) {
error[0] = false;
}
return i;
} catch(IOException x) {
Log.e("tmessages", "read int64 error");
if (error != null) {
error[0] = true;
}
FileLog.e("tmessages", "read int64 error");
}
return 0;
}
@ -124,7 +147,7 @@ public class SerializedData {
try {
out.write(b);
} catch(Exception x) {
Log.e("tmessages", "write raw error");
FileLog.e("tmessages", "write raw error");
}
}
@ -132,7 +155,7 @@ public class SerializedData {
try {
out.write(b, offset, count);
} catch(Exception x) {
Log.e("tmessages", "write raw error");
FileLog.e("tmessages", "write raw error");
}
}
@ -140,7 +163,7 @@ public class SerializedData {
try {
out.writeByte((byte)i);
} catch (Exception e) {
Log.e("tmessages", "write byte error");
FileLog.e("tmessages", "write byte error");
}
}
@ -148,7 +171,7 @@ public class SerializedData {
try {
out.writeByte(b);
} catch (Exception e) {
Log.e("tmessages", "write byte error");
FileLog.e("tmessages", "write byte error");
}
}
@ -156,7 +179,7 @@ public class SerializedData {
try {
in.read(b);
} catch(Exception x) {
Log.e("tmessages", "read raw error");
FileLog.e("tmessages", "read raw error");
}
}
@ -183,7 +206,7 @@ public class SerializedData {
}
return new String(b, "UTF-8");
} catch(Exception x) {
Log.e("tmessages", "read string error");
FileLog.e("tmessages", "read string error");
}
return null;
}
@ -205,7 +228,7 @@ public class SerializedData {
}
return b;
} catch(Exception x) {
Log.e("tmessages", "read byte array error");
FileLog.e("tmessages", "read byte array error");
}
return null;
}
@ -226,8 +249,8 @@ public class SerializedData {
out.write(0);
i++;
}
}catch(Exception x) {
Log.e("tmessages", "write byte array error");
} catch(Exception x) {
FileLog.e("tmessages", "write byte array error");
}
}
@ -235,7 +258,7 @@ public class SerializedData {
try {
writeByteArray(s.getBytes("UTF-8"));
} catch(Exception x) {
Log.e("tmessages", "write string error");
FileLog.e("tmessages", "write string error");
}
}
@ -256,15 +279,15 @@ public class SerializedData {
i++;
}
} catch(Exception x) {
Log.e("tmessages", "write byte array error");
FileLog.e("tmessages", "write byte array error");
}
}
public double readDouble(){
public double readDouble() {
try {
return Double.longBitsToDouble(readInt64());
} catch(Exception x) {
Log.e("tmessages", "read double error");
FileLog.e("tmessages", "read double error");
}
return 0;
}
@ -273,7 +296,7 @@ public class SerializedData {
try {
writeInt64(Double.doubleToRawLongBits(d));
} catch(Exception x) {
Log.e("tmessages", "write double error");
FileLog.e("tmessages", "write double error");
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -49,11 +49,11 @@ public class SmsListener extends BroadcastReceiver {
}
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
} catch(Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,20 +8,16 @@
package org.telegram.messenger;
import android.util.Log;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;
import jawnae.pyronet.PyroClient;
import jawnae.pyronet.PyroSelector;
import jawnae.pyronet.events.PyroClientAdapter;
import jawnae.pyronet.PyroClientAdapter;
public class TcpConnection extends PyroClientAdapter {
public enum TcpConnectionState {
@ -37,19 +33,23 @@ public class TcpConnection extends PyroClientAdapter {
public abstract void tcpConnectionConnected(TcpConnection connection);
public abstract void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack);
public abstract void tcpConnectionReceivedData(TcpConnection connection, byte[] data);
public abstract void tcpConnectionProgressChanged(TcpConnection connection, long messageId, int currentSize, int length);
}
private static PyroSelector selector;
private PyroClient client;
public TcpConnectionState connectionState;
private Queue<byte[]> packetsQueue;
public volatile int channelToken = 0;
private String hostAddress;
private int hostPort;
public int datacenterId;
private int datacenterId;
private int failedConnectionCount;
public TcpConnectionDelegate delegate;
private ByteBuffer restOfTheData;
private long lastMessageId = 0;
private boolean hasSomeDataSinceLastConnect = false;
private int willRetryConnectCount = 5;
private boolean isNextPort = false;
public int transportRequestClass;
@ -57,14 +57,12 @@ public class TcpConnection extends PyroClientAdapter {
private Timer reconnectTimer;
public TcpConnection(String ip, int port) {
public TcpConnection(int did) {
if (selector == null) {
selector = new PyroSelector();
selector.spawnNetworkThread("network thread");
}
packetsQueue = new LinkedList<byte[]>();
hostAddress = ip;
hostPort = port;
datacenterId = did;
connectionState = TcpConnectionState.TcpConnectionStageIdle;
}
@ -73,74 +71,142 @@ public class TcpConnection extends PyroClientAdapter {
return nextChannelToken++;
}
public int getDatacenterId() {
return datacenterId;
}
public void connect() {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
if (connectionState == TcpConnectionState.TcpConnectionStageConnected || connectionState == TcpConnectionState.TcpConnectionStageConnecting) {
if ((connectionState == TcpConnectionState.TcpConnectionStageConnected || connectionState == TcpConnectionState.TcpConnectionStageConnecting) && client != null) {
return;
}
connectionState = TcpConnectionState.TcpConnectionStageConnecting;
try {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(this + " Connecting (%s:%d)", hostAddress, hostPort));
}
Datacenter datacenter = ConnectionsManager.Instance.datacenterWithId(datacenterId);
hostAddress = datacenter.getCurrentAddress();
hostPort = datacenter.getCurrentPort();
FileLog.d("tmessages", String.format(TcpConnection.this + " Connecting (%s:%d)", hostAddress, hostPort));
firstPacket = true;
restOfTheData = null;
hasSomeDataSinceLastConnect = false;
if (client != null) {
client.removeListener(TcpConnection.this);
client.dropConnection();
client = null;
}
client = selector.connect(new InetSocketAddress(hostAddress, hostPort));
client.addListener(TcpConnection.this);
client.setTimeout(35000);
if (isNextPort) {
client.setTimeout(8000);
} else {
client.setTimeout(35000);
}
selector.wakeup();
} catch (Exception e) {
e.printStackTrace();
try {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
} catch (Exception e2) {
FileLog.e("tmessages", e2);
}
connectionState = TcpConnectionState.TcpConnectionStageReconnecting;
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionClosed(TcpConnection.this);
}
});
}
failedConnectionCount++;
if (failedConnectionCount == 1) {
if (hasSomeDataSinceLastConnect) {
willRetryConnectCount = 5;
} else {
willRetryConnectCount = 1;
}
}
isNextPort = true;
if (failedConnectionCount > willRetryConnectCount) {
Datacenter datacenter = ConnectionsManager.Instance.datacenterWithId(datacenterId);
datacenter.nextAddressOrPort();
failedConnectionCount = 0;
}
FileLog.e("tmessages", e);
FileLog.d("tmessages", "Reconnect " + hostAddress + ":" + hostPort + " " + TcpConnection.this);
try {
reconnectTimer = new Timer();
reconnectTimer.schedule(new TimerTask() {
@Override
public void run() {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
try {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
} catch (Exception e2) {
FileLog.e("tmessages", e2);
}
connect();
}
});
}
}, failedConnectionCount >= 3 ? 500 : 300, failedConnectionCount >= 3 ? 500 : 300);
} catch (Exception e3) {
FileLog.e("tmessages", e3);
}
}
}
});
}
private void suspendConnectionInternal() {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle || connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
return;
}
FileLog.d("tmessages", "suspend connnection " + TcpConnection.this);
connectionState = TcpConnectionState.TcpConnectionStageSuspended;
if (client != null) {
client.removeListener(TcpConnection.this);
client.dropConnection();
client = null;
}
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionClosed(TcpConnection.this);
}
});
}
firstPacket = true;
restOfTheData = null;
channelToken = 0;
}
public void suspendConnection(boolean task) {
if (task) {
selector.scheduleTask(new Runnable() {
@Override
public void run() {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle || connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
return;
}
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "suspend connnection " + this);
}
connectionState = TcpConnectionState.TcpConnectionStageSuspended;
if (client != null) {
client.dropConnection();
client = null;
}
suspendConnectionInternal();
}
});
} else {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle || connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
return;
}
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "suspend connnection " + this);
}
connectionState = TcpConnectionState.TcpConnectionStageSuspended;
if (client != null) {
client.dropConnection();
client = null;
}
suspendConnectionInternal();
}
}
@ -160,10 +226,14 @@ public class TcpConnection extends PyroClientAdapter {
public void run() {
if (connectionState == TcpConnectionState.TcpConnectionStageIdle ||
connectionState == TcpConnectionState.TcpConnectionStageReconnecting ||
connectionState == TcpConnectionState.TcpConnectionStageSuspended) {
connectionState == TcpConnectionState.TcpConnectionStageSuspended || client == null) {
connect();
}
if (client == null || client.isDisconnected()) {
return;
}
int packetLength = data.length / 4;
SerializedData buffer = new SerializedData();
@ -183,33 +253,22 @@ public class TcpConnection extends PyroClientAdapter {
final byte[] packet = buffer.toByteArray();
if (client != null && !client.isDisconnected()) {
ByteBuffer sendBuffer = ByteBuffer.allocate((firstPacket ? 1 : 0) + packet.length);
sendBuffer.rewind();
sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (firstPacket) {
sendBuffer.put((byte)0xef);
firstPacket = false;
}
sendBuffer.put(packet);
sendBuffer.rewind();
client.write(sendBuffer);
} else {
packetsQueue.add(packet);
ByteBuffer sendBuffer = ByteBuffer.allocate((firstPacket ? 1 : 0) + packet.length);
sendBuffer.rewind();
sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (firstPacket) {
sendBuffer.put((byte)0xef);
firstPacket = false;
}
sendBuffer.put(packet);
sendBuffer.rewind();
client.write(sendBuffer);
}
});
}
private void readData(ByteBuffer buffer) throws Exception {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "received data = " + buffer.limit());
}
if (restOfTheData != null) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "there is rest of data " + restOfTheData.limit());
}
ByteBuffer newBuffer = ByteBuffer.allocate(restOfTheData.limit() + buffer.limit());
newBuffer.put(restOfTheData);
newBuffer.put(buffer);
@ -221,6 +280,13 @@ public class TcpConnection extends PyroClientAdapter {
buffer.rewind();
while (buffer.hasRemaining()) {
if (!hasSomeDataSinceLastConnect) {
Datacenter datacenter = ConnectionsManager.Instance.datacenterWithId(datacenterId);
datacenter.storeCurrentAddressAndPortNum();
isNextPort = false;
client.setTimeout(35000);
}
hasSomeDataSinceLastConnect = true;
int currentPacketLength;
buffer.mark();
@ -261,17 +327,38 @@ public class TcpConnection extends PyroClientAdapter {
currentPacketLength = (buffer.getInt() >> 8) * 4;
}
if (currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
FileLog.e("tmessages", "Invalid packet length");
reconnect();
return;
}
if (currentPacketLength < buffer.remaining()) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received message len " + currentPacketLength + " but packet larger " + buffer.remaining());
}
FileLog.d("tmessages", TcpConnection.this + " Received message len " + currentPacketLength + " but packet larger " + buffer.remaining());
lastMessageId = 0;
} else if (currentPacketLength == buffer.remaining()) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received message len " + currentPacketLength + " equal to packet size");
}
FileLog.d("tmessages", TcpConnection.this + " Received message len " + currentPacketLength + " equal to packet size");
lastMessageId = 0;
} else {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " Received packet size less(" + buffer.remaining() + ") then message size(" + currentPacketLength + ")");
FileLog.d("tmessages", TcpConnection.this + " Received packet size less(" + buffer.remaining() + ") then message size(" + currentPacketLength + ")");
if (buffer.remaining() >= 152 && (transportRequestClass & RPCRequest.RPCRequestClassDownloadMedia) != 0) {
if (lastMessageId == 0) {
byte[] temp = new byte[152];
buffer.get(temp);
lastMessageId = ConnectionsManager.Instance.needsToDecodeMessageIdFromPartialData(TcpConnection.this, temp);
}
if (lastMessageId != -1 && lastMessageId != 0) {
if (delegate != null) {
final int arg2 = buffer.remaining();
final int arg3 = currentPacketLength;
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
delegate.tcpConnectionProgressChanged(TcpConnection.this, lastMessageId, arg2, arg3);
}
});
}
}
}
buffer.reset();
restOfTheData = ByteBuffer.allocate(buffer.remaining());
@ -281,14 +368,6 @@ public class TcpConnection extends PyroClientAdapter {
return;
}
if (currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", "Invalid packet length");
}
reconnect();
return;
}
final byte[] packetData = new byte[currentPacketLength];
buffer.get(packetData);
@ -303,21 +382,18 @@ public class TcpConnection extends PyroClientAdapter {
}
}
public void handleDisconnect(PyroClient client, IOException e) {
public void handleDisconnect(PyroClient client, Exception e) {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
if (ConnectionsManager.DEBUG_VERSION) {
if (e != null) {
Log.d("tmessages", "Disconnected " + this + " with error " + e);
} else {
Log.d("tmessages", "Disconnected " + this);
}
if (e != null) {
FileLog.d("tmessages", "Disconnected " + TcpConnection.this + " with error " + e);
} else {
FileLog.d("tmessages", "Disconnected " + TcpConnection.this);
}
firstPacket = true;
restOfTheData = null;
packetsQueue.clear();
channelToken = 0;
if (connectionState != TcpConnectionState.TcpConnectionStageSuspended && connectionState != TcpConnectionState.TcpConnectionStageIdle) {
connectionState = TcpConnectionState.TcpConnectionStageIdle;
@ -330,12 +406,23 @@ public class TcpConnection extends PyroClientAdapter {
}
});
}
if (connectionState == TcpConnectionState.TcpConnectionStageIdle && (!packetsQueue.isEmpty() ||
(transportRequestClass & RPCRequest.RPCRequestClassGeneric) != 0 && (datacenterId == ConnectionsManager.Instance.currentDatacenterId || datacenterId == ConnectionsManager.Instance.movingToDatacenterId))) {
if (connectionState == TcpConnectionState.TcpConnectionStageIdle &&
((transportRequestClass & RPCRequest.RPCRequestClassGeneric) != 0 && (datacenterId == ConnectionsManager.Instance.currentDatacenterId || datacenterId == ConnectionsManager.Instance.movingToDatacenterId))) {
failedConnectionCount++;
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "Reconnect " + hostAddress + ":" + hostPort + " " + this);
if (failedConnectionCount == 1) {
if (hasSomeDataSinceLastConnect) {
willRetryConnectCount = 5;
} else {
willRetryConnectCount = 1;
}
}
isNextPort = true;
if (failedConnectionCount > willRetryConnectCount) {
Datacenter datacenter = ConnectionsManager.Instance.datacenterWithId(datacenterId);
datacenter.nextAddressOrPort();
failedConnectionCount = 0;
}
FileLog.d("tmessages", "Reconnect " + hostAddress + ":" + hostPort + " " + TcpConnection.this);
try {
reconnectTimer = new Timer();
reconnectTimer.schedule(new TimerTask() {
@ -350,29 +437,24 @@ public class TcpConnection extends PyroClientAdapter {
reconnectTimer = null;
}
} catch (Exception e2) {
e2.printStackTrace();
FileLog.e("tmessages", e2);
}
connect();
}
});
}
}, failedConnectionCount > 10 ? 500 : 200, failedConnectionCount > 10 ? 500 : 200);
}, failedConnectionCount > 3 ? 500 : 300, failedConnectionCount > 3 ? 500 : 300);
} catch (Exception e3) {
e3.printStackTrace();
FileLog.e("tmessages", e3);
}
}
}
@Override
public void connectedClient(PyroClient client) {
//if (!ConnectionsManager.isNetworkOnline()) {
// return;
//}
connectionState = TcpConnectionState.TcpConnectionStageConnected;
channelToken = generateChannelToken();
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", String.format(this + " Connected (%s:%d)", hostAddress, hostPort));
}
FileLog.d("tmessages", String.format(TcpConnection.this + " Connected (%s:%d)", hostAddress, hostPort));
if (delegate != null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
@ -381,23 +463,11 @@ public class TcpConnection extends PyroClientAdapter {
}
});
}
while (packetsQueue.size() != 0) {
byte[] packet = packetsQueue.poll();
ByteBuffer sendBuffer = ByteBuffer.allocate((firstPacket ? 1 : 0) + packet.length);
sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (firstPacket) {
sendBuffer.put((byte)0xef);
firstPacket = false;
}
sendBuffer.put(packet);
sendBuffer.rewind();
client.write(sendBuffer);
}
}
@Override
public void unconnectableClient(PyroClient client) {
handleDisconnect(client, null);
public void unconnectableClient(PyroClient client, Exception cause) {
handleDisconnect(client, cause);
}
@Override
@ -417,9 +487,7 @@ public class TcpConnection extends PyroClientAdapter {
failedConnectionCount = 0;
readData(data);
} catch (Exception e) {
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", "read data error");
}
FileLog.d("tmessages", "read data error");
reconnect();
}
}
@ -427,8 +495,6 @@ public class TcpConnection extends PyroClientAdapter {
@Override
public void sentData(PyroClient client, int bytes) {
failedConnectionCount = 0;
if (ConnectionsManager.DEBUG_VERSION) {
Log.d("tmessages", this + " bytes sent " + bytes);
}
FileLog.d("tmessages", TcpConnection.this + " bytes sent " + bytes);
}
}

View File

@ -1,55 +0,0 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import java.util.ArrayList;
import java.util.HashMap;
public class UpdateDatacenterListAction extends Action {
public int datacenterId;
public UpdateDatacenterListAction(int id) {
datacenterId = id;
}
public void execute(HashMap params) {
TLRPC.TL_help_getConfig getConfig = new TLRPC.TL_help_getConfig();
ConnectionsManager.Instance.performRpc(getConfig, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (delegate == null) {
return;
}
if (error == null) {
TLRPC.TL_config config = (TLRPC.TL_config)response;
ArrayList<Datacenter> datacenters = new ArrayList<Datacenter>();
for (TLRPC.TL_dcOption datacenterDesc : config.dc_options) {
Datacenter datacenter = new Datacenter();
datacenter.datacenterId = datacenterDesc.id;
datacenter.authSessionId = (long)(MessagesController.random.nextDouble() * Long.MAX_VALUE);
datacenter.address = datacenterDesc.ip_address;
datacenter.port = datacenterDesc.port;
datacenters.add(datacenter);
}
HashMap<String, Object> result = new HashMap<String, Object>();
result.put("datacenters", datacenters);
delegate.ActionDidFinishExecution(UpdateDatacenterListAction.this, result);
} else {
delegate.ActionDidFailExecution(UpdateDatacenterListAction.this);
}
}
}, null, true, RPCRequest.RPCRequestClassEnableUnauthorized | RPCRequest.RPCRequestClassGeneric);
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -10,13 +10,13 @@ package org.telegram.messenger;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLRPC;
import org.telegram.ui.ApplicationLoader;
import java.io.File;
import java.io.FileOutputStream;
public class UserConfig {
public static TLRPC.User currentUser;
@ -24,8 +24,8 @@ public class UserConfig {
public static boolean clientActivated = false;
public static boolean registeredForPush = false;
public static String pushString = "";
public static int lastSendMessageId = -1;
public static int lastLocalId = -1;
public static int lastSendMessageId = -210000;
public static int lastLocalId = -210000;
public static String contactsHash = "";
public static String importHash = "";
private final static Integer sync = 1;
@ -41,45 +41,53 @@ public class UserConfig {
}
public static void saveConfig(boolean withFile) {
saveConfig(withFile, null);
}
public static void saveConfig(boolean withFile, File oldFile) {
synchronized (sync) {
SerializedData data = new SerializedData();
if (currentUser != null) {
data.writeInt32(2);
currentUser.serializeToStream(data);
clientUserId = currentUser.id;
clientActivated = true;
try {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("registeredForPush", registeredForPush);
editor.putString("pushString", pushString);
editor.putInt("lastSendMessageId", lastSendMessageId);
editor.putInt("lastLocalId", lastLocalId);
editor.putString("contactsHash", contactsHash);
editor.putString("importHash", importHash);
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
editor.commit();
} else {
data.writeInt32(0);
}
if (withFile) {
try {
File configFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "user.dat");
if (!configFile.exists()) {
configFile.createNewFile();
if (currentUser != null) {
editor.putBoolean("registeredForPush", registeredForPush);
editor.putString("pushString", pushString);
editor.putInt("lastSendMessageId", lastSendMessageId);
editor.putInt("lastLocalId", lastLocalId);
editor.putString("contactsHash", contactsHash);
editor.putString("importHash", importHash);
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
if (withFile) {
SerializedData data = new SerializedData();
currentUser.serializeToStream(data);
clientUserId = currentUser.id;
clientActivated = true;
String userString = Base64.encodeToString(data.toByteArray(), Base64.DEFAULT);
editor.putString("user", userString);
}
FileOutputStream stream = new FileOutputStream(configFile);
stream.write(data.toByteArray());
stream.close();
} catch (Exception e) {
e.printStackTrace();
} else {
editor.putBoolean("registeredForPush", registeredForPush);
editor.putString("pushString", pushString);
editor.putInt("lastSendMessageId", lastSendMessageId);
editor.putInt("lastLocalId", lastLocalId);
editor.putString("contactsHash", contactsHash);
editor.putString("importHash", importHash);
editor.putBoolean("saveIncomingPhotos", saveIncomingPhotos);
editor.remove("user");
}
editor.commit();
if (oldFile != null) {
oldFile.delete();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
public static void loadConfig() {
synchronized (sync) {
File configFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "user.dat");
final File configFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "user.dat");
if (configFile.exists()) {
try {
SerializedData data = new SerializedData(configFile);
@ -113,6 +121,12 @@ public class UserConfig {
MessagesStorage.secretPBytes = data.readByteArray();
}
MessagesStorage.secretG = data.readInt32();
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
saveConfig(true, configFile);
}
});
} else if (ver == 2) {
int constructor = data.readInt32();
currentUser = (TLRPC.TL_userSelf)TLClassStore.Instance().TLdeserialize(data, constructor);
@ -122,14 +136,49 @@ public class UserConfig {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
registeredForPush = preferences.getBoolean("registeredForPush", false);
pushString = preferences.getString("pushString", "");
lastSendMessageId = preferences.getInt("lastSendMessageId", -1);
lastLocalId = preferences.getInt("lastLocalId", -1);
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
lastLocalId = preferences.getInt("lastLocalId", -210000);
contactsHash = preferences.getString("contactsHash", "");
importHash = preferences.getString("importHash", "");
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
}
if (lastLocalId > -210000) {
lastLocalId = -210000;
}
if (lastSendMessageId > -210000) {
lastSendMessageId = -210000;
}
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
saveConfig(true, configFile);
}
});
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
} else {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
registeredForPush = preferences.getBoolean("registeredForPush", false);
pushString = preferences.getString("pushString", "");
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
lastLocalId = preferences.getInt("lastLocalId", -210000);
contactsHash = preferences.getString("contactsHash", "");
importHash = preferences.getString("importHash", "");
saveIncomingPhotos = preferences.getBoolean("saveIncomingPhotos", false);
String user = preferences.getString("user", null);
if (user != null) {
byte[] userBytes = Base64.decode(user, Base64.DEFAULT);
if (userBytes != null) {
SerializedData data = new SerializedData(userBytes);
currentUser = (TLRPC.TL_userSelf)TLClassStore.Instance().TLdeserialize(data, data.readInt32());
clientUserId = currentUser.id;
clientActivated = true;
}
}
if (currentUser == null) {
clientActivated = false;
clientUserId = 0;
}
}
}
@ -141,10 +190,11 @@ public class UserConfig {
currentUser = null;
registeredForPush = false;
contactsHash = "";
lastLocalId = -1;
lastLocalId = -210000;
importHash = "";
lastSendMessageId = -1;
lastSendMessageId = -210000;
saveIncomingPhotos = false;
saveConfig(true);
MessagesController.Instance.deleteAllAppAccounts();
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -20,7 +20,6 @@ import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@ -53,6 +52,7 @@ import javax.crypto.Cipher;
public class Utilities {
public static Handler applicationHandler;
public static int statusBarHeight = 0;
private final static Integer lock = 1;
public static class TPFactorizedValue {
@ -63,7 +63,7 @@ public class Utilities {
public static DispatchQueue globalQueue = new DispatchQueue("globalQueue");
public static DispatchQueue cacheOutQueue = new DispatchQueue("cacheOutQueue");
public static DispatchQueue imageLoadQueue = new DispatchQueue("imageLoadQueue");
public static DispatchQueue fileUploadQueue = new DispatchQueue("imageLoadQueue");
public static DispatchQueue fileUploadQueue = new DispatchQueue("fileUploadQueue");
public native static long doPQNative(long _what);
public native static byte[] aesIgeEncryption(byte[] _what, byte[] _key, byte[] _iv, boolean encrypt, boolean changeIv);
@ -101,7 +101,7 @@ public class Utilities {
return result;
} else {
Log.e("tmessages", String.format("**** Factorization failed for %d", what));
FileLog.e("tmessages", String.format("**** Factorization failed for %d", what));
TPFactorizedValue result = new TPFactorizedValue();
result.p = 0;
result.q = 0;
@ -113,8 +113,8 @@ public class Utilities {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
return md.digest(convertme);
} catch (Throwable e) {
e.printStackTrace();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return null;
}
@ -128,7 +128,7 @@ public class Utilities {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return null;
}
@ -219,7 +219,7 @@ public class Utilities {
SerializedData stream = new SerializedData(bytesOutput.toByteArray());
return TLClassStore.Instance().TLdeserialize(stream, stream.readInt32(), parentObject);
} catch (IOException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return null;
}
@ -235,8 +235,7 @@ public class Utilities {
assetPath);
cache.put(assetPath, t);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface '" + assetPath
+ "' because " + e.getMessage());
FileLog.e(TAG, "Could not get typeface '" + assetPath + "' because " + e.getMessage());
return null;
}
}
@ -258,8 +257,7 @@ public class Utilities {
if (view == null) {
return false;
}
InputMethodManager inputManager = (InputMethodManager) view
.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.isActive(view);
}
@ -267,10 +265,10 @@ public class Utilities {
if (view == null) {
return;
}
InputMethodManager imm = (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (!imm.isActive())
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (!imm.isActive()) {
return;
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
@ -279,18 +277,21 @@ public class Utilities {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog = new ProgressDialog(activity);
if (message != null) {
progressDialog.setMessage(message);
if(!activity.isFinishing()) {
progressDialog = new ProgressDialog(activity);
if (message != null) {
progressDialog.setMessage(message);
}
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
});
}
public static FastDateFormat formatterDay;
public static FastDateFormat formatterWeek;
public static FastDateFormat formatterMonth;
public static FastDateFormat formatterYear;
public static FastDateFormat formatterYearMax;
@ -300,11 +301,21 @@ public class Utilities {
static {
Locale locale = Locale.getDefault();
String lang = locale.getLanguage();
formatterMonth = FastDateFormat.getInstance("dd MMM", locale);
formatterYear = FastDateFormat.getInstance("dd.MM.yy", locale);
formatterYearMax = FastDateFormat.getInstance("dd.MM.yyyy", locale);
chatDate = FastDateFormat.getInstance("d MMMM", locale);
chatFullDate = FastDateFormat.getInstance("d MMMM yyyy", locale);
if (lang.equals("en")) {
formatterMonth = FastDateFormat.getInstance("MMM dd", locale);
formatterYear = FastDateFormat.getInstance("dd.MM.yy", locale);
formatterYearMax = FastDateFormat.getInstance("dd.MM.yyyy", locale);
chatDate = FastDateFormat.getInstance("MMMM d", locale);
chatFullDate = FastDateFormat.getInstance("MMMM d, yyyy", locale);
} else {
formatterMonth = FastDateFormat.getInstance("dd MMM", locale);
formatterYear = FastDateFormat.getInstance("dd.MM.yy", locale);
formatterYearMax = FastDateFormat.getInstance("dd.MM.yyyy", locale);
chatDate = FastDateFormat.getInstance("d MMMM", locale);
chatFullDate = FastDateFormat.getInstance("d MMMM yyyy", locale);
}
formatterWeek = FastDateFormat.getInstance("EEE", locale);
if (lang != null) {
if (DateFormat.is24HourFormat(ApplicationLoader.applicationContext)) {
formatterDay = FastDateFormat.getInstance("HH:mm", locale);
@ -394,7 +405,7 @@ public class Utilities {
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
result = false;
} finally {
if(source != null) {
@ -418,20 +429,20 @@ public class Utilities {
public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002};
public static int[] arrUsersAvatars = {
R.drawable.user_placeholder_red,
R.drawable.user_placeholder_green,
R.drawable.user_placeholder_yellow,
R.drawable.user_placeholder_blue,
R.drawable.user_placeholder_purple,
R.drawable.user_placeholder_pink,
R.drawable.user_placeholder_cyan,
R.drawable.user_placeholder_orange};
R.drawable.user_red,
R.drawable.user_green,
R.drawable.user_yellow,
R.drawable.user_blue,
R.drawable.user_violet,
R.drawable.user_pink,
R.drawable.user_aqua,
R.drawable.user_orange};
public static int[] arrGroupsAvatars = {
R.drawable.group_placeholder_green,
R.drawable.group_placeholder_red,
R.drawable.group_placeholder_blue,
R.drawable.group_placeholder_yellow};
R.drawable.group_green,
R.drawable.group_red,
R.drawable.group_blue,
R.drawable.group_yellow};
public static int getColorIndex(int id) {
int[] arr;
@ -458,7 +469,7 @@ public class Utilities {
}
return Math.abs(b) % arr.length;
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return id % arr.length;
}
@ -491,7 +502,7 @@ public class Utilities {
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return null;
}
@ -523,14 +534,13 @@ public class Utilities {
if (storageDir != null) {
if (! storageDir.mkdirs()) {
if (! storageDir.exists()){
Log.d("tmessages", "failed to create directory");
FileLog.d("tmessages", "failed to create directory");
return null;
}
}
}
} else {
Log.v("tmessages", "External storage is not mounted READ/WRITE.");
FileLog.d("tmessages", "External storage is not mounted READ/WRITE.");
}
return storageDir;
@ -543,7 +553,7 @@ public class Utilities {
String imageFileName = "IMG_" + timeStamp + "_";
return File.createTempFile(imageFileName, ".jpg", storageDir);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return null;
}
@ -560,6 +570,7 @@ public class Utilities {
} else if (name2 != null && name2.length() != 0) {
wholeString += " " + name2;
}
wholeString = wholeString.trim();
String[] args = wholeString.split(" ");
for (String arg : args) {
@ -571,7 +582,7 @@ public class Utilities {
builder.append(" ");
}
String query = str.substring(0, q.length());
builder.append(Html.fromHtml("<font color=\"#1274c9\">" + query + "</font>"));
builder.append(Html.fromHtml("<font color=\"#357aa8\">" + query + "</font>"));
str = str.substring(q.length());
builder.append(str);
} else {
@ -597,7 +608,7 @@ public class Utilities {
return new File(ApplicationLoader.applicationContext.getCacheDir(), fileName);
*/
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return null;
}
@ -611,4 +622,26 @@ public class Utilities {
}
return result;
}
public static String stringForMessageListDate(long date) {
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date * 1000);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (year != dateYear) {
return 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));
} else if(dayDiff > -7 && dayDiff <= -1) {
return formatterWeek.format(new Date(date * 1000));
} else {
return formatterMonth.format(new Date(date * 1000));
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -43,59 +43,147 @@ public class MessageObject {
fromUser = MessagesController.Instance.users.get(message.from_id);
}
if (message.action instanceof TLRPC.TL_messageActionChatCreate) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionCreateGroup).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (message.from_id == UserConfig.clientUserId) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionCreateGroup).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionCreateGroup).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionCreateGroup).replace("un1", "");
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) {
if (message.action.user_id == message.from_id) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionLeftUser).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (message.from_id == UserConfig.clientUserId) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionLeftUser).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionLeftUser).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionLeftUser).replace("un1", "");
}
}
} else {
TLRPC.User who = users.get(message.action.user_id);
String str = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionKickUser);
messageText = str.replace("un2", Utilities.formatName(who.first_name, who.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (who == null) {
MessagesController.Instance.users.get(message.action.user_id);
}
String str = ApplicationLoader.applicationContext.getString(R.string.ActionKickUser);
if (who != null && fromUser != null) {
if (message.from_id == UserConfig.clientUserId) {
messageText = str.replace("un2", Utilities.formatName(who.first_name, who.last_name)).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else if (message.action.user_id == UserConfig.clientUserId) {
messageText = str.replace("un2", ApplicationLoader.applicationContext.getString(R.string.FromYou)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = str.replace("un2", Utilities.formatName(who.first_name, who.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
}
} else {
messageText = str.replace("un2", "").replace("un1", "");
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatAddUser) {
TLRPC.User whoUser = users.get(message.action.user_id);
String str = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionAddUser);
messageText = str.replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (whoUser == null) {
MessagesController.Instance.users.get(message.action.user_id);
}
String str = ApplicationLoader.applicationContext.getString(R.string.ActionAddUser);
if (whoUser != null && fromUser != null) {
if (message.from_id == UserConfig.clientUserId) {
messageText = str.replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else if (message.action.user_id == UserConfig.clientUserId) {
messageText = str.replace("un2", ApplicationLoader.applicationContext.getString(R.string.FromYou)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = str.replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
}
} else {
messageText = str.replace("un2", "").replace("un1", "");
}
} else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
photoThumbs = new ArrayList<PhotoObject>();
for (TLRPC.PhotoSize size : message.action.photo.sizes) {
photoThumbs.add(new PhotoObject(size));
}
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionChangedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (message.from_id == UserConfig.clientUserId) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedPhoto).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedPhoto).replace("un1", "");
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatEditTitle) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionChangedTitle).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
if (message.from_id == UserConfig.clientUserId) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedTitle).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou)).replace("un2", message.action.title);
} else {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedTitle).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionChangedTitle).replace("un1", "").replace("un2", message.action.title);
}
}
} else if (message.action instanceof TLRPC.TL_messageActionChatDeletePhoto) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.ActionRemovedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
if (message.from_id == UserConfig.clientUserId) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionRemovedPhoto).replace("un1", ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionRemovedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.ActionRemovedPhoto).replace("un1", "");
}
}
} else if (message.action instanceof TLRPC.TL_messageActionTTLChange) {
if (message.action.ttl != 0) {
String timeString;
if (message.action.ttl == 2) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime2s);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime2s);
} else if (message.action.ttl == 5) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime5s);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime5s);
} else if (message.action.ttl == 60) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime1m);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime1m);
} else if (message.action.ttl == 60 * 60) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime1h);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime1h);
} else if (message.action.ttl == 60 * 60 * 24) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime1d);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime1d);
} else if (message.action.ttl == 60 * 60 * 24 * 7) {
timeString = ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetime1w);
timeString = ApplicationLoader.applicationContext.getString(R.string.MessageLifetime1w);
} else {
timeString = String.format("%d", message.action.ttl);
}
if (message.from_id == UserConfig.clientUserId) {
messageText = String.format(ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetimeChangedOutgoing), timeString);
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeChangedOutgoing), timeString);
} else {
messageText = String.format(ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetimeChanged), fromUser.first_name, timeString);
if (fromUser != null) {
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeChanged), fromUser.first_name, timeString);
} else {
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeChanged), "", timeString);
}
}
} else {
if (message.from_id == UserConfig.clientUserId) {
messageText = String.format(ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetimeRemoved), ApplicationLoader.applicationContext.getResources().getString(R.string.FromYou));
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeRemoved), ApplicationLoader.applicationContext.getString(R.string.FromYou));
} else {
messageText = String.format(ApplicationLoader.applicationContext.getResources().getString(R.string.MessageLifetimeRemoved), fromUser.first_name);
if (fromUser != null) {
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeRemoved), fromUser.first_name);
} else {
messageText = String.format(ApplicationLoader.applicationContext.getString(R.string.MessageLifetimeRemoved), "");
}
}
}
} else if (message.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
messageText = ApplicationLoader.applicationContext.getString(R.string.NotificationUnrecognizedDevice, message.action.title, message.action.address);
} else if (message.action instanceof TLRPC.TL_messageActionUserJoined) {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.NotificationContactJoined, Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.NotificationContactJoined, "");
}
} else if (message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
if (fromUser != null) {
messageText = ApplicationLoader.applicationContext.getString(R.string.NotificationContactNewPhoto, Utilities.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = ApplicationLoader.applicationContext.getString(R.string.NotificationContactNewPhoto, "");
}
}
}
} else if (message.media != null && !(message.media instanceof TLRPC.TL_messageMediaEmpty)) {
@ -108,7 +196,7 @@ public class MessageObject {
imagePreview = obj.image;
}
}
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.AttachPhoto);
messageText = ApplicationLoader.applicationContext.getString(R.string.AttachPhoto);
} else if (message.media instanceof TLRPC.TL_messageMediaVideo) {
photoThumbs = new ArrayList<PhotoObject>();
PhotoObject obj = new PhotoObject(message.media.video.thumb);
@ -116,11 +204,13 @@ public class MessageObject {
if (imagePreview == null && obj.image != null) {
imagePreview = obj.image;
}
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.AttachVideo);
messageText = ApplicationLoader.applicationContext.getString(R.string.AttachVideo);
} else if (message.media instanceof TLRPC.TL_messageMediaGeo) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.AttachLocation);
messageText = ApplicationLoader.applicationContext.getString(R.string.AttachLocation);
} else if (message.media instanceof TLRPC.TL_messageMediaContact) {
messageText = ApplicationLoader.applicationContext.getResources().getString(R.string.AttachContact);
messageText = ApplicationLoader.applicationContext.getString(R.string.AttachContact);
} else if (message.media instanceof TLRPC.TL_messageMediaUnsupported) {
messageText = ApplicationLoader.applicationContext.getString(R.string.UnsuppotedMedia);
}
} else {
messageText = message.message;
@ -159,9 +249,15 @@ public class MessageObject {
} else {
type = 13;
}
} else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaUnsupported) {
if (message.from_id == UserConfig.clientUserId) {
type = 0;
} else {
type = 1;
}
}
} else if (message instanceof TLRPC.TL_messageService) {
if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) {
if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto || message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
type = 11;
} else {
type = 10;

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -41,6 +41,9 @@ public class PhotoObject {
int closestHeight = 9999;
PhotoObject closestObject = null;
for (PhotoObject obj : arr) {
if (obj == null || obj.photoOwner == null) {
continue;
}
int diffW = Math.abs(obj.photoOwner.w - width);
int diffH = Math.abs(obj.photoOwner.h - height);
if (closestObject == null || closestWidth > diffW && closestHeight > diffH || closestObject.photoOwner instanceof TLRPC.TL_photoCachedSize) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -13,25 +13,22 @@ import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.view.Display;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.internal.app.ActionBarImpl;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
@ -47,22 +44,28 @@ import net.hockeyapp.android.UpdateManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ApplicationActivity extends SherlockFragmentActivity implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
private View shadowView;
public class ApplicationActivity extends ActionBarActivity implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
private boolean finished = false;
private NotificationView notificationView;
String photoPath = null;
String videoPath = null;
String sendingText = null;
private String photoPath = null;
private String videoPath = null;
private String sendingText = null;
private int currentConnectionState;
private View statusView;
private View backStatusButton;
private View statusBackground;
private TextView statusText;
private View containerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
Utilities.statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
NotificationCenter.Instance.postNotificationName(702, this);
currentConnectionState = ConnectionsManager.Instance.connectionState;
for (BaseFragment fragment : ApplicationLoader.fragmentsStack) {
@ -71,12 +74,11 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
if (parent != null) {
parent.removeView(fragment.fragmentView);
}
fragment.parentActivity = null;
fragment.fragmentView = null;
}
fragment.parentActivity = this;
}
setContentView(R.layout.application_layout);
shadowView = findViewById(R.id.shadow);
NotificationCenter.Instance.addObserver(this, 1234);
NotificationCenter.Instance.addObserver(this, 658);
NotificationCenter.Instance.addObserver(this, 701);
@ -88,6 +90,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
statusView = getLayoutInflater().inflate(R.layout.updating_state_layout, null);
statusBackground = statusView.findViewById(R.id.back_button_background);
backStatusButton = statusView.findViewById(R.id.back_button);
containerView = findViewById(R.id.container);
statusText = (TextView)statusView.findViewById(R.id.status_text);
statusBackground.setOnClickListener(new View.OnClickListener() {
@Override
@ -125,7 +128,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
}
} else if (push_chat_id != 0) {
@ -136,7 +139,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
ChatActivity fragment = new ChatActivity();
@ -146,7 +149,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
if (fragment.onFragmentCreate()) {
pushOpened = true;
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
}
if (videoPath != null || photoPath != null || sendingText != null) {
@ -175,14 +178,16 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
}
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
getWindow().setFormat(PixelFormat.RGB_565);
}
@SuppressWarnings("unchecked")
private void prepareForHideShowActionBar() {
try {
Class aClass = getSupportActionBar().getClass();
if (aClass == ActionBarImpl.class) {
Method method = aClass.getDeclaredMethod("setShowHideAnimationEnabled", boolean.class);
Class firstClass = getSupportActionBar().getClass();
Class aClass = firstClass.getSuperclass();
if (aClass == android.support.v7.app.ActionBar.class) {
Method method = firstClass.getDeclaredMethod("setShowHideAnimationEnabled", boolean.class);
method.invoke(getSupportActionBar(), false);
} else {
Field field = aClass.getDeclaredField("mActionBar");
@ -190,20 +195,18 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
Method method = field.get(getSupportActionBar()).getClass().getDeclaredMethod("setShowHideAnimationEnabled", boolean.class);
method.invoke(field.get(getSupportActionBar()), false);
}
} catch (Exception exception) {
exception.printStackTrace();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void showActionBar() {
prepareForHideShowActionBar();
shadowView.setVisibility(View.VISIBLE);
getSupportActionBar().show();
}
public void hideActionBar() {
prepareForHideShowActionBar();
shadowView.setVisibility(View.INVISIBLE);
getSupportActionBar().hide();
}
@ -241,7 +244,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
}
} else if (push_chat_id != 0) {
@ -251,7 +254,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
ChatActivity fragment = new ChatActivity();
@ -260,7 +263,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
fragment.setArguments(bundle);
if (fragment.onFragmentCreate()) {
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
}
if (open_settings != 0) {
@ -284,13 +287,13 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
bundle.putInt("user_id", lower_part);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_user_" + lower_part, true, false);
presentFragment(fragment, "chat" + Math.random(), true, false);
} else if (lower_part < 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
bundle.putInt("chat_id", -lower_part);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_group_" + -lower_part, true, false);
presentFragment(fragment, "chat" + Math.random(), true, false);
}
} else {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
@ -298,7 +301,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
bundle.putInt("enc_id", chat_id);
fragment.setArguments(bundle);
fragment.scrollToTopOnResume = true;
presentFragment(fragment, "chat_enc_" + chat_id, true, false);
presentFragment(fragment, "chat" + Math.random(), true, false);
}
if (photoPath != null) {
fragment.processSendingPhoto(photoPath);
@ -318,7 +321,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
}
private void checkForUpdates() {
if (ConnectionsManager.DEBUG_VERSION) {
if (FileLog.DEBUG_VERSION) {
UpdateManager.register(this, "your-hockeyapp-api-key-here");
}
}
@ -347,14 +350,14 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
fixLayout();
checkForCrashes();
checkForUpdates();
ApplicationLoader.lastPauseTime = 0;
invalidateOptionsMenu();
ApplicationLoader.resetLastPauseTime();
supportInvalidateOptionsMenu();
updateActionBar();
try {
NotificationManager mNotificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
@ -383,14 +386,13 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
}
private void fixLayout() {
if (shadowView != null) {
ViewTreeObserver obs = shadowView.getViewTreeObserver();
if (containerView != null) {
ViewTreeObserver obs = containerView.getViewTreeObserver();
obs.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int rotation = manager.getDefaultDisplay().getRotation();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
int height;
@ -408,13 +410,10 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
notificationView.applyOrientationPaddings(rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90, density, height);
}
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) shadowView.getLayoutParams();
params.setMargins(0, height, 0, 0);
shadowView.setLayoutParams(params);
if (Build.VERSION.SDK_INT < 16) {
shadowView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
containerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
shadowView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
containerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
@ -459,7 +458,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_user_" + push_user_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
} else if (push_chat_id != 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
@ -473,7 +472,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_group_" + push_chat_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
} else if (push_enc_id != 0) {
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
@ -487,7 +486,7 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
lastFragment.willBeHidden();
}
ApplicationLoader.fragmentsStack.add(fragment);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat_enc_" + push_enc_id).commitAllowingStateLoss();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "chat" + Math.random()).commitAllowingStateLoss();
}
}
} else if (id == 701) {
@ -502,12 +501,42 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
} else if (id == 703) {
int state = (Integer)args[0];
if (currentConnectionState != state) {
FileLog.e("tmessages", "switch to state " + state);
currentConnectionState = state;
updateActionBar();
}
}
}
public void fixBackButton() {
if(android.os.Build.VERSION.SDK_INT == 19) {
//workaround for back button dissapear
try {
Class firstClass = getSupportActionBar().getClass();
Class aClass = firstClass.getSuperclass();
if (aClass == android.support.v7.app.ActionBar.class) {
} else {
Field field = aClass.getDeclaredField("mActionBar");
field.setAccessible(true);
android.app.ActionBar bar = (android.app.ActionBar)field.get(getSupportActionBar());
field = bar.getClass().getDeclaredField("mActionView");
field.setAccessible(true);
View v = (View)field.get(bar);
aClass = v.getClass();
field = aClass.getDeclaredField("mHomeLayout");
field.setAccessible(true);
v = (View)field.get(v);
v.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar == null) {
@ -540,15 +569,32 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
}
if (currentConnectionState == 1) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.WaitingForNetwork) + "</font>"));
statusText.setText(getString(R.string.WaitingForNetwork));
} else if (currentConnectionState == 2) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.Connecting) + "</font>"));
statusText.setText(getString(R.string.Connecting));
} else if (currentConnectionState == 3) {
statusText.setText(Html.fromHtml("<font color='#006fc8'>" + getString(R.string.Updating) + "</font>"));
statusText.setText(getString(R.string.Updating));
}
if (actionBar.getCustomView() != statusView) {
actionBar.setCustomView(statusView);
}
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
try {
if (statusView.getLayoutParams() instanceof android.support.v7.app.ActionBar.LayoutParams) {
android.support.v7.app.ActionBar.LayoutParams statusParams = (android.support.v7.app.ActionBar.LayoutParams)statusView.getLayoutParams();
statusText.measure(View.MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.AT_MOST), 100);
statusParams.width = (int)(statusText.getMeasuredWidth() + 54 * density);
statusView.setLayoutParams(statusParams);
} else if (statusView.getLayoutParams() instanceof android.app.ActionBar.LayoutParams) {
android.app.ActionBar.LayoutParams statusParams = (android.app.ActionBar.LayoutParams)statusView.getLayoutParams();
statusText.measure(View.MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.AT_MOST), 100);
statusParams.width = (int)(statusText.getMeasuredWidth() + 54 * density);
statusView.setLayoutParams(statusParams);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@ -646,4 +692,13 @@ public class ApplicationActivity extends SherlockFragmentActivity implements Not
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
try {
super.onSaveInstanceState(outState);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -15,7 +15,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;
import android.view.ViewConfiguration;
import com.google.android.gms.common.ConnectionResult;
@ -25,6 +24,7 @@ import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.UserConfig;
@ -62,7 +62,7 @@ public class ApplicationLoader extends Application {
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
applicationContext = getApplicationContext();
Utilities.getTypeface("fonts/rlight.ttf");
Utilities.getTypeface("fonts/rmedium.ttf");
UserConfig.loadConfig();
SharedPreferences preferences = getSharedPreferences("Notifications", MODE_PRIVATE);
if (UserConfig.currentUser != null) {
@ -101,7 +101,7 @@ public class ApplicationLoader extends Application {
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
if (checkPlayServices()) {
@ -114,15 +114,18 @@ public class ApplicationLoader extends Application {
sendRegistrationIdToBackend(false);
}
} else {
Log.i("tmessages", "No valid Google Play Services APK found.");
FileLog.d("tmessages", "No valid Google Play Services APK found.");
}
PhoneFormat format = PhoneFormat.Instance;
lastPauseTime = System.currentTimeMillis() - 5000;
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", "start application with time " + lastPauseTime);
}
lastPauseTime = System.currentTimeMillis();
FileLog.e("tmessages", "start application with time " + lastPauseTime);
}
public static void resetLastPauseTime() {
lastPauseTime = 0;
ConnectionsManager.Instance.applicationMovedToForeground();
}
private boolean checkPlayServices() {
@ -143,13 +146,13 @@ public class ApplicationLoader extends Application {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.length() == 0) {
Log.i("tmessages", "Registration not found.");
FileLog.d("tmessages", "Registration not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.i("tmessages", "App version changed.");
FileLog.d("tmessages", "App version changed.");
return "";
}
return registrationId;
@ -172,17 +175,29 @@ public class ApplicationLoader extends Application {
AsyncTask<String, String, Boolean> task = new AsyncTask<String, String, Boolean>() {
@Override
protected Boolean doInBackground(String... objects) {
String msg;
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(applicationContext);
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(applicationContext);
}
int count = 0;
while (count < 1000) {
try {
count++;
regid = gcm.register(SENDER_ID);
sendRegistrationIdToBackend(true);
storeRegistrationId(applicationContext, regid);
return true;
} catch (IOException e) {
FileLog.e("tmessages", e);
}
try {
if (count % 20 == 0) {
Thread.sleep(60000 * 30);
} else {
Thread.sleep(5000);
}
} catch (InterruptedException e) {
FileLog.e("tmessages", e);
}
regid = gcm.register(SENDER_ID);
sendRegistrationIdToBackend(true);
storeRegistrationId(applicationContext, regid);
return true;
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
@ -196,7 +211,12 @@ public class ApplicationLoader extends Application {
UserConfig.pushString = regid;
UserConfig.registeredForPush = !isNew;
UserConfig.saveConfig(false);
MessagesController.Instance.registerForPush(regid);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
MessagesController.Instance.registerForPush(regid);
}
});
}
});
}
@ -204,7 +224,7 @@ public class ApplicationLoader extends Application {
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i("tmessages", "Saving regId on app version " + appVersion);
FileLog.e("tmessages", "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -20,14 +20,15 @@ import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.internal.view.SupportMenuItem;
import android.support.v7.app.ActionBar;
import android.text.Html;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
@ -35,16 +36,12 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.AvatarUpdater;
@ -83,7 +80,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
MessagesController.Instance.getMediaCount(-chat_id, classGuid, true);
avatarUpdater.delegate = new AvatarUpdater.AvatarUpdaterDelegate() {
@Override
public void didUploadedPhoto(TLRPC.TL_inputFile file, TLRPC.PhotoSize small, TLRPC.PhotoSize big) {
public void didUploadedPhoto(TLRPC.InputFile file, TLRPC.PhotoSize small, TLRPC.PhotoSize big) {
if (chat_id != 0) {
MessagesController.Instance.changeChatAvatar(chat_id, file);
}
@ -163,45 +160,34 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
editor.putBoolean(key, !value);
editor.commit();
listView.invalidateViews();
TLRPC.TL_account_updateNotifySettings req = new TLRPC.TL_account_updateNotifySettings();
req.settings = new TLRPC.TL_inputPeerNotifySettings();
req.settings.sound = "";
req.peer = new TLRPC.TL_inputNotifyPeer();
((TLRPC.TL_inputNotifyPeer)req.peer).peer = new TLRPC.TL_inputPeerChat();
((TLRPC.TL_inputNotifyPeer)req.peer).peer.chat_id = chat_id;
req.settings.show_previews = true;
req.settings.events_mask = 1;
if (value) {
req.settings.mute_until = (int)(System.currentTimeMillis() / 1000) + 10 * 365 * 24 * 60 * 60;
} else {
req.settings.mute_until = 0;
}
ConnectionsManager.Instance.performRpc(req, null, null, true, RPCRequest.RPCRequestClassGeneric);
} else if (i == 3) {
Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
SharedPreferences preferences = parentActivity.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
Uri currentSound = null;
try {
Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
SharedPreferences preferences = parentActivity.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
Uri currentSound = null;
String defaultPath = null;
Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
if (defaultUri != null) {
defaultPath = defaultUri.getPath();
}
String path = preferences.getString("sound_chat_path_" + chat_id, defaultPath);
if (path != null && !path.equals("NoSound")) {
if (path.equals(defaultPath)) {
currentSound = defaultUri;
} else {
currentSound = Uri.parse(path);
String defaultPath = null;
Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
if (defaultUri != null) {
defaultPath = defaultUri.getPath();
}
}
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentSound);
startActivityForResult(tmpIntent, 15);
String path = preferences.getString("sound_chat_path_" + chat_id, defaultPath);
if (path != null && !path.equals("NoSound")) {
if (path.equals(defaultPath)) {
currentSound = defaultUri;
} else {
currentSound = Uri.parse(path);
}
}
tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentSound);
startActivityForResult(tmpIntent, 15);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else if (i == 5) {
MediaActivity fragment = new MediaActivity();
Bundle bundle = new Bundle();
@ -330,10 +316,10 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setCustomView(null);
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.GroupInfo) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.GroupInfo));
actionBar.setSubtitle(null);
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -342,12 +328,13 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
title.setCompoundDrawablePadding(0);
}
((ApplicationActivity)parentActivity).fixBackButton();
}
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
if (listViewAdapter != null) {
@ -355,44 +342,6 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
}
((ApplicationActivity)parentActivity).showActionBar();
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
if (listView != null) {
ViewTreeObserver obs = listView.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager)parentActivity.getSystemService(Activity.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
listView.setPadding(listView.getPaddingLeft(), height, listView.getPaddingRight(), listView.getPaddingBottom());
listView.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
@ -402,9 +351,6 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
case android.R.id.home:
finishFragment();
break;
case R.id.block_user:
openAddMenu();
break;
}
return true;
}
@ -466,7 +412,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
if (action == 0) {
TLRPC.Chat chat = MessagesController.Instance.chats.get(chat_id);
if (chat.photo != null && chat.photo.photo_big != null) {
NotificationCenter.Instance.addToMemCache(3, chat.photo.photo_big);
NotificationCenter.Instance.addToMemCache(53, chat.photo.photo_big);
Intent intent = new Intent(parentActivity, GalleryImageViewer.class);
startActivity(intent);
}
@ -506,15 +452,23 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
} else {
NotificationCenter.Instance.removeObserver(this, MessagesController.closeChats);
NotificationCenter.Instance.postNotificationName(MessagesController.closeChats);
MessagesController.Instance.deleteDialog(-chat_id, 0, false);
MessagesController.Instance.deleteUserFromChat(chat_id, UserConfig.clientUserId, info);
MessagesController.Instance.deleteDialog(-chat_id, 0, false);
finishFragment();
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.settings_block_users_bar_menu, menu);
inflater.inflate(R.menu.group_profile_menu, menu);
SupportMenuItem doneItem = (SupportMenuItem)menu.findItem(R.id.block_user);
TextView doneTextView = (TextView)doneItem.getActionView().findViewById(R.id.done_button);
doneTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openAddMenu();
}
});
}
private class ListAdapter extends BaseAdapter {
@ -571,9 +525,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.chat_profile_avatar_layout, viewGroup, false);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
onlineText = (TextView)view.findViewById(R.id.settings_online);
onlineText.setTypeface(typeface);
ImageButton button = (ImageButton)view.findViewById(R.id.settings_edit_name);
button.setOnClickListener(new View.OnClickListener() {
@ -636,11 +588,13 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
}
avatarImage = (BackupImageView)view.findViewById(R.id.settings_avatar_image);
TextView textView = (TextView)view.findViewById(R.id.settings_name);
Typeface typeface = Utilities.getTypeface("fonts/rmedium.ttf");
textView.setTypeface(typeface);
textView.setText(chat.title);
if (chat.participants_count != 0 && onlineCount > 0) {
onlineText.setText(Html.fromHtml(String.format("%d %s, <font color='#006fc8'>%d %s</font>", chat.participants_count, getStringEntry(R.string.Members), onlineCount, getStringEntry(R.string.Online))));
onlineText.setText(Html.fromHtml(String.format("%d %s, <font color='#357aa8'>%d %s</font>", chat.participants_count, getStringEntry(R.string.Members), onlineCount, getStringEntry(R.string.Online))));
} else {
onlineText.setText(String.format("%d %s", chat.participants_count, getStringEntry(R.string.Members)));
}
@ -692,8 +646,6 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
}
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
detailTextView.setTypeface(typeface);
View divider = view.findViewById(R.id.settings_row_divider);
if (i == 3) {
SharedPreferences preferences = mContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
@ -726,8 +678,6 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
if (holder == null) {
holder = new ContactsActivity.ContactListRowHolder(view);
view.setTag(holder);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
holder.nameTextView.setTypeface(typeface);
}
View divider = view.findViewById(R.id.settings_row_divider);
@ -741,19 +691,11 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
holder.nameTextView.setText(Html.fromHtml("<b>" + user.last_name + "</b>"));
}
if (info.admin_id != UserConfig.clientUserId && part.inviter_id != UserConfig.clientUserId && part.user_id != UserConfig.clientUserId) {
if(android.os.Build.VERSION.SDK_INT >= 11) {
holder.avatarImage.setAlpha(0.7f);
holder.nameTextView.setAlpha(0.7f);
holder.messageTextView.setAlpha(0.7f);
}
} else {
if(android.os.Build.VERSION.SDK_INT >= 11) {
holder.avatarImage.setAlpha(1.0f);
holder.nameTextView.setAlpha(1.0f);
holder.messageTextView.setAlpha(1.0f);
}
}
// if (info.admin_id != UserConfig.clientUserId && part.inviter_id != UserConfig.clientUserId && part.user_id != UserConfig.clientUserId) {
//
// } else {
//
// }
TLRPC.FileLocation photo = null;
if (user.photo != null) {
@ -768,7 +710,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
} else {
int currentTime = ConnectionsManager.Instance.getCurrentTime();
if ((user.status.expires > currentTime || user.status.was_online > currentTime || user.id == UserConfig.clientUserId) && user.status.expires != 0) {
holder.messageTextView.setTextColor(0xff006fc8);
holder.messageTextView.setTextColor(0xff357aa8);
holder.messageTextView.setText(getStringEntry(R.string.Online));
} else {
if (user.status.was_online <= 10000 && user.status.expires <= 10000) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -9,25 +9,19 @@
package org.telegram.ui;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Display;
import android.support.v7.app.ActionBar;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
@ -93,43 +87,6 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
return fragmentView;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
final View view = getView();
if (view != null) {
ViewTreeObserver obs = view.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager)parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
view.setPadding(view.getPaddingLeft(), height, view.getPaddingRight(), view.getPaddingBottom());
view.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
public boolean canApplyUpdateStatus() {
return false;
@ -144,6 +101,7 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setCustomView(R.layout.settings_do_action_layout);
View cancelButton = actionBar.getCustomView().findViewById(R.id.cancel_button);
@ -168,11 +126,11 @@ public class ChatProfileChangeNameActivity extends BaseFragment {
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean animations = preferences.getBoolean("view_animations", true);
if (!animations) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -9,27 +9,20 @@
package org.telegram.ui;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Display;
import android.support.v7.app.ActionBar;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
@ -42,6 +35,7 @@ import org.telegram.ui.Views.BaseFragment;
public class ContactAddActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private int user_id;
private String phone = null;
private View doneButton;
private EditText firstNameField;
private EditText lastNameField;
@ -54,6 +48,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
super.onFragmentCreate();
NotificationCenter.Instance.addObserver(this, MessagesController.updateInterfaces);
user_id = getArguments().getInt("user_id", 0);
phone = getArguments().getString("phone");
return true;
}
@ -63,23 +58,21 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
NotificationCenter.Instance.removeObserver(this, MessagesController.updateInterfaces);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (fragmentView == null) {
fragmentView = inflater.inflate(R.layout.contact_add_layout, container, false);
TLRPC.User user = MessagesController.Instance.users.get(user_id);
if (phone != null) {
user.phone = PhoneFormat.stripExceptNumbers(phone);
}
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
onlineText = (TextView)fragmentView.findViewById(R.id.settings_online);
onlineText.setTypeface(typeface);
avatarImage = (BackupImageView)fragmentView.findViewById(R.id.settings_avatar_image);
phoneText = (TextView)fragmentView.findViewById(R.id.settings_name);
Typeface typeface = Utilities.getTypeface("fonts/rmedium.ttf");
phoneText.setTypeface(typeface);
firstNameField = (EditText)fragmentView.findViewById(R.id.first_name_field);
firstNameField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@ -175,9 +168,10 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
ActionBar actionBar = parentActivity.getSupportActionBar();
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -213,11 +207,10 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean animations = preferences.getBoolean("view_animations", true);
@ -227,43 +220,6 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
final View view = getView();
if (view != null) {
ViewTreeObserver obs = view.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager)parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
view.setPadding(view.getPaddingLeft(), height, view.getPaddingRight(), view.getPaddingBottom());
view.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (nextAnim != 0) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -12,32 +12,28 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.internal.view.SupportMenuItem;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.SearchView;
import android.text.Html;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.widget.SearchView;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
@ -49,6 +45,8 @@ import org.telegram.ui.Views.OnSwipeTouchListener;
import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
@ -71,7 +69,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
private SearchView searchView;
private TextView epmtyTextView;
private HashMap<Integer, TLRPC.User> ignoreUsers;
MenuItem searchItem;
private SupportMenuItem searchItem;
private boolean isRTL;
private Timer searchDialogsTimer;
@ -170,7 +168,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
Bundle bundle = new Bundle();
bundle.putInt("user_id", user_id);
fragment.setArguments(bundle);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat_user_" + user_id, destroyAfterSelect, false);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat" + Math.random(), destroyAfterSelect, false);
}
}
} else {
@ -191,7 +189,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
intent.putExtra(Intent.EXTRA_TEXT, getStringEntry(R.string.InviteText));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
return;
} else {
@ -222,7 +220,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
Bundle bundle = new Bundle();
bundle.putInt("user_id", uid);
fragment.setArguments(bundle);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat_user_" + uid, destroyAfterSelect, false);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat" + Math.random(), destroyAfterSelect, false);
}
}
} else {
@ -247,7 +245,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
Bundle bundle = new Bundle();
bundle.putInt("user_id", cLocal.user_id);
fragment.setArguments(bundle);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat_user_" + cLocal.user_id, destroyAfterSelect, false);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat" + Math.random(), destroyAfterSelect, false);
}
return;
}
@ -260,12 +258,11 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
@Override
public void onClick(DialogInterface dialogInterface, int i) {
try {
String number = arg1;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromParts("sms", number, null));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromParts("sms", arg1, null));
intent.putExtra("sms_body", getStringEntry(R.string.InviteText));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -305,12 +302,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
return fragmentView;
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void didSelectResult(final int user_id, boolean useAlert) {
if (useAlert && selectAlertString != 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity);
@ -339,39 +330,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
}
}
private void fixLayout() {
if (listView != null) {
ViewTreeObserver obs = listView.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)listView.getLayoutParams();
params.setMargins(0, height, 0, 0);
listView.setLayoutParams(params);
listView.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
public void applySelfActionBar() {
if (parentActivity == null) {
@ -386,7 +344,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
actionBar.setCustomView(null);
actionBar.setSubtitle(null);
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -397,10 +355,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
}
if (destroyAfterSelect) {
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.SelectContact) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.SelectContact));
} else {
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.Contacts) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.Contacts));
}
((ApplicationActivity)parentActivity).fixBackButton();
}
@Override
@ -409,7 +369,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
if (isFinish) {
return;
}
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
if (!firstStart && listViewAdapter != null) {
@ -418,7 +378,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
firstStart = false;
((ApplicationActivity)parentActivity).showActionBar();
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
}
public void searchDialogs(final String query) {
@ -431,7 +390,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
searchDialogsTimer.cancel();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
searchDialogsTimer = new Timer();
searchDialogsTimer.schedule(new TimerTask() {
@ -441,7 +400,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
searchDialogsTimer.cancel();
searchDialogsTimer = null;
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
processSearch(query);
}
@ -453,14 +412,15 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (query.length() == 0) {
String q = query.trim().toLowerCase();
if (q.length() == 0) {
updateSearchResults(new ArrayList<TLRPC.User>(), new ArrayList<CharSequence>());
return;
}
long time = System.currentTimeMillis();
ArrayList<TLRPC.User> resultArray = new ArrayList<TLRPC.User>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<CharSequence>();
String q = query.toLowerCase();
for (TLRPC.TL_contact contact : MessagesController.Instance.contacts) {
TLRPC.User user = MessagesController.Instance.users.get(contact.user_id);
@ -510,14 +470,24 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.contacts_menu, menu);
searchItem = menu.findItem(R.id.messages_list_menu_search);
searchView = (SearchView) searchItem.getActionView();
searchView.setQueryHint(getStringEntry(R.string.SearchContactHint));
searchItem = (SupportMenuItem)menu.findItem(R.id.messages_list_menu_search);
searchView = (SearchView)searchItem.getActionView();
int srcId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null);
ImageView img = (ImageView) searchView.findViewById(srcId);
TextView textView = (TextView) searchView.findViewById(R.id.search_src_text);
if (textView != null) {
textView.setTextColor(0xffffffff);
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.set(textView, R.drawable.search_carret);
} catch (Exception e) {
e.printStackTrace();
}
}
ImageView img = (ImageView) searchView.findViewById(R.id.search_close_btn);
if (img != null) {
img.setImageResource(R.drawable.ic_msg_in_cross);
img.setImageResource(R.drawable.ic_msg_btn_cross_custom);
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@ -549,10 +519,13 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
}
});
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
searchItem.setSupportOnActionExpandListener(new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
parentActivity.getSupportActionBar().setIcon(R.drawable.ic_ab_search);
if (parentActivity != null) {
ActionBar actionBar = parentActivity.getSupportActionBar();
actionBar.setIcon(R.drawable.ic_ab_search);
}
searching = true;
return true;
}
@ -563,19 +536,21 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
searchDialogs(null);
searching = false;
searchWas = false;
ViewGroup group = (ViewGroup)listView.getParent();
ViewGroup group = (ViewGroup) listView.getParent();
listView.setAdapter(listViewAdapter);
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (!isRTL) {
listView.setPadding((int)(density * 16), listView.getPaddingTop(), (int)(density * 30), listView.getPaddingBottom());
listView.setPadding((int) (density * 16), listView.getPaddingTop(), (int) (density * 30), listView.getPaddingBottom());
} else {
listView.setPadding((int)(density * 30), listView.getPaddingTop(), (int)(density * 16), listView.getPaddingBottom());
listView.setPadding((int) (density * 30), listView.getPaddingTop(), (int) (density * 16), listView.getPaddingBottom());
}
if(android.os.Build.VERSION.SDK_INT >= 11) {
if (android.os.Build.VERSION.SDK_INT >= 11) {
listView.setFastScrollAlwaysVisible(true);
}
listView.setFastScrollEnabled(true);
listView.setVerticalScrollBarEnabled(false);
((ApplicationActivity)parentActivity).updateActionBar();
epmtyTextView.setText(getStringEntry(R.string.NoContacts));
return true;
}
@ -599,7 +574,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
Bundle bundle = new Bundle();
bundle.putInt("enc_id", encryptedChat.id);
fragment.setArguments(bundle);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat_enc_" + id, true, false);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat" + Math.random(), true, false);
}
}
}
@ -703,7 +678,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
} else {
int currentTime = ConnectionsManager.Instance.getCurrentTime();
if (user.status.expires > currentTime || user.status.was_online > currentTime) {
holder.messageTextView.setTextColor(0xff006fc8);
holder.messageTextView.setTextColor(0xff357aa8);
holder.messageTextView.setText(getStringEntry(R.string.Online));
} else {
if (user.status.was_online <= 10000 && user.status.expires <= 10000) {
@ -829,8 +804,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
if (holder == null) {
holder = new ContactListRowHolder(convertView);
convertView.setTag(holder);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
holder.nameTextView.setTypeface(typeface);
}
if (ignoreUsers != null) {
@ -876,7 +849,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
} else {
int currentTime = ConnectionsManager.Instance.getCurrentTime();
if (user.status.expires > currentTime || user.status.was_online > currentTime) {
holder.messageTextView.setTextColor(0xff006fc8);
holder.messageTextView.setTextColor(0xff357aa8);
holder.messageTextView.setText(getStringEntry(R.string.Online));
} else {
if (user.status.was_online <= 10000 && user.status.expires <= 10000) {
@ -899,8 +872,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_row_button_layout, parent, false);
textView = (TextView)convertView.findViewById(R.id.settings_row_text);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
textView.setTypeface(typeface);
} else {
textView = (TextView)convertView.findViewById(R.id.settings_row_text);
}
@ -999,11 +970,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
public TextView nameTextView;
public ContactListRowHolder(View view) {
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
messageTextView = (TextView)view.findViewById(R.id.messages_list_row_message);
if (messageTextView != null) {
messageTextView.setTypeface(typeface);
}
nameTextView = (TextView)view.findViewById(R.id.messages_list_row_name);
avatarImage = (BackupImageView)view.findViewById(R.id.messages_list_row_avatar);
}

View File

@ -0,0 +1,541 @@
/*
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.ui;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.support.v4.internal.view.SupportMenuItem;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.PinnedHeaderListView;
import org.telegram.ui.Views.SectionedBaseAdapter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
public class CountrySelectActivity extends ActionBarActivity {
private SupportMenuItem searchItem;
private SearchView searchView;
private SectionedBaseAdapter listViewAdapter;
private PinnedHeaderListView listView;
private boolean searchWas;
private boolean searching;
private BaseAdapter searchListViewAdapter;
private TextView epmtyTextView;
private boolean isRTL;
private HashMap<String, ArrayList<Country>> countries = new HashMap<String, ArrayList<Country>>();
private ArrayList<String> sortedCountries = new ArrayList<String>();
private Timer searchDialogsTimer;
public ArrayList<Country> searchResult;
public static class Country {
public String name;
public String code;
public String shortname;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Locale locale = Locale.getDefault();
String lang = locale.getLanguage();
isRTL = lang != null && lang.toLowerCase().equals("ar");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().getAssets().open("countries.txt")));
String line;
while ((line = reader.readLine()) != null) {
String[] args = line.split(";");
Country c = new Country();
c.name = args[2];
c.code = args[0];
c.shortname = args[1];
String n = c.name.substring(0, 1).toUpperCase();
ArrayList<Country> arr = countries.get(n);
if (arr == null) {
arr = new ArrayList<Country>();
countries.put(n, arr);
sortedCountries.add(n);
}
arr.add(c);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
Collections.sort(sortedCountries, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
return lhs.compareTo(rhs);
}
});
for (ArrayList<Country> arr : countries.values()) {
Collections.sort(arr, new Comparator<Country>() {
@Override
public int compare(Country country, Country country2) {
return country.name.compareTo(country2.name);
}
});
}
setContentView(R.layout.country_select_layout);
epmtyTextView = (TextView)findViewById(R.id.searchEmptyView);
searchListViewAdapter = new SearchAdapter(this);
listView = (PinnedHeaderListView)findViewById(R.id.listView);
listView.setEmptyView(epmtyTextView);
listView.setVerticalScrollBarEnabled(false);
listView.setAdapter(listViewAdapter = new ListAdapter(this));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (searching && searchWas) {
if (i < searchResult.size()) {
Country c = searchResult.get(i);
Intent intent = new Intent();
intent.putExtra("country", c.name);
setResult(RESULT_OK, intent);
finish();
}
} else {
int section = listViewAdapter.getSectionForPosition(i);
int row = listViewAdapter.getPositionInSectionForPosition(i);
if (section < sortedCountries.size()) {
String n = sortedCountries.get(section);
ArrayList<Country> arr = countries.get(n);
if (row < arr.size()) {
Country c = arr.get(row);
Intent intent = new Intent();
intent.putExtra("country", c.name);
setResult(RESULT_OK, intent);
finish();
}
}
}
}
});
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
getWindow().setFormat(PixelFormat.RGB_565);
}
public void applySelfActionBar() {
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setCustomView(null);
actionBar.setSubtitle(null);
actionBar.setTitle(getString(R.string.ChooseCountry));
fixBackButton();
}
@Override
protected void onResume() {
super.onResume();
applySelfActionBar();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case android.R.id.home:
if (searchItem != null) {
if (searchItem.isActionViewExpanded()) {
searchItem.collapseActionView();
}
}
finish();
break;
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.contacts_menu, menu);
searchItem = (SupportMenuItem)menu.findItem(R.id.messages_list_menu_search);
searchView = (SearchView)searchItem.getActionView();
TextView textView = (TextView) searchView.findViewById(R.id.search_src_text);
if (textView != null) {
textView.setTextColor(0xffffffff);
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.set(textView, R.drawable.search_carret);
} catch (Exception e) {
e.printStackTrace();
}
}
ImageView img = (ImageView) searchView.findViewById(R.id.search_close_btn);
if (img != null) {
img.setImageResource(R.drawable.ic_msg_btn_cross_custom);
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return true;
}
@Override
public boolean onQueryTextChange(String s) {
searchDialogs(s);
if (s.length() != 0) {
searchWas = true;
if (listView != null) {
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
listView.setPadding((int)(density * 16), listView.getPaddingTop(), (int)(density * 16), listView.getPaddingBottom());
listView.setAdapter(searchListViewAdapter);
if(android.os.Build.VERSION.SDK_INT >= 11) {
listView.setFastScrollAlwaysVisible(false);
}
listView.setFastScrollEnabled(false);
listView.setVerticalScrollBarEnabled(true);
}
if (epmtyTextView != null) {
epmtyTextView.setText(getString(R.string.NoResult));
}
}
return true;
}
});
searchItem.setSupportOnActionExpandListener(new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
getSupportActionBar().setIcon(R.drawable.ic_ab_search);
searching = true;
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
searchView.setQuery("", false);
searchDialogs(null);
searching = false;
searchWas = false;
ViewGroup group = (ViewGroup) listView.getParent();
listView.setAdapter(listViewAdapter);
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (!isRTL) {
listView.setPadding((int) (density * 16), listView.getPaddingTop(), (int) (density * 30), listView.getPaddingBottom());
} else {
listView.setPadding((int) (density * 30), listView.getPaddingTop(), (int) (density * 16), listView.getPaddingBottom());
}
if (android.os.Build.VERSION.SDK_INT >= 11) {
listView.setFastScrollAlwaysVisible(true);
}
listView.setFastScrollEnabled(true);
listView.setVerticalScrollBarEnabled(false);
applySelfActionBar();
epmtyTextView.setText(getString(R.string.ChooseCountry));
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
public void fixBackButton() {
if(android.os.Build.VERSION.SDK_INT == 19) {
//workaround for back button dissapear
try {
Class firstClass = getSupportActionBar().getClass();
Class aClass = firstClass.getSuperclass();
if (aClass == android.support.v7.app.ActionBar.class) {
} else {
Field field = aClass.getDeclaredField("mActionBar");
field.setAccessible(true);
android.app.ActionBar bar = (android.app.ActionBar)field.get(getSupportActionBar());
field = bar.getClass().getDeclaredField("mActionView");
field.setAccessible(true);
View v = (View)field.get(bar);
aClass = v.getClass();
field = aClass.getDeclaredField("mHomeLayout");
field.setAccessible(true);
v = (View)field.get(v);
v.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void searchDialogs(final String query) {
if (query == null) {
searchResult = null;
} else {
try {
if (searchDialogsTimer != null) {
searchDialogsTimer.cancel();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
searchDialogsTimer = new Timer();
searchDialogsTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
searchDialogsTimer.cancel();
searchDialogsTimer = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
processSearch(query);
}
}, 100, 300);
}
}
private void processSearch(final String query) {
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
String q = query.trim().toLowerCase();
if (q.length() == 0) {
updateSearchResults(new ArrayList<Country>());
return;
}
long time = System.currentTimeMillis();
ArrayList<Country> resultArray = new ArrayList<Country>();
String n = query.substring(0, 1);
ArrayList<Country> arr = countries.get(n.toUpperCase());
if (arr != null) {
for (Country c : arr) {
if (c.name.toLowerCase().startsWith(query)) {
resultArray.add(c);
}
}
}
updateSearchResults(resultArray);
}
});
}
private void updateSearchResults(final ArrayList<Country> arrCounties) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
searchResult = arrCounties;
searchListViewAdapter.notifyDataSetChanged();
}
});
}
private class SearchAdapter extends BaseAdapter {
private Context mContext;
public SearchAdapter(Context context) {
mContext = context;
}
@Override
public boolean areAllItemsEnabled() {
return true;
}
@Override
public boolean isEnabled(int i) {
return true;
}
@Override
public int getCount() {
if (searchResult == null) {
return 0;
}
return searchResult.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.country_row_layout, viewGroup, false);
}
TextView textView = (TextView)view.findViewById(R.id.settings_row_text);
TextView detailTextView = (TextView)view.findViewById(R.id.settings_row_text_detail);
View divider = view.findViewById(R.id.settings_row_divider);
Country c = searchResult.get(i);
textView.setText(c.name);
detailTextView.setText("+" + c.code);
if (i == searchResult.size() - 1) {
divider.setVisibility(View.GONE);
} else {
divider.setVisibility(View.VISIBLE);
}
return view;
}
@Override
public int getItemViewType(int i) {
return 0;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean isEmpty() {
return searchResult == null || searchResult.size() == 0;
}
}
private class ListAdapter extends SectionedBaseAdapter {
private Context mContext;
public ListAdapter(Context context) {
mContext = context;
}
@Override
public Object getItem(int section, int position) {
return null;
}
@Override
public long getItemId(int section, int position) {
return 0;
}
@Override
public int getSectionCount() {
return sortedCountries.size();
}
@Override
public int getCountForSection(int section) {
String n = sortedCountries.get(section);
ArrayList<Country> arr = countries.get(n);
return arr.size();
}
@Override
public View getItemView(int section, int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.country_row_layout, parent, false);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_row_text);
TextView detailTextView = (TextView)convertView.findViewById(R.id.settings_row_text_detail);
View divider = convertView.findViewById(R.id.settings_row_divider);
String n = sortedCountries.get(section);
ArrayList<Country> arr = countries.get(n);
Country c = arr.get(position);
textView.setText(c.name);
detailTextView.setText("+" + c.code);
if (position == arr.size() - 1) {
divider.setVisibility(View.GONE);
} else {
divider.setVisibility(View.VISIBLE);
}
return convertView;
}
@Override
public int getItemViewType(int section, int position) {
return 0;
}
@Override
public int getItemViewTypeCount() {
return 1;
}
@Override
public int getSectionHeaderViewType(int section) {
return 0;
}
@Override
public int getSectionHeaderViewTypeCount() {
return 1;
}
@Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.settings_section_layout, parent, false);
convertView.setBackgroundColor(0xfffafafa);
}
TextView textView = (TextView)convertView.findViewById(R.id.settings_section_text);
textView.setText(sortedCountries.get(section).toUpperCase());
return convertView;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -12,9 +12,12 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@ -24,11 +27,8 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.objects.PhotoObject;
import org.telegram.ui.Views.AbstractGalleryActivity;
import org.telegram.ui.Views.GalleryViewPager;
@ -43,10 +43,8 @@ import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
public class GalleryImageViewer extends AbstractGalleryActivity implements NotificationCenter.NotificationCenterDelegate {
@ -63,18 +61,18 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
private boolean loadingMore = false;
private TextView title;
private boolean ignoreSet = false;
private ProgressBar loadingProgress;
private String currentFileName;
private int user_id = 0;
private ArrayList<MessageObject> imagesArrTemp = new ArrayList<MessageObject>();
private HashMap<Integer, MessageObject> imagesByIdsTemp = new HashMap<Integer, MessageObject>();
private ArrayList<TLRPC.FileLocation> imagesArrLocations;
private long currentDialog = 0;
private int totalCount = 0;
private int classGuid;
private boolean cacheEndReached;
private HashMap<String, ProgressBar> loadingFile = new HashMap<String, ProgressBar>();
private HashMap<Integer, String> progressByTag = new HashMap<Integer, String>();
private boolean firstLoad = true;
private boolean cacheEndReached = false;
public static int needShowAllMedia = 2000;
@ -100,8 +98,9 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
timeTextView = (TextView)findViewById(R.id.gallery_view_time_text);
bottomView = findViewById(R.id.gallery_view_bottom_view);
fakeTitleView = (TextView)findViewById(R.id.fake_title_view);
loadingProgress = (ProgressBar)findViewById(R.id.action_progress);
title = (TextView)findViewById(R.id.abs__action_bar_title);
title = (TextView)findViewById(R.id.action_bar_title);
if (title == null) {
final int titleId = getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)findViewById(titleId);
@ -112,19 +111,22 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
NotificationCenter.Instance.addObserver(this, FileLoader.FileLoadProgressChanged);
NotificationCenter.Instance.addObserver(this, MessagesController.mediaCountDidLoaded);
NotificationCenter.Instance.addObserver(this, MessagesController.mediaDidLoaded);
NotificationCenter.Instance.addObserver(this, MessagesController.userPhotosLoaded);
Integer index = null;
if (localPagerAdapter == null) {
final MessageObject file = (MessageObject)NotificationCenter.Instance.getFromMemCache(1);
final TLRPC.FileLocation fileLocation = (TLRPC.FileLocation)NotificationCenter.Instance.getFromMemCache(3);
final ArrayList<MessageObject> messagesArr = (ArrayList<MessageObject>)NotificationCenter.Instance.getFromMemCache(4);
index = (Integer)NotificationCenter.Instance.getFromMemCache(5);
final MessageObject file = (MessageObject)NotificationCenter.Instance.getFromMemCache(51);
final TLRPC.FileLocation fileLocation = (TLRPC.FileLocation)NotificationCenter.Instance.getFromMemCache(53);
final ArrayList<MessageObject> messagesArr = (ArrayList<MessageObject>)NotificationCenter.Instance.getFromMemCache(54);
index = (Integer)NotificationCenter.Instance.getFromMemCache(55);
Integer uid = (Integer)NotificationCenter.Instance.getFromMemCache(56);
if (uid != null) {
user_id = uid;
}
ArrayList<MessageObject> imagesArr = null;
HashMap<Integer, MessageObject> imagesByIds = null;
if (file != null) {
imagesArr = new ArrayList<MessageObject>();
imagesByIds = new HashMap<Integer, MessageObject>();
ArrayList<MessageObject> imagesArr = new ArrayList<MessageObject>();
HashMap<Integer, MessageObject> imagesByIds = new HashMap<Integer, MessageObject>();
imagesArr.add(file);
if (file.messageOwner.action == null || file.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) {
needSearchMessage = true;
@ -143,17 +145,18 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
}
}
localPagerAdapter = new LocalPagerAdapter(imagesArr, imagesByIds);
} else if (fileLocation != null) {
ArrayList<TLRPC.FileLocation> arr = new ArrayList<TLRPC.FileLocation>();
arr.add(fileLocation);
imagesArrLocations = arr;
withoutBottom = true;
deleteButton.setVisibility(View.INVISIBLE);
nameTextView.setVisibility(View.INVISIBLE);
timeTextView.setVisibility(View.INVISIBLE);
localPagerAdapter = new LocalPagerAdapter(arr);
} else if (messagesArr != null) {
imagesArr = new ArrayList<MessageObject>();
imagesByIds = new HashMap<Integer, MessageObject>();
ArrayList<MessageObject> imagesArr = new ArrayList<MessageObject>();
HashMap<Integer, MessageObject> imagesByIds = new HashMap<Integer, MessageObject>();
imagesArr.addAll(messagesArr);
Collections.reverse(imagesArr);
for (MessageObject message : imagesArr) {
@ -175,8 +178,8 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
}
}
localPagerAdapter = new LocalPagerAdapter(imagesArr, imagesByIds);
}
localPagerAdapter = new LocalPagerAdapter(imagesArr, imagesByIds);
}
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
@ -187,7 +190,7 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
if (index != null) {
fromAll = true;
mViewPager.setCurrentItem( index);
mViewPager.setCurrentItem(index);
}
shareButton.setOnClickListener(new View.OnClickListener() {
@ -203,7 +206,7 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}
});
@ -225,6 +228,10 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
if (currentDialog != 0 && totalCount == 0) {
MessagesController.Instance.getMediaCount(currentDialog, classGuid, true);
}
if (user_id != 0) {
MessagesController.Instance.loadUserPhotos(user_id, 0, 30, 0, true, classGuid);
}
checkCurrentFile();
}
@Override
@ -235,6 +242,7 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
NotificationCenter.Instance.removeObserver(this, FileLoader.FileLoadProgressChanged);
NotificationCenter.Instance.removeObserver(this, MessagesController.mediaCountDidLoaded);
NotificationCenter.Instance.removeObserver(this, MessagesController.mediaDidLoaded);
NotificationCenter.Instance.removeObserver(this, MessagesController.userPhotosLoaded);
ConnectionsManager.Instance.cancelRpcsForClassGuid(classGuid);
}
@ -243,28 +251,100 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
public void didReceivedNotification(int id, final Object... args) {
if (id == FileLoader.FileDidFailedLoad) {
String location = (String)args[0];
if (loadingFile.containsKey(location)) {
loadingFile.remove(location);
localPagerAdapter.updateViews();
if (currentFileName != null && currentFileName.equals(location)) {
if (loadingProgress != null) {
loadingProgress.setVisibility(View.GONE);
}
if (localPagerAdapter != null) {
localPagerAdapter.updateViews();
}
}
} else if (id == FileLoader.FileDidLoaded) {
String location = (String)args[0];
if (loadingFile.containsKey(location)) {
loadingFile.remove(location);
localPagerAdapter.updateViews();
if (currentFileName != null && currentFileName.equals(location)) {
if (loadingProgress != null) {
loadingProgress.setVisibility(View.GONE);
}
if (localPagerAdapter != null) {
localPagerAdapter.updateViews();
}
}
} else if (id == FileLoader.FileLoadProgressChanged) {
String location = (String)args[0];
ProgressBar bar;
if ((bar = loadingFile.get(location)) != null) {
if (currentFileName != null && currentFileName.equals(location)) {
Float progress = (Float)args[1];
bar.setProgress((int)(progress * 100));
if (loadingProgress != null) {
loadingProgress.setVisibility(View.VISIBLE);
loadingProgress.setProgress((int)(progress * 100));
}
if (localPagerAdapter != null) {
localPagerAdapter.updateViews();
}
}
} else if (id == MessagesController.userPhotosLoaded) {
int guid = (Integer)args[4];
int uid = (Integer)args[0];
if (user_id == uid && classGuid == guid) {
boolean fromCache = (Boolean)args[3];
TLRPC.FileLocation currentLocation = null;
int setToImage = -1;
if (localPagerAdapter != null && mViewPager != null) {
int idx = mViewPager.getCurrentItem();
if (localPagerAdapter.imagesArrLocations.size() > idx) {
currentLocation = localPagerAdapter.imagesArrLocations.get(idx);
}
}
ArrayList<TLRPC.Photo> photos = (ArrayList<TLRPC.Photo>)args[5];
if (photos.isEmpty()) {
return;
}
ArrayList<TLRPC.FileLocation> arr = new ArrayList<TLRPC.FileLocation>();
for (TLRPC.Photo photo : photos) {
if (photo instanceof TLRPC.TL_photoEmpty) {
continue;
}
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(photo.sizes, 800, 800);
if (sizeFull != null) {
if (currentLocation != null && sizeFull.location.local_id == currentLocation.local_id && sizeFull.location.volume_id == currentLocation.volume_id) {
setToImage = arr.size();
}
arr.add(sizeFull.location);
}
}
mViewPager.setAdapter(null);
int count = mViewPager.getChildCount();
for (int a = 0; a < count; a++) {
View child = mViewPager.getChildAt(0);
mViewPager.removeView(child);
}
mViewPager.mCurrentView = null;
needSearchMessage = false;
ignoreSet = true;
mViewPager.setAdapter(localPagerAdapter = new LocalPagerAdapter(arr));
mViewPager.invalidate();
ignoreSet = false;
if (setToImage != -1) {
mViewPager.setCurrentItem(setToImage);
} else {
mViewPager.setCurrentItem(0);
}
if (fromCache) {
MessagesController.Instance.loadUserPhotos(user_id, 0, 30, 0, false, classGuid);
}
}
} else if (id == MessagesController.mediaCountDidLoaded) {
long uid = (Long)args[0];
if (uid == currentDialog) {
if ((int)currentDialog != 0) {
boolean fromCache = (Boolean)args[2];
if (fromCache) {
MessagesController.Instance.getMediaCount(currentDialog, classGuid, false);
}
}
totalCount = (Integer)args[1];
if (needSearchMessage) {
if (needSearchMessage && firstLoad) {
firstLoad = false;
MessagesController.Instance.loadMedia(currentDialog, 0, 100, 0, true, classGuid);
loadingMore = true;
} else {
@ -317,6 +397,9 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
}
}
if (added == 0) {
totalCount = imagesArrTemp.size();
}
if (foundIndex != -1) {
mViewPager.setAdapter(null);
@ -353,17 +436,19 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
if (arr.isEmpty() && !fromCache) {
totalCount = arr.size();
}
int current = mViewPager.getCurrentItem();
ignoreSet = true;
imagesArrTemp = new ArrayList<MessageObject>(localPagerAdapter.imagesArr);
imagesByIdsTemp = new HashMap<Integer, MessageObject>(localPagerAdapter.imagesByIds);
mViewPager.setAdapter(localPagerAdapter = new LocalPagerAdapter(imagesArrTemp, imagesByIdsTemp));
mViewPager.invalidate();
ignoreSet = false;
imagesArrTemp = null;
imagesByIdsTemp = null;
if (added != 0) {
int current = mViewPager.getCurrentItem();
ignoreSet = true;
imagesArrTemp = new ArrayList<MessageObject>(localPagerAdapter.imagesArr);
imagesByIdsTemp = new HashMap<Integer, MessageObject>(localPagerAdapter.imagesByIds);
mViewPager.setAdapter(localPagerAdapter = new LocalPagerAdapter(imagesArrTemp, imagesByIdsTemp));
mViewPager.invalidate();
ignoreSet = false;
imagesArrTemp = null;
imagesByIdsTemp = null;
mViewPager.setCurrentItem(current + added);
} else {
totalCount = localPagerAdapter.imagesArr.size();
}
}
}
@ -373,18 +458,22 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
private TLRPC.FileLocation getCurrentFile() {
int item = mViewPager.getCurrentItem();
if (withoutBottom) {
return imagesArrLocations.get(item);
return localPagerAdapter.imagesArrLocations.get(item);
} else {
MessageObject message = localPagerAdapter.imagesArr.get(item);
if (message.messageOwner instanceof TLRPC.TL_messageService) {
ArrayList<TLRPC.PhotoSize> sizes = message.messageOwner.action.photo.sizes;
if (sizes.size() > 0) {
return sizes.get(sizes.size() - 1).location;
if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
return message.messageOwner.action.newUserPhoto.photo_big;
} else {
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(message.messageOwner.action.photo.sizes, 800, 800);
if (sizeFull != null) {
return sizeFull.location;
}
}
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = message.messageOwner.media.photo.sizes;
if (sizes.size() > 0) {
return sizes.get(sizes.size() - 1).location;
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(message.messageOwner.media.photo.sizes, 800, 800);
if (sizeFull != null) {
return sizeFull.location;
}
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
return message.messageOwner.media.video.thumb.location;
@ -414,13 +503,69 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
} else {
nameTextView.setText("");
}
invalidateOptionsMenu();
isVideo = obj.messageOwner.media != null && obj.messageOwner.media instanceof TLRPC.TL_messageMediaVideo;
if (obj.messageOwner instanceof TLRPC.TL_messageService) {
if (obj.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
TLRPC.FileLocation file = obj.messageOwner.action.newUserPhoto.photo_big;
currentFileName = file.volume_id + "_" + file.local_id + ".jpg";
} else {
ArrayList<TLRPC.PhotoSize> sizes = obj.messageOwner.action.photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(sizes, 800, 800);
if (sizeFull != null) {
currentFileName = sizeFull.location.volume_id + "_" + sizeFull.location.local_id + ".jpg";
}
}
}
} else if (obj.messageOwner.media != null) {
if (obj.messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
currentFileName = obj.messageOwner.media.video.dc_id + "_" + obj.messageOwner.media.video.id + ".mp4";
} else if (obj.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
TLRPC.FileLocation file = getCurrentFile();
if (file != null) {
currentFileName = file.volume_id + "_" + file.local_id + ".jpg";
} else {
currentFileName = null;
}
}
} else {
currentFileName = null;
}
checkCurrentFile();
supportInvalidateOptionsMenu();
}
private void checkCurrentFile() {
if (currentFileName != null) {
File f = new File(Utilities.getCacheDir(), currentFileName);
if (f.exists()) {
loadingProgress.setVisibility(View.GONE);
} else {
loadingProgress.setVisibility(View.VISIBLE);
Float progress = FileLoader.Instance.fileProgresses.get(currentFileName);
if (progress != null) {
loadingProgress.setProgress((int)(progress * 100));
} else {
loadingProgress.setProgress(0);
}
}
} else {
loadingProgress.setVisibility(View.GONE);
}
if (isVideo) {
if (!FileLoader.Instance.isLoadingFile(currentFileName)) {
loadingProgress.setVisibility(View.GONE);
} else {
loadingProgress.setVisibility(View.VISIBLE);
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
MenuInflater inflater = getMenuInflater();
if (withoutBottom) {
inflater.inflate(R.menu.gallery_save_only_menu, menu);
} else {
@ -436,14 +581,16 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
@Override
public void openOptionsMenu() {
TLRPC.FileLocation file = getCurrentFile();
File f = new File(Utilities.getCacheDir(), file.volume_id + "_" + file.local_id + ".jpg");
if (f.exists()) {
super.openOptionsMenu();
if (file != null) {
File f = new File(Utilities.getCacheDir(), file.volume_id + "_" + file.local_id + ".jpg");
if (f.exists()) {
super.openOptionsMenu();
}
}
}
@Override
public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
processSelectedMenu(itemId);
return true;
@ -484,14 +631,13 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
case R.id.gallery_menu_save:
TLRPC.FileLocation file = getCurrentFile();
File f = new File(Utilities.getCacheDir(), file.volume_id + "_" + file.local_id + ".jpg");
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + ".jpg";
File dstFile = Utilities.generatePicturePath();
try {
MediaStore.Images.Media.insertImage(getContentResolver(), f.getAbsolutePath(), imageFileName, "");
Utilities.copyFile(f, dstFile);
Utilities.addMediaToGallery(Uri.fromFile(dstFile));
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
//Utilities.addMediaToGallery(addToTouchActiveAlbum(imageFileName, f.getAbsolutePath()));
break;
// case R.id.gallery_menu_send: {
// Intent intent = new Intent(this, MessagesActivity.class);
@ -548,21 +694,6 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
}
/*public Uri addToTouchActiveAlbum(String title, String filePath) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, title);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.BUCKET_ID, filePath.hashCode());
values.put(MediaStore.Images.Media.BUCKET_DISPLAY_NAME, "TMessages");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
//values.put(MediaStore.MediaColumns.DATA, filePath);
values.put(MediaStore.Images.Media.DATA, filePath);
return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}*/
private void startViewAnimation(final View panel, boolean up) {
Animation animation;
if (!up) {
@ -612,13 +743,17 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
public class LocalPagerAdapter extends PagerAdapter {
public ArrayList<MessageObject> imagesArr;
public HashMap<Integer, MessageObject> imagesByIds;
public int tagCounter = 0;
private ArrayList<TLRPC.FileLocation> imagesArrLocations;
public LocalPagerAdapter(ArrayList<MessageObject> _imagesArr, HashMap<Integer, MessageObject> _imagesByIds) {
imagesArr = _imagesArr;
imagesByIds = _imagesByIds;
}
public LocalPagerAdapter(ArrayList<TLRPC.FileLocation> locations) {
imagesArrLocations = locations;
}
@Override
public void setPrimaryItem(ViewGroup container, final int position, Object object) {
super.setPrimaryItem(container, position, object);
@ -650,6 +785,26 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
});
}
} else if (imagesArrLocations != null) {
TLRPC.FileLocation file = imagesArrLocations.get(position);
currentFileName = file.volume_id + "_" + file.local_id + ".jpg";
checkCurrentFile();
if (imagesArrLocations.size() > 1) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
getSupportActionBar().setTitle(String.format("%d %s %d", position + 1, getString(R.string.Of), imagesArrLocations.size()));
if (title != null) {
fakeTitleView.setText(String.format("%d %s %d", position + 1, getString(R.string.Of), imagesArrLocations.size()));
fakeTitleView.measure(View.MeasureSpec.makeMeasureSpec(400, View.MeasureSpec.AT_MOST), 40);
title.setWidth(fakeTitleView.getMeasuredWidth() + (int)(8 * getResources().getDisplayMetrics().density));
title.setMaxWidth(fakeTitleView.getMeasuredWidth() + (int)(8 * getResources().getDisplayMetrics().density));
}
}
});
} else {
getSupportActionBar().setTitle(getString(R.string.Gallery));
}
}
}
@ -657,25 +812,22 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
int count = mViewPager.getChildCount();
for (int a = 0; a < count; a++) {
View v = mViewPager.getChildAt(a);
final ProgressBar progressBar = (ProgressBar)v.findViewById(R.id.action_progress);
final TextView playButton = (TextView)v.findViewById(R.id.action_button);
final View progressBarParent = v.findViewById(R.id.action_progress_parent);
MessageObject message = (MessageObject)playButton.getTag();
if (progressBar != null && message != null) {
processViews(progressBar, playButton, message, progressBarParent);
if (message != null) {
processViews(playButton, message);
}
}
}
public void processViews(ProgressBar progressBar, TextView playButton, MessageObject message, View progressBarParent) {
public void processViews(TextView playButton, MessageObject message) {
if (message.messageOwner.send_state != MessagesController.MESSAGE_SEND_STATE_SENDING && message.messageOwner.send_state != MessagesController.MESSAGE_SEND_STATE_SEND_ERROR) {
playButton.setVisibility(View.VISIBLE);
String fileName = message.messageOwner.media.video.dc_id + "_" + message.messageOwner.media.video.id + ".mp4";
boolean load = false;
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
File f = new File(message.messageOwner.attachPath);
if (f.exists()) {
playButton.setVisibility(View.VISIBLE);
progressBarParent.setVisibility(View.GONE);
playButton.setText(getString(R.string.ViewVideo));
} else {
load = true;
@ -683,8 +835,6 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
} else {
File cacheFile = new File(Utilities.getCacheDir(), fileName);
if (cacheFile.exists()) {
playButton.setVisibility(View.VISIBLE);
progressBarParent.setVisibility(View.GONE);
playButton.setText(getString(R.string.ViewVideo));
} else {
load = true;
@ -692,33 +842,11 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
if (load) {
Float progress = FileLoader.Instance.fileProgresses.get(fileName);
if (loadingFile.containsKey(fileName) || progress != null) {
if (progress != null) {
progressBar.setProgress((int) (progress * 100));
} else {
progressBar.setProgress(0);
}
progressByTag.put((Integer)progressBar.getTag(), fileName);
loadingFile.put(fileName, progressBar);
progressBarParent.setVisibility(View.VISIBLE);
playButton.setVisibility(View.GONE);
if (FileLoader.Instance.isLoadingFile(fileName)) {
playButton.setText(R.string.CancelDownload);
} else {
progressBarParent.setVisibility(View.GONE);
playButton.setVisibility(View.VISIBLE);
playButton.setText(String.format("%s %.1f MB", getString(R.string.DOWNLOAD), message.messageOwner.media.video.size / 1024.0f / 1024.0f));
}
} else {
Integer tag = (Integer)progressBar.getTag();
String file = progressByTag.get(tag);
if (file != null) {
loadingFile.remove(file);
}
}
} else {
Integer tag = (Integer)progressBar.getTag();
String file = progressByTag.get(tag);
if (file != null) {
loadingFile.remove(file);
}
}
}
@ -734,24 +862,25 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
((ViewPager) collection).addView(view, 0);
PZSImageView iv = (PZSImageView)view.findViewById(R.id.page_image);
final ProgressBar progressBar = (ProgressBar)view.findViewById(R.id.action_progress);
final TextView playButton = (TextView)view.findViewById(R.id.action_button);
final View progressBarParent = view.findViewById(R.id.action_progress_parent);
progressBar.setTag(tagCounter);
tagCounter++;
if (imagesArr != null) {
final MessageObject message = imagesArr.get(position);
view.setTag(message.messageOwner.id);
if (message.messageOwner instanceof TLRPC.TL_messageService) {
ArrayList<TLRPC.PhotoSize> sizes = message.messageOwner.action.photo.sizes;
iv.isVideo = false;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(sizes, 800, 800);
if (message.imagePreview != null) {
iv.setImage(sizeFull.location, null, message.imagePreview);
} else {
iv.setImage(sizeFull.location, null, 0);
if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
iv.isVideo = false;
iv.setImage(message.messageOwner.action.newUserPhoto.photo_big, null, 0, -1);
} else {
ArrayList<TLRPC.PhotoSize> sizes = message.messageOwner.action.photo.sizes;
iv.isVideo = false;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(sizes, 800, 800);
if (message.imagePreview != null) {
iv.setImage(sizeFull.location, null, message.imagePreview, sizeFull.size);
} else {
iv.setImage(sizeFull.location, null, 0, sizeFull.size);
}
}
}
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
@ -760,13 +889,13 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = PhotoObject.getClosestPhotoSizeWithSize(sizes, 800, 800);
if (message.imagePreview != null) {
iv.setImage(sizeFull.location, null, message.imagePreview);
iv.setImage(sizeFull.location, null, message.imagePreview, sizeFull.size);
} else {
iv.setImage(sizeFull.location, null, 0);
iv.setImage(sizeFull.location, null, 0, sizeFull.size);
}
}
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
processViews(progressBar, playButton, message, progressBarParent);
processViews(playButton, message);
playButton.setTag(message);
playButton.setOnClickListener(new View.OnClickListener() {
@ -794,14 +923,13 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
}
}
if (loadFile) {
if (!loadingFile.containsKey(fileName)) {
progressByTag.put((Integer)progressBar.getTag(), fileName);
loadingFile.put(fileName, progressBar);
if (!FileLoader.Instance.isLoadingFile(fileName)) {
FileLoader.Instance.loadFile(message.messageOwner.media.video, null);
progressBar.setProgress(0);
progressBarParent.setVisibility(View.VISIBLE);
playButton.setVisibility(View.INVISIBLE);
} else {
FileLoader.Instance.cancelLoadFile(message.messageOwner.media.video, null);
}
checkCurrentFile();
processViews(playButton, message);
}
}
});
@ -809,12 +937,14 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
if (message.messageOwner.media.video.thumb instanceof TLRPC.TL_photoCachedSize) {
iv.setImageBitmap(message.imagePreview);
} else {
iv.setImage(message.messageOwner.media.video.thumb.location, null, 0);
if (message.messageOwner.media.video.thumb != null) {
iv.setImage(message.messageOwner.media.video.thumb.location, null, 0, message.messageOwner.media.video.thumb.size);
}
}
}
} else {
iv.isVideo = false;
iv.setImage(imagesArrLocations.get(position), null, 0);
iv.setImage(imagesArrLocations.get(position), null, 0, -1);
}
return view;
@ -826,12 +956,6 @@ public class GalleryImageViewer extends AbstractGalleryActivity implements Notif
PZSImageView iv = (PZSImageView)((View)view).findViewById(R.id.page_image);
FileLoader.Instance.cancelLoadingForImageView(iv);
iv.clearImage();
final ProgressBar progressBar = (ProgressBar)((View)view).findViewById(R.id.action_progress);
Integer tag = (Integer)progressBar.getTag();
String file = progressByTag.get(tag);
if (file != null) {
loadingFile.remove(file);
}
}
@Override

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -12,10 +12,11 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.internal.view.SupportMenuItem;
import android.support.v7.app.ActionBar;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
@ -23,26 +24,21 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.ImageSpan;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
@ -64,7 +60,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
private TextView doneTextView;
private EditText userSelectEditText;
private TextView countTextView;
private View topView;
private boolean ignoreChange = false;
private HashMap<Integer, Emoji.XImageSpan> selectedContacts = new HashMap<Integer, Emoji.XImageSpan>();
@ -114,7 +109,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
epmtyTextView = (TextView)fragmentView.findViewById(R.id.searchEmptyView);
userSelectEditText = (EditText)fragmentView.findViewById(R.id.bubble_input_text);
countTextView = (TextView)fragmentView.findViewById(R.id.bubble_counter_text);
topView = fragmentView.findViewById(R.id.top_layout);
if (Build.VERSION.SDK_INT >= 11) {
userSelectEditText.setTextIsSelectable(false);
}
@ -142,7 +136,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
try {
deletedString = changeString.toString().substring(afterChangeIndex, beforeChangeIndex);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
if (deletedString.length() > 0) {
if (searching && searchWas) {
@ -263,45 +257,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
return fragmentView;
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
if (listView != null) {
ViewTreeObserver obs = listView.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
LinearLayout.LayoutParams params2 = (LinearLayout.LayoutParams)topView.getLayoutParams();
params2.setMargins(0, height, 0, 0);
topView.setLayoutParams(params2);
listView.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
public void applySelfActionBar() {
if (parentActivity == null) {
@ -314,9 +269,9 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setCustomView(null);
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.NewGroup) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.NewGroup));
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -330,12 +285,11 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).showActionBar();
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
}
public Emoji.XImageSpan createAndPutChipForUser(TLRPC.User user) {
@ -382,7 +336,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
searchDialogsTimer.cancel();
}
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
searchDialogsTimer = new Timer();
searchDialogsTimer.schedule(new TimerTask() {
@ -392,7 +346,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
searchDialogsTimer.cancel();
searchDialogsTimer = null;
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
processSearch(query);
}
@ -454,7 +408,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.group_create_menu, menu);
MenuItem doneItem = menu.findItem(R.id.done_menu_item);
SupportMenuItem doneItem = (SupportMenuItem)menu.findItem(R.id.done_menu_item);
doneTextView = (TextView)doneItem.getActionView().findViewById(R.id.done_button);
doneTextView.setOnClickListener(new View.OnClickListener() {
@Override
@ -551,9 +505,9 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
ImageView checkButton = (ImageView)convertView.findViewById(R.id.settings_row_check_button);
if (selectedContacts.containsKey(user.id)) {
checkButton.setImageResource(R.drawable.btn_check_on);
checkButton.setImageResource(R.drawable.btn_check_on_old);
} else {
checkButton.setImageResource(R.drawable.btn_check_off);
checkButton.setImageResource(R.drawable.btn_check_off_old);
}
View divider = convertView.findViewById(R.id.settings_row_divider);
@ -565,7 +519,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
if (searchWas && searching) {
holder.nameTextView.setText(searchResultNames.get(position));
holder.nameTextView.setTypeface(null);
} else {
if (user.first_name.length() != 0 && user.last_name.length() != 0) {
holder.nameTextView.setText(Html.fromHtml(user.first_name + " <b>" + user.last_name + "</b>"));
@ -574,8 +527,6 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
} else {
holder.nameTextView.setText(Html.fromHtml("<b>" + user.last_name + "</b>"));
}
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
holder.nameTextView.setTypeface(typeface);
}
TLRPC.FileLocation photo = null;
@ -591,7 +542,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
} else {
int currentTime = ConnectionsManager.Instance.getCurrentTime();
if (user.status.expires > currentTime || user.status.was_online > currentTime) {
holder.messageTextView.setTextColor(0xff006fc8);
holder.messageTextView.setTextColor(0xff357aa8);
holder.messageTextView.setText(getStringEntry(R.string.Online));
} else {
if (user.status.was_online <= 10000 && user.status.expires <= 10000) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -12,28 +12,23 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.internal.view.SupportMenuItem;
import android.support.v7.app.ActionBar;
import android.text.Html;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
@ -50,11 +45,10 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
private PinnedHeaderListView listView;
private TextView nameTextView;
private TLRPC.FileLocation avatar;
private TLRPC.TL_inputFile uploadedAvatar;
private TLRPC.InputFile uploadedAvatar;
private ArrayList<Integer> selectedContacts;
private BackupImageView avatarImage;
private boolean createAfterUpload;
private View topView;
private boolean donePressed;
private AvatarUpdater avatarUpdater = new AvatarUpdater();
@ -116,7 +110,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
} else if (i == 2) {
avatar = null;
uploadedAvatar = null;
avatarImage.setImage(avatar, "50_50", R.drawable.group_placeholder_blue);
avatarImage.setImage(avatar, "50_50", R.drawable.group_blue);
}
}
});
@ -125,7 +119,6 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
});
avatarImage = (BackupImageView)fragmentView.findViewById(R.id.settings_avatar_image);
topView = fragmentView.findViewById(R.id.top_layout);
nameTextView = (EditText)fragmentView.findViewById(R.id.bubble_input_text);
listView = (PinnedHeaderListView)fragmentView.findViewById(R.id.listView);
@ -139,45 +132,6 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
return fragmentView;
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
if (listView != null) {
ViewTreeObserver obs = listView.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager)parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
}
}
LinearLayout.LayoutParams params2 = (LinearLayout.LayoutParams)topView.getLayoutParams();
params2.setMargins(0, height, 0, 0);
topView.setLayoutParams(params2);
listView.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
}
@Override
public void applySelfActionBar() {
if (parentActivity == null) {
@ -190,9 +144,9 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setCustomView(null);
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.NewGroup) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.NewGroup));
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -206,24 +160,23 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).showActionBar();
((ApplicationActivity)parentActivity).updateActionBar();
fixLayout();
}
@Override
public void didUploadedPhoto(final TLRPC.TL_inputFile file, final TLRPC.PhotoSize small, final TLRPC.PhotoSize big) {
public void didUploadedPhoto(final TLRPC.InputFile file, final TLRPC.PhotoSize small, final TLRPC.PhotoSize big) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
uploadedAvatar = file;
avatar = small.location;
avatarImage.setImage(avatar, "50_50", R.drawable.group_placeholder_blue);
avatarImage.setImage(avatar, "50_50", R.drawable.group_blue);
if (createAfterUpload) {
Log.e("tmessages", "avatar did uploaded");
FileLog.e("tmessages", "avatar did uploaded");
MessagesController.Instance.createChat(nameTextView.getText().toString(), selectedContacts, uploadedAvatar);
}
}
@ -250,7 +203,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.group_create_menu, menu);
MenuItem doneItem = menu.findItem(R.id.done_menu_item);
SupportMenuItem doneItem = (SupportMenuItem)menu.findItem(R.id.done_menu_item);
TextView doneTextView = (TextView)doneItem.getActionView().findViewById(R.id.done_button);
doneTextView.setOnClickListener(new View.OnClickListener() {
@Override
@ -281,7 +234,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
} else if (id == MessagesController.chatDidFailCreate) {
Utilities.HideProgressDialog(parentActivity);
donePressed = false;
Log.e("tmessages", "did fail create");
FileLog.e("tmessages", "did fail create chat");
} else if (id == MessagesController.chatDidCreated) {
Utilities.RunOnUIThread(new Runnable() {
@Override
@ -291,7 +244,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
Bundle bundle = new Bundle();
bundle.putInt("chat_id", (Integer)args[0]);
fragment.setArguments(bundle);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat_group_" + args[0], true, false);
((ApplicationActivity)parentActivity).presentFragment(fragment, "chat" + Math.random(), true, false);
}
});
}
@ -331,6 +284,9 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
@Override
public int getCountForSection(int section) {
if (selectedContacts == null) {
return 0;
}
return selectedContacts.size();
}
@ -346,8 +302,6 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
if (holder == null) {
holder = new ContactsActivity.ContactListRowHolder(convertView);
convertView.setTag(holder);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
holder.nameTextView.setTypeface(typeface);
}
View divider = convertView.findViewById(R.id.settings_row_divider);
@ -378,7 +332,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
} else {
int currentTime = ConnectionsManager.Instance.getCurrentTime();
if (user.status.expires > currentTime || user.status.was_online > currentTime) {
holder.messageTextView.setTextColor(0xff006fc8);
holder.messageTextView.setTextColor(0xff357aa8);
holder.messageTextView.setText(getStringEntry(R.string.Online));
} else {
if (user.status.was_online <= 10000 && user.status.expires <= 10000) {

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -9,11 +9,11 @@
package org.telegram.ui;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.text.Html;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@ -22,12 +22,9 @@ import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.BaseFragment;
import org.telegram.ui.Views.IdenticonView;
@ -57,8 +54,6 @@ public class IdenticonActivity extends BaseFragment {
fragmentView = inflater.inflate(R.layout.identicon_layout, container, false);
IdenticonView identiconView = (IdenticonView) fragmentView.findViewById(R.id.identicon_view);
TextView textView = (TextView)fragmentView.findViewById(R.id.identicon_text);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
textView.setTypeface(typeface);
TLRPC.EncryptedChat encryptedChat = MessagesController.Instance.encryptedChats.get(chat_id);
if (encryptedChat != null) {
identiconView.setBytes(encryptedChat.auth_key);
@ -87,15 +82,15 @@ public class IdenticonActivity extends BaseFragment {
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setSubtitle(null);
actionBar.setCustomView(null);
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.EncryptionKey) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.EncryptionKey));
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
}
if (title != null) {
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_blue, 0, 0, 0);
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_white, 0, 0, 0);
title.setCompoundDrawablePadding((int)(4 * getResources().getDisplayMetrics().density));
}
}
@ -112,7 +107,7 @@ public class IdenticonActivity extends BaseFragment {
if (isFinish) {
return;
}
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).showActionBar();
@ -129,36 +124,25 @@ public class IdenticonActivity extends BaseFragment {
public boolean onPreDraw() {
LinearLayout layout = (LinearLayout)fragmentView;
WindowManager manager = (WindowManager)parentActivity.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
int height;
int currentActionBarHeight = parentActivity.getSupportActionBar().getHeight();
int rotation = manager.getDefaultDisplay().getRotation();
float density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
if (currentActionBarHeight != 48 * density && currentActionBarHeight != 40 * density) {
height = currentActionBarHeight;
} else {
height = (int)(48.0f * density);
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
height = (int)(40.0f * density);
layout.setOrientation(LinearLayout.HORIZONTAL);
}
}
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
layout.setOrientation(LinearLayout.HORIZONTAL);
} else {
layout.setOrientation(LinearLayout.VERTICAL);
}
v.setPadding(v.getPaddingLeft(), height, v.getPaddingRight(), v.getPaddingBottom());
v.setPadding(v.getPaddingLeft(), 0, v.getPaddingRight(), v.getPaddingBottom());
v.getViewTreeObserver().removeOnPreDrawListener(this);
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = ApplicationLoader.applicationContext.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
}
if (title != null) {
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_blue, 0, 0, 0);
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_white, 0, 0, 0);
title.setCompoundDrawablePadding((int)(4 * density));
}
@ -169,7 +153,7 @@ public class IdenticonActivity extends BaseFragment {
}
@Override
public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case android.R.id.home:

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -8,59 +8,38 @@
package org.telegram.ui;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.text.Html;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import java.util.Locale;
public class IntroActivity extends SherlockFragmentActivity {
public class IntroActivity extends ActionBarActivity {
private ViewPager viewPager;
private ImageView topImage1;
private ImageView topImage2;
private View slidingView;
private View parentSlidingView;
private TextView startMessagingButton;
private ViewGroup bottomPages;
private int lastPage = 0;
private float density = 1;
private boolean isRTL = false;
private boolean justCreated = false;
private boolean startPressed = false;
private int[][] colors2 = new int[][] {
new int[] {179, 179, 179},
new int[] {247, 91, 47},
new int[] {249, 145, 23},
new int[] {250, 200, 0},
new int[] {93, 195, 38},
new int[] {47, 146, 232}
};
private int[] icons;
private int[] titles;
private int[] messages;
int fixedFirstNum1;
int fixedFirstNum2;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -73,14 +52,16 @@ public class IntroActivity extends SherlockFragmentActivity {
if (lang != null && lang.toLowerCase().equals("ar")) {
isRTL = true;
icons = new int[] {
R.drawable.icon5,
R.drawable.icon4,
R.drawable.icon3,
R.drawable.icon2,
R.drawable.icon1,
R.drawable.icon0
R.drawable.intro7,
R.drawable.intro6,
R.drawable.intro5,
R.drawable.intro4,
R.drawable.intro3,
R.drawable.intro2,
R.drawable.intro1
};
titles = new int[] {
R.string.Page7Title,
R.string.Page6Title,
R.string.Page5Title,
R.string.Page4Title,
@ -89,6 +70,7 @@ public class IntroActivity extends SherlockFragmentActivity {
R.string.Page1Title
};
messages = new int[] {
R.string.Page7Message,
R.string.Page6Message,
R.string.Page5Message,
R.string.Page4Message,
@ -96,16 +78,15 @@ public class IntroActivity extends SherlockFragmentActivity {
R.string.Page2Message,
R.string.Page1Message
};
fixedFirstNum1 = 5;
fixedFirstNum2 = 4;
} else {
icons = new int[] {
R.drawable.icon0,
R.drawable.icon1,
R.drawable.icon2,
R.drawable.icon3,
R.drawable.icon4,
R.drawable.icon5
R.drawable.intro1,
R.drawable.intro2,
R.drawable.intro3,
R.drawable.intro4,
R.drawable.intro5,
R.drawable.intro6,
R.drawable.intro7
};
titles = new int[] {
R.string.Page1Title,
@ -113,7 +94,8 @@ public class IntroActivity extends SherlockFragmentActivity {
R.string.Page3Title,
R.string.Page4Title,
R.string.Page5Title,
R.string.Page6Title
R.string.Page6Title,
R.string.Page7Title
};
messages = new int[] {
R.string.Page1Message,
@ -121,18 +103,16 @@ public class IntroActivity extends SherlockFragmentActivity {
R.string.Page3Message,
R.string.Page4Message,
R.string.Page5Message,
R.string.Page6Message
R.string.Page6Message,
R.string.Page7Message
};
fixedFirstNum1 = 0;
fixedFirstNum2 = 1;
}
density = getResources().getDisplayMetrics().density;
viewPager = (ViewPager)findViewById(R.id.intro_view_pager);
slidingView = findViewById(R.id.sliding_view);
parentSlidingView = findViewById(R.id.parent_slinding_view);
startMessagingButton = (TextView)findViewById(R.id.start_messaging_button);
topImage1 = (ImageView)findViewById(R.id.icon_image1);
topImage2 = (ImageView)findViewById(R.id.icon_image2);
bottomPages = (ViewGroup)findViewById(R.id.bottom_pages);
topImage2.setVisibility(View.GONE);
viewPager.setAdapter(new IntroAdapter());
viewPager.setPageMargin(0);
@ -140,7 +120,7 @@ public class IntroActivity extends SherlockFragmentActivity {
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateColors(position, positionOffset);
}
@Override
@ -230,7 +210,6 @@ public class IntroActivity extends SherlockFragmentActivity {
justCreated = true;
getSupportActionBar().hide();
fixLayout();
}
@Override
@ -238,8 +217,8 @@ public class IntroActivity extends SherlockFragmentActivity {
super.onResume();
if (justCreated) {
if (isRTL) {
viewPager.setCurrentItem(5);
lastPage = 5;
viewPager.setCurrentItem(6);
lastPage = 6;
} else {
viewPager.setCurrentItem(0);
lastPage = 0;
@ -248,94 +227,17 @@ public class IntroActivity extends SherlockFragmentActivity {
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
private void fixLayout() {
viewPager.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
WindowManager manager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int rotation = display.getRotation();
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)parentSlidingView.getLayoutParams();
FrameLayout.LayoutParams buttonParams = (FrameLayout.LayoutParams)startMessagingButton.getLayoutParams();
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, (int)(50 * density));
buttonParams.height = (int)(density * 52);
} else {
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, (int)(82 * density));
buttonParams.height = (int)(density * 84);
}
parentSlidingView.setLayoutParams(params);
startMessagingButton.setLayoutParams(buttonParams);
updateColors(viewPager.getCurrentItem(), 0);
viewPager.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
private void updateColors(int position, float positionOffset) {
int colorPosition = position;
int nextColorPosition = colorPosition + 1;
float offset = positionOffset;
if (isRTL) {
colorPosition = 5 - position;
if (positionOffset != 0) {
colorPosition--;
offset = 1 - offset;
}
nextColorPosition = colorPosition + 1;
}
if (colorPosition >= 0) {
int r = colors2[colorPosition][0];
int g = colors2[colorPosition][1];
int b = colors2[colorPosition][2];
if (nextColorPosition < colors2.length && nextColorPosition > 0 && offset != 0) {
r += (colors2[nextColorPosition][0] - colors2[colorPosition][0]) * offset;
g += (colors2[nextColorPosition][1] - colors2[colorPosition][1]) * offset;
b += (colors2[nextColorPosition][2] - colors2[colorPosition][2]) * offset;
}
slidingView.setBackgroundColor(colorFromRGB(r, g, b));
}
int width = parentSlidingView.getWidth() / 6;
FrameLayout.LayoutParams parentParams = (FrameLayout.LayoutParams)parentSlidingView.getLayoutParams();
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)slidingView.getLayoutParams();
int posX = (int)(24 * density + position * width + positionOffset * width);
if (position >= colors2.length - 2) {
int missed = parentSlidingView.getWidth() - width * 6;
posX += missed * (position == colors2.length - 2 ? positionOffset : 1);
}
params.width = width;
params.setMargins(posX, params.topMargin, params.rightMargin, parentParams.bottomMargin);
slidingView.setLayoutParams(params);
}
private int colorFromRGB(int red, int green, int blue) {
return 0xff000000 | red << 16 | green << 8 | blue;
}
private class IntroAdapter extends PagerAdapter {
@Override
public int getCount() {
return 6;
return 7;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = View.inflate(container.getContext(), R.layout.intro_view_layout, null);
TextView headerTextView = (TextView)view.findViewById(R.id.header_text);
Typeface typeface = Utilities.getTypeface("fonts/rlight.ttf");
headerTextView.setTypeface(typeface);
TextView messageTextView = (TextView)view.findViewById(R.id.message_text);
messageTextView.setTypeface(typeface);
container.addView(view, 0);
headerTextView.setText(getString(titles[position]));
@ -352,6 +254,15 @@ public class IntroActivity extends SherlockFragmentActivity {
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
int count = bottomPages.getChildCount();
for (int a = 0; a < count; a++) {
View child = bottomPages.getChildAt(a);
if (a == position) {
child.setBackgroundColor(0xff2ca5e0);
} else {
child.setBackgroundColor(0xffbbbbbb);
}
}
}
@Override

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -16,6 +16,7 @@ import android.net.Uri;
import android.os.Bundle;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
@ -104,7 +105,7 @@ public class LaunchActivity extends PausableActivity {
NotificationManager mNotificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}

View File

@ -1,5 +1,5 @@
/*
* This is the source code of Telegram for Android v. 1.2.3.
* This is the source code of Telegram for Android v. 1.3.2.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
@ -13,16 +13,15 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.Html;
import android.support.v7.app.ActionBar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
@ -33,6 +32,7 @@ import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import org.telegram.TL.TLRPC;
import org.telegram.messenger.FileLog;
import org.telegram.objects.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
@ -177,7 +177,7 @@ public class LocationActivity extends BaseFragment implements LocationListener,
if (parentActivity == null) {
return;
}
final ActionBar actionBar = parentActivity.getSupportActionBar();
ActionBar actionBar = parentActivity.getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
@ -186,12 +186,12 @@ public class LocationActivity extends BaseFragment implements LocationListener,
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setCustomView(null);
if (messageObject != null) {
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.ChatLocation) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.ChatLocation));
} else {
actionBar.setTitle(Html.fromHtml("<font color='#006fc8'>" + getStringEntry(R.string.ShareLocation) + "</font>"));
actionBar.setTitle(getStringEntry(R.string.ShareLocation));
}
TextView title = (TextView)parentActivity.findViewById(R.id.abs__action_bar_title);
TextView title = (TextView)parentActivity.findViewById(R.id.action_bar_title);
if (title == null) {
final int subtitleId = parentActivity.getResources().getIdentifier("action_bar_title", "id", "android");
title = (TextView)parentActivity.findViewById(subtitleId);
@ -205,7 +205,7 @@ public class LocationActivity extends BaseFragment implements LocationListener,
@Override
public void onResume() {
super.onResume();
if (getSherlockActivity() == null) {
if (getActivity() == null) {
return;
}
((ApplicationActivity)parentActivity).showActionBar();
@ -319,7 +319,7 @@ public class LocationActivity extends BaseFragment implements LocationListener,
}
positionMarker(location);
} catch (Exception e) {
e.printStackTrace();
FileLog.e("tmessages", e);
}
}

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