Commit 3eed85a3 authored by DrKLO's avatar DrKLO

Video editing and compression on 4.1+ (please test it and send debug info to...

Video editing and compression on 4.1+ (please test it and send debug info to me), Tablet version, a lot of other things (don't upload to markets, it's unstable)
parent 8d412f9e
......@@ -80,7 +80,7 @@ android {
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 326
versionName "1.8.3"
versionCode 327
versionName "1.9.0"
}
}
......@@ -3,12 +3,12 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := tmessages
LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DLOG_DISABLED
LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -O2 -funroll-loops
#LOCAL_LDLIBS := -llog
LOCAL_LDLIBS := -ljnigraphics
LOCAL_LDLIBS := -ljnigraphics -llog
LOCAL_SRC_FILES := \
./opus/src/opus.c \
......@@ -227,6 +227,46 @@ LOCAL_SRC_FILES += \
./libjpeg/jquant2.c \
./libjpeg/jutils.c
LOCAL_SRC_FILES += \
./libyuv/source/compare_common.cc \
./libyuv/source/compare_neon.cc \
./libyuv/source/compare_posix.cc \
./libyuv/source/compare_win.cc \
./libyuv/source/compare.cc \
./libyuv/source/convert_argb.cc \
./libyuv/source/convert_from_argb.cc \
./libyuv/source/convert_from.cc \
./libyuv/source/convert_jpeg.cc \
./libyuv/source/convert_to_argb.cc \
./libyuv/source/convert_to_i420.cc \
./libyuv/source/convert.cc \
./libyuv/source/cpu_id.cc \
./libyuv/source/format_conversion.cc \
./libyuv/source/mjpeg_decoder.cc \
./libyuv/source/mjpeg_validate.cc \
./libyuv/source/planar_functions.cc \
./libyuv/source/rotate_argb.cc \
./libyuv/source/rotate_mips.cc \
./libyuv/source/rotate_neon.cc \
./libyuv/source/rotate_neon64.cc \
./libyuv/source/rotate.cc \
./libyuv/source/row_any.cc \
./libyuv/source/row_common.cc \
./libyuv/source/row_mips.cc \
./libyuv/source/row_neon.cc \
./libyuv/source/row_neon64.cc \
./libyuv/source/row_posix.cc \
./libyuv/source/row_win.cc \
./libyuv/source/scale_argb.cc \
./libyuv/source/scale_common.cc \
./libyuv/source/scale_mips.cc \
./libyuv/source/scale_neon.cc \
./libyuv/source/scale_neon64.cc \
./libyuv/source/scale_posix.cc \
./libyuv/source/scale_win.cc \
./libyuv/source/scale.cc \
./libyuv/source/video_common.cc
LOCAL_SRC_FILES += \
./jni.c \
./sqlite_cursor.c \
......@@ -237,6 +277,7 @@ LOCAL_SRC_FILES += \
./gif.c \
./utils.c \
./image.c \
./video.c \
./fake.c
include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
......@@ -2,5 +2,5 @@
void fakeFunction() {
printf("some androids has buggy native loader, so i should check size of libs in java to know that native library is correct. So each changed native library should has diffrent size in different app versions. This function will increase lib size for few bytes :)");
printf("bla blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla");
printf("");
}
......@@ -4,7 +4,7 @@
#include <android/log.h>
#include <jni.h>
#define LOG_TAG "tmessages_native"
#define LOG_TAG "tmessages"
#ifndef LOG_DISABLED
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
......
#include <jni.h>
#include <libyuv.h>
#include <utils.h>
enum COLOR_FORMATTYPE {
COLOR_FormatMonochrome = 1,
COLOR_Format8bitRGB332 = 2,
COLOR_Format12bitRGB444 = 3,
COLOR_Format16bitARGB4444 = 4,
COLOR_Format16bitARGB1555 = 5,
COLOR_Format16bitRGB565 = 6,
COLOR_Format16bitBGR565 = 7,
COLOR_Format18bitRGB666 = 8,
COLOR_Format18bitARGB1665 = 9,
COLOR_Format19bitARGB1666 = 10,
COLOR_Format24bitRGB888 = 11,
COLOR_Format24bitBGR888 = 12,
COLOR_Format24bitARGB1887 = 13,
COLOR_Format25bitARGB1888 = 14,
COLOR_Format32bitBGRA8888 = 15,
COLOR_Format32bitARGB8888 = 16,
COLOR_FormatYUV411Planar = 17,
COLOR_FormatYUV411PackedPlanar = 18,
COLOR_FormatYUV420Planar = 19,
COLOR_FormatYUV420PackedPlanar = 20,
COLOR_FormatYUV420SemiPlanar = 21,
COLOR_FormatYUV422Planar = 22,
COLOR_FormatYUV422PackedPlanar = 23,
COLOR_FormatYUV422SemiPlanar = 24,
COLOR_FormatYCbYCr = 25,
COLOR_FormatYCrYCb = 26,
COLOR_FormatCbYCrY = 27,
COLOR_FormatCrYCbY = 28,
COLOR_FormatYUV444Interleaved = 29,
COLOR_FormatRawBayer8bit = 30,
COLOR_FormatRawBayer10bit = 31,
COLOR_FormatRawBayer8bitcompressed = 32,
COLOR_FormatL2 = 33,
COLOR_FormatL4 = 34,
COLOR_FormatL8 = 35,
COLOR_FormatL16 = 36,
COLOR_FormatL24 = 37,
COLOR_FormatL32 = 38,
COLOR_FormatYUV420PackedSemiPlanar = 39,
COLOR_FormatYUV422PackedSemiPlanar = 40,
COLOR_Format18BitBGR666 = 41,
COLOR_Format24BitARGB6666 = 42,
COLOR_Format24BitABGR6666 = 43,
COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100,
COLOR_FormatSurface = 0x7F000789,
COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00
};
int isSemiPlanarYUV(int colorFormat) {
switch (colorFormat) {
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
return 0;
case COLOR_FormatYUV420SemiPlanar:
case COLOR_FormatYUV420PackedSemiPlanar:
case COLOR_TI_FormatYUV420PackedSemiPlanar:
return 1;
default:
return 0;
}
}
JNIEXPORT int Java_org_telegram_messenger_Utilities_convertVideoFrame(JNIEnv *env, jclass class, jobject src, jobject dest, int destFormat, int width, int height, int padding) {
if (!src || !dest || !destFormat) {
return 0;
}
jbyte *srcBuff = (*env)->GetDirectBufferAddress(env, src);
jbyte *destBuff = (*env)->GetDirectBufferAddress(env, dest);
int half_width = (width + 1) / 2;
int half_height = (height + 1) / 2;
if (!isSemiPlanarYUV(destFormat)) {
ARGBToI420(srcBuff, width * 4,
destBuff, width,
destBuff + width * height + half_width * half_height + padding * 5 / 4, half_width,
destBuff + width * height + padding, half_width,
width, height);
} else {
ARGBToNV21(srcBuff, width * 4,
destBuff, width,
destBuff + width * height + padding, half_width * 2,
width, height);
}
return 1;
}
......@@ -98,8 +98,7 @@
</activity>
<activity
android:name="org.telegram.ui.IntroActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait">
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
</activity>
<activity
android:name="org.telegram.ui.PopupNotificationActivity"
......
......@@ -23,10 +23,13 @@ import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.ApplicationLoader;
import java.io.File;
import java.util.Hashtable;
import java.util.Locale;
public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<String, Typeface>();
......@@ -39,13 +42,44 @@ public class AndroidUtilities {
public static float density = 1;
public static Point displaySize = new Point();
public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002};
public static int[] arrUsersAvatars = {
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_red,
R.drawable.group_green,
R.drawable.group_yellow,
R.drawable.group_blue,
R.drawable.group_violet,
R.drawable.group_pink,
R.drawable.group_aqua,
R.drawable.group_orange};
public static int[] arrBroadcastAvatars = {
R.drawable.broadcast_red,
R.drawable.broadcast_green,
R.drawable.broadcast_yellow,
R.drawable.broadcast_blue,
R.drawable.broadcast_violet,
R.drawable.broadcast_pink,
R.drawable.broadcast_aqua,
R.drawable.broadcast_orange};
static {
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
checkDisplaySize();
}
public static void lockOrientation(Activity activity) {
if (prevOrientation != -10) {
if (activity == null || prevOrientation != -10) {
return;
}
try {
......@@ -103,6 +137,9 @@ public class AndroidUtilities {
}
public static void unlockOrientation(Activity activity) {
if (activity == null) {
return;
}
try {
if (prevOrientation != -10) {
activity.setRequestedOrientation(prevOrientation);
......@@ -229,4 +266,60 @@ public class AndroidUtilities {
public static void RunOnUIThread(Runnable runnable) {
ApplicationLoader.applicationHandler.post(runnable);
}
public static boolean isTablet() {
return (ApplicationLoader.applicationContext.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
public static int getColorIndex(int id) {
int[] arr;
if (id >= 0) {
arr = arrUsersAvatars;
} else {
arr = arrGroupsAvatars;
}
try {
String str;
if (id >= 0) {
str = String.format(Locale.US, "%d%d", id, UserConfig.getClientUserId());
} else {
str = String.format(Locale.US, "%d", id);
}
if (str.length() > 15) {
str = str.substring(0, 15);
}
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
int b = digest[Math.abs(id % 16)];
if (b < 0) {
b += 256;
}
return Math.abs(b) % arr.length;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return id % arr.length;
}
public static int getColorForId(int id) {
if (id / 1000 == 333) {
return 0xff0f94ed;
}
return arrColors[getColorIndex(id)];
}
public static int getUserAvatarForId(int id) {
if (id / 1000 == 333 || id / 1000 == 777) {
return R.drawable.telegram_avatar;
}
return arrUsersAvatars[getColorIndex(id)];
}
public static int getGroupAvatarForId(int id) {
return arrGroupsAvatars[getColorIndex(-Math.abs(id))];
}
public static int getBroadcastAvatarForId(int id) {
return arrBroadcastAvatars[getColorIndex(-Math.abs(id))];
}
}
......@@ -17,6 +17,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.util.SparseArray;
import org.telegram.PhoneFormat.PhoneFormat;
......@@ -48,6 +49,7 @@ public class ContactsController {
private boolean contactsBookLoaded = false;
private String lastContactsVersions = "";
private ArrayList<Integer> delayedContactsUpdate = new ArrayList<Integer>();
public int nameDisplayOrder = 1;
public static class Contact {
public int id;
......@@ -99,6 +101,14 @@ public class ContactsController {
return localInstance;
}
public ContactsController() {
try {
nameDisplayOrder = Settings.System.getInt(ApplicationLoader.applicationContext.getContentResolver(), "android.contacts.DISPLAY_ORDER");
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
public void cleanup() {
contactsBook.clear();
contactsBookSPhones.clear();
......@@ -1465,7 +1475,7 @@ public class ContactsController {
MessagesStorage.getInstance().putContacts(arrayList, false);
if (u.phone != null && u.phone.length() > 0) {
String name = Utilities.formatName(u.first_name, u.last_name);
String name = formatName(u.first_name, u.last_name);
MessagesStorage.getInstance().applyPhoneBookUpdates(u.phone, "");
Contact contact = contactsBookSPhones.get(u.phone);
if (contact != null) {
......@@ -1529,7 +1539,7 @@ public class ContactsController {
for (TLRPC.User user : users) {
if (user.phone != null && user.phone.length() > 0) {
String name = Utilities.formatName(user.first_name, user.last_name);
String name = ContactsController.formatName(user.first_name, user.last_name);
MessagesStorage.getInstance().applyPhoneBookUpdates(user.phone, "");
Contact contact = contactsBookSPhones.get(user.phone);
if (contact != null) {
......@@ -1563,4 +1573,24 @@ public class ContactsController {
}
}, true, RPCRequest.RPCRequestClassGeneric);
}
public static String formatName(String firstName, String lastName) {
String result = null;
if (ContactsController.getInstance().nameDisplayOrder == 1) {
result = firstName;
if (result == null || result.length() == 0) {
result = lastName;
} else if (result.length() != 0 && lastName != null && lastName.length() != 0) {
result += " " + lastName;
}
} else {
result = lastName;
if (result == null || result.length() == 0) {
result = firstName;
} else if (result.length() != 0 && firstName != null && firstName.length() != 0) {
result += " " + firstName;
}
}
return result.trim();
}
}
......@@ -214,7 +214,11 @@ public class Emoji {
emojiFullSize = 90;
}
drawImgSize = AndroidUtilities.dp(20);
if (AndroidUtilities.isTablet()) {
bigImgSize = AndroidUtilities.dp(40);
} else {
bigImgSize = AndroidUtilities.dp(30);
}
for (int j = 1; j < data.length; j++) {
for (int i = 0; i < data[j].length; i++) {
......
......@@ -91,7 +91,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouCreateGroup", R.string.ActionYouCreateGroup);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionCreateGroup", R.string.ActionCreateGroup).replace("un1", "");
}
......@@ -102,7 +102,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouLeftUser", R.string.ActionYouLeftUser);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionLeftUser", R.string.ActionLeftUser).replace("un1", "");
}
......@@ -117,11 +117,11 @@ public class MessageObject {
}
if (who != null && fromUser != null) {
if (isFromMe()) {
messageText = LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser).replace("un2", Utilities.formatName(who.first_name, who.last_name));
messageText = LocaleController.getString("ActionYouKickUser", R.string.ActionYouKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name));
} else if (message.action.user_id == UserConfig.getClientUserId()) {
messageText = LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionKickUserYou", R.string.ActionKickUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", Utilities.formatName(who.first_name, who.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", ContactsController.formatName(who.first_name, who.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
}
} else {
messageText = LocaleController.getString("ActionKickUser", R.string.ActionKickUser).replace("un2", "").replace("un1", "");
......@@ -137,11 +137,11 @@ public class MessageObject {
}
if (whoUser != null && fromUser != null) {
if (isFromMe()) {
messageText = LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser).replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name));
messageText = LocaleController.getString("ActionYouAddUser", R.string.ActionYouAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name));
} else if (message.action.user_id == UserConfig.getClientUserId()) {
messageText = LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionAddUserYou", R.string.ActionAddUserYou).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", Utilities.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", ContactsController.formatName(whoUser.first_name, whoUser.last_name)).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
}
} else {
messageText = LocaleController.getString("ActionAddUser", R.string.ActionAddUser).replace("un2", "").replace("un1", "");
......@@ -151,7 +151,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouChangedPhoto", R.string.ActionYouChangedPhoto);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionChangedPhoto", R.string.ActionChangedPhoto).replace("un1", "");
}
......@@ -161,7 +161,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouChangedTitle", R.string.ActionYouChangedTitle).replace("un2", message.action.title);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name)).replace("un2", message.action.title);
} else {
messageText = LocaleController.getString("ActionChangedTitle", R.string.ActionChangedTitle).replace("un1", "").replace("un2", message.action.title);
}
......@@ -171,7 +171,7 @@ public class MessageObject {
messageText = LocaleController.getString("ActionYouRemovedPhoto", R.string.ActionYouRemovedPhoto);
} else {
if (fromUser != null) {
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.getString("ActionRemovedPhoto", R.string.ActionRemovedPhoto).replace("un1", "");
}
......@@ -232,13 +232,13 @@ public class MessageObject {
messageText = LocaleController.formatString("NotificationUnrecognizedDevice", R.string.NotificationUnrecognizedDevice, name, date, message.action.title, message.action.address);
} else if (message.action instanceof TLRPC.TL_messageActionUserJoined) {
if (fromUser != null) {
messageText = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, "");
}
} else if (message.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
if (fromUser != null) {
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, Utilities.formatName(fromUser.first_name, fromUser.last_name));
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, ContactsController.formatName(fromUser.first_name, fromUser.last_name));
} else {
messageText = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, "");
}
......@@ -443,11 +443,24 @@ public class MessageObject {
}
int maxWidth;
if (AndroidUtilities.isTablet()) {
int min = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
int leftWidth = min / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
if (messageOwner.to_id.chat_id != 0) {
maxWidth = min - leftWidth - AndroidUtilities.dp(122);
} else {
maxWidth = min - leftWidth - AndroidUtilities.dp(80);
}
} else {
if (messageOwner.to_id.chat_id != 0) {
maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122);
} else {
maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80);
}
}
StaticLayout textLayout = null;
......@@ -485,12 +498,17 @@ public class MessageObject {
CharSequence str = messageText.subSequence(startCharacter, endCharacter);
block.textLayout = new StaticLayout(str, textPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
block.textYOffset = textLayout.getLineTop(linesOffset);
if (a != blocksCount - 1) {
if (a != 0) {
blockHeight = Math.min(blockHeight, (int)(block.textYOffset - prevOffset));
}
prevOffset = block.textYOffset;
/*if (a != blocksCount - 1) {
int height = block.textLayout.getHeight();
blockHeight = Math.min(blockHeight, block.textLayout.getHeight());
prevOffset = block.textYOffset;
} else {
blockHeight = Math.min(blockHeight, (int)(block.textYOffset - prevOffset));
}
}*/
} catch (Exception e) {
FileLog.e("tmessages", e);
continue;
......
......@@ -143,7 +143,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
maxGroupCount = preferences.getInt("maxGroupCount", 200);
maxBroadcastCount = preferences.getInt("maxBroadcastCount", 100);
fontSize = preferences.getInt("fons_size", 16);
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
}
public void updateConfig(final TLRPC.TL_config config) {
......@@ -1175,7 +1175,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
if (label.length() != 0) {
label += ", ";
}
label += Utilities.formatName(user.first_name, user.last_name);
label += ContactsController.formatName(user.first_name, user.last_name);
count++;
}
if (count == 2) {
......@@ -3462,9 +3462,23 @@ public class MessagesController implements NotificationCenter.NotificationCenter
changed = true;
}
} else {
boolean change = false;
if (dialog.top_message > 0 && lastMessage.messageOwner.id > 0 && lastMessage.messageOwner.id > dialog.top_message ||
dialog.top_message < 0 && lastMessage.messageOwner.id < 0 && lastMessage.messageOwner.id < dialog.top_message ||
dialog.last_message_date < lastMessage.messageOwner.date) {
dialog.top_message < 0 && lastMessage.messageOwner.id < 0 && lastMessage.messageOwner.id < dialog.top_message) {
change = true;
} else {
MessageObject currentDialogMessage = dialogMessage.get(dialog.top_message);
if (currentDialogMessage != null) {
if (currentDialogMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING && lastMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
change = true;
} else if (dialog.last_message_date < lastMessage.messageOwner.date || dialog.last_message_date == lastMessage.messageOwner.date && lastMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
change = true;
}
} else {
change = true;
}
}
if (change) {
dialogMessage.remove(dialog.top_message);
dialog.top_message = lastMessage.messageOwner.id;
if (!isBroadcast) {
......
......@@ -1253,7 +1253,7 @@ public class MessagesStorage {
if (user.status != null) {
user.status.expires = cursor.intValue(7);
}
resultArrayNames.add(Html.fromHtml("<font color=\"#00a60e\">" + Utilities.formatName(user.first_name, user.last_name) + "</font>"));
resultArrayNames.add(Html.fromHtml("<font color=\"#00a60e\">" + ContactsController.formatName(user.first_name, user.last_name) + "</font>"));
resultArray.add(chat);
encUsers.add(user);
}
......
......@@ -24,9 +24,9 @@ import java.util.zip.ZipFile;
public class NativeLoader {
private static final long sizes[] = new long[] {
811664, //armeabi
864932, //armeabi-v7a
1262644, //x86
946908, //armeabi
1028848, //armeabi-v7a
1603780, //x86
0, //mips
};
......
......@@ -38,6 +38,7 @@ public class NotificationCenter {
public static final int notificationsSettingsUpdated = 26;
public static final int pushMessagesUpdated = 27;
public static final int blockedUsersDidLoaded = 28;
public static final int openedChatChanged = 29;
public static final int wallpapersDidLoaded = 171;
public static final int closeOtherAppActivities = 702;
......@@ -67,7 +68,7 @@ public class NotificationCenter {
final private HashMap<Integer, Object> removeAfterBroadcast = new HashMap<Integer, Object>();
final private HashMap<Integer, Object> addAfterBroadcast = new HashMap<Integer, Object>();
private boolean broadcasting = false;
private int broadcasting = 0;
private static volatile NotificationCenter Instance = null;
public static NotificationCenter getInstance() {
......@@ -89,14 +90,15 @@ public class NotificationCenter {
public void postNotificationName(int id, Object... args) {
synchronized (observers) {
broadcasting = true;
broadcasting++;
ArrayList<Object> objects = observers.get(id);
if (objects != null) {
for (Object obj : objects) {
((NotificationCenterDelegate)obj).didReceivedNotification(id, args);
}
}
broadcasting = false;
broadcasting--;
if (broadcasting == 0) {
if (!removeAfterBroadcast.isEmpty()) {
for (HashMap.Entry<Integer, Object> entry : removeAfterBroadcast.entrySet()) {
removeObserver(entry.getValue(), entry.getKey());
......@@ -111,10 +113,11 @@ public class NotificationCenter {
}
}
}
}
public void addObserver(Object observer, int id) {
synchronized (observers) {
if (broadcasting) {
if (broadcasting != 0) {
addAfterBroadcast.put(id, observer);
return;
}
......@@ -131,7 +134,7 @@ public class NotificationCenter {
public void removeObserver(Object observer, int id) {
synchronized (observers) {
if (broadcasting) {
if (broadcasting != 0) {
removeAfterBroadcast.put(id, observer);
return;
}
......
......@@ -30,7 +30,6 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.ApplicationLoader;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PopupNotificationActivity;
......@@ -126,9 +125,9 @@ public class NotificationsController {
if (preferences.getBoolean("EnablePreviewAll", true)) {
if (messageObject.messageOwner instanceof TLRPC.TL_messageService) {
if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined) {
msg = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationContactJoined", R.string.NotificationContactJoined, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
msg = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationContactNewPhoto", R.string.NotificationContactNewPhoto, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
String date = String.format("%s %s %s", LocaleController.formatterYear.format(((long)messageObject.messageOwner.date) * 1000), LocaleController.getString("OtherAt", R.string.OtherAt), LocaleController.formatterDay.format(((long)messageObject.messageOwner.date) * 1000));
msg = LocaleController.formatString("NotificationUnrecognizedDevice", R.string.NotificationUnrecognizedDevice, UserConfig.getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address);
......@@ -136,26 +135,26 @@ public class NotificationsController {
} else {
if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty) {
if (messageObject.messageOwner.message != null && messageObject.messageOwner.message.length() != 0) {
msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, Utilities.formatName(user.first_name, user.last_name), messageObject.messageOwner.message);
msg = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, ContactsController.formatName(user.first_name, user.last_name), messageObject.messageOwner.message);
} else {
msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, ContactsController.formatName(user.first_name, user.last_name));
}
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
msg = LocaleController.formatString("NotificationMessagePhoto", R.string.NotificationMessagePhoto, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessagePhoto", R.string.NotificationMessagePhoto, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
msg = LocaleController.formatString("NotificationMessageVideo", R.string.NotificationMessageVideo, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageVideo", R.string.NotificationMessageVideo, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) {
msg = LocaleController.formatString("NotificationMessageContact", R.string.NotificationMessageContact, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageContact", R.string.NotificationMessageContact, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) {
msg = LocaleController.formatString("NotificationMessageMap", R.string.NotificationMessageMap, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageMap", R.string.NotificationMessageMap, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
msg = LocaleController.formatString("NotificationMessageDocument", R.string.NotificationMessageDocument, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageDocument", R.string.NotificationMessageDocument, ContactsController.formatName(user.first_name, user.last_name));
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaAudio) {
msg = LocaleController.formatString("NotificationMessageAudio", R.string.NotificationMessageAudio, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageAudio", R.string.NotificationMessageAudio, ContactsController.formatName(user.first_name, user.last_name));
}
}
} else {
msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, Utilities.formatName(user.first_name, user.last_name));
msg = LocaleController.formatString("NotificationMessageNoText", R.string.NotificationMessageNoText, ContactsController.formatName(user.first_name, user.last_name));
}
} else if (chat_id != 0) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
......@@ -163,29 +162,29 @@ public class NotificationsController {
if (messageObject.messageOwner instanceof TLRPC.TL_messageService) {
if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) {
if (messageObject.messageOwner.action.user_id == UserConfig.getClientUserId()) {
msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else {
TLRPC.User u2 = MessagesController.getInstance().getUser(messageObject.messageOwner.action.user_id);
if (u2 == null) {
return null;
}
msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, Utilities.formatName(user.first_name, user.last_name), chat.title, Utilities.formatName(u2.first_name, u2.last_name));
msg = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, ContactsController.formatName(user.first_name, user.last_name), chat.title, ContactsController.formatName(u2.first_name, u2.last_name));
}
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) {
msg = LocaleController.formatString("NotificationEditedGroupName", R.string.NotificationEditedGroupName, Utilities.formatName(user.first_name, user.last_name), messageObject.messageOwner.action.title);
msg = LocaleController.formatString("NotificationEditedGroupName", R.string.NotificationEditedGroupName, ContactsController.formatName(user.first_name, user.last_name), messageObject.messageOwner.action.title);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeletePhoto) {
msg = LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser) {
if (messageObject.messageOwner.action.user_id == UserConfig.getClientUserId()) {
msg = LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.action.user_id == user.id) {
msg = LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else {
TLRPC.User u2 = MessagesController.getInstance().getUser(messageObject.messageOwner.action.user_id);
if (u2 == null) {
return null;
}
msg = LocaleController.formatString("NotificationGroupKickMember", R.string.NotificationGroupKickMember, Utilities.formatName(user.first_name, user.last_name), chat.title, Utilities.formatName(u2.first_name, u2.last_name));
msg = LocaleController.formatString("NotificationGroupKickMember", R.string.NotificationGroupKickMember, ContactsController.formatName(user.first_name, user.last_name), chat.title, ContactsController.formatName(u2.first_name, u2.last_name));
}
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatCreate) {
msg = messageObject.messageText.toString();
......@@ -193,26 +192,26 @@ public class NotificationsController {
} else {
if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty) {
if (messageObject.messageOwner.message != null && messageObject.messageOwner.message.length() != 0) {
msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, Utilities.formatName(user.first_name, user.last_name), chat.title, messageObject.messageOwner.message);
msg = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, ContactsController.formatName(user.first_name, user.last_name), chat.title, messageObject.messageOwner.message);
} else {
msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, ContactsController.formatName(user.first_name, user.last_name), chat.title);
}
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
msg = LocaleController.formatString("NotificationMessageGroupPhoto", R.string.NotificationMessageGroupPhoto, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupPhoto", R.string.NotificationMessageGroupPhoto, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVideo) {
msg = LocaleController.formatString("NotificationMessageGroupVideo", R.string.NotificationMessageGroupVideo, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupVideo", R.string.NotificationMessageGroupVideo, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) {
msg = LocaleController.formatString("NotificationMessageGroupContact", R.string.NotificationMessageGroupContact, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupContact", R.string.NotificationMessageGroupContact, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) {
msg = LocaleController.formatString("NotificationMessageGroupMap", R.string.NotificationMessageGroupMap, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupMap", R.string.NotificationMessageGroupMap, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
msg = LocaleController.formatString("NotificationMessageGroupDocument", R.string.NotificationMessageGroupDocument, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupDocument", R.string.NotificationMessageGroupDocument, ContactsController.formatName(user.first_name, user.last_name), chat.title);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaAudio) {
msg = LocaleController.formatString("NotificationMessageGroupAudio", R.string.NotificationMessageGroupAudio, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupAudio", R.string.NotificationMessageGroupAudio, ContactsController.formatName(user.first_name, user.last_name), chat.title);
}
}
} else {
msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, Utilities.formatName(user.first_name, user.last_name), chat.title);
msg = LocaleController.formatString("NotificationMessageGroupNoText", R.string.NotificationMessageGroupNoText, ContactsController.formatName(user.first_name, user.last_name), chat.title);
}
}
} else {
......@@ -358,7 +357,7 @@ public class NotificationsController {
if (chat != null) {
name = chat.title;
} else {
name = Utilities.formatName(user.first_name, user.last_name);
name = ContactsController.formatName(user.first_name, user.last_name);
}
}
......
......@@ -28,6 +28,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
private TLRPC.ChatParticipants currentChatInfo = null;
private HashMap<String, ArrayList<DelayedMessage>> delayedMessages = new HashMap<String, ArrayList<DelayedMessage>>();
private HashMap<Integer, MessageObject> unsentMessages = new HashMap<Integer, MessageObject>();
private class DelayedMessage {
public TLObject sendRequest;
......@@ -153,6 +154,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
arr.remove(a);
a--;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, obj.obj.messageOwner.id);
processSentMessage(obj.obj.messageOwner.id);
}
}
if (arr.isEmpty()) {
......@@ -191,14 +193,25 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
MessagesController.getInstance().deleteMessages(messages, null, null);
}
public boolean retrySendMessage(MessageObject messageObject) {
public boolean retrySendMessage(MessageObject messageObject, boolean unsent) {
if (messageObject.messageOwner.id >= 0) {
return false;
}
if (unsent) {
unsentMessages.put(messageObject.messageOwner.id, messageObject);
}
sendMessage(messageObject);
return true;
}
private void processSentMessage(int id) {
int prevSize = unsentMessages.size();
unsentMessages.remove(id);
if (prevSize != 0 && unsentMessages.size() == 0) {
checkUnsentMessages();
}
}
public void processForwardFromMyName(MessageObject messageObject, long did) {
if (messageObject == null) {
return;
......@@ -271,7 +284,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
}
private void sendMessage(String message, double lat, double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry) {
TLRPC.Message newMsg = null;
int type = -1;
if (retry) {
......@@ -394,12 +406,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.getClientUserId();
newMsg.out = true;
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
UserConfig.saveConfig(false);
}
if (newMsg.random_id == 0) {
newMsg.random_id = getNextRandomId();
}
newMsg.date = ConnectionsManager.getInstance().getCurrentTime();
newMsg.unread = true;
newMsg.dialog_id = peer;
int lower_id = (int) peer;
......@@ -410,6 +422,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (lower_id != 0) {
if (high_id == 1) {
if (currentChatInfo == null) {
processSentMessage(newMsg.id);
return;
}
sendToPeers = new ArrayList<TLRPC.InputUser>();
......@@ -434,6 +447,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id);
if (sendToUser == null) {
processSentMessage(newMsg.id);
return;
}
if (sendToUser instanceof TLRPC.TL_userForeign || sendToUser instanceof TLRPC.TL_userRequest) {
......@@ -767,6 +781,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.messageOwner.id);
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.messageOwner.id);
processSentMessage(newMsgObj.messageOwner.id);
}
}
......@@ -855,11 +870,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
final boolean isBroadcast = req instanceof TLRPC.TL_messages_sendBroadcast;
final ArrayList<TLRPC.Message> sentMessages = new ArrayList<TLRPC.Message>();
if (response instanceof TLRPC.TL_messages_sentMessage) {
if (response instanceof TLRPC.messages_SentMessage) {
TLRPC.TL_messages_sentMessage res = (TLRPC.TL_messages_sentMessage) response;
newMsgObj.messageOwner.id = res.id;
newMsgObj.messageOwner.date = res.date;
MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.date);
//TODO link check
} else if (response instanceof TLRPC.messages_StatedMessage) {
TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage) response;
sentMessages.add(res.message);
......@@ -903,6 +919,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload);
}
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.messageOwner.id), newMsgObj);
processSentMessage(oldId);
}
});
}
......@@ -914,6 +931,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
public void run() {
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.messageOwner.id);
processSentMessage(newMsgObj.messageOwner.id);
}
});
}
......@@ -1009,6 +1027,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
public void run() {
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.messageOwner.id, newMsgObj.messageOwner.id, newMsgObj);
processSentMessage(newMsgObj.messageOwner.id);
}
});
}
......@@ -1020,6 +1039,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
public void run() {
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.messageOwner.id);
processSentMessage(newMsgObj.messageOwner.id);
}
});
}
......@@ -1370,7 +1390,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
MessagesController.getInstance().putEncryptedChats(encryptedChats, true);
for (TLRPC.Message message : messages) {
MessageObject messageObject = new MessageObject(message, null, 0);
retrySendMessage(messageObject);
retrySendMessage(messageObject, true);
}
}
});
......
......@@ -87,7 +87,7 @@ public class MP4Builder {
fos.flush();
}
public void writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) throws Exception {
public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) throws Exception {
if (writeNewMdat) {
mdat.setContentSize(0);
mdat.getBox(fc);
......@@ -111,16 +111,18 @@ public class MP4Builder {
currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo);
byteBuf.position(bufferInfo.offset);
byteBuf.limit(bufferInfo.offset + bufferInfo.size);
fc.write(byteBuf);
dataOffset += bufferInfo.size;
if (flush) {
fos.flush();
}
return flush;
}
public int addTrack(MediaFormat mediaFormat, boolean isVideo) throws Exception {
return currentMp4Movie.addTrack(mediaFormat, isVideo);
public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception {
return currentMp4Movie.addTrack(mediaFormat, isAudio);
}
public void finishMovie(boolean error) throws Exception {
......
......@@ -74,8 +74,8 @@ public class Mp4Movie {
track.addSample(offset, bufferInfo);
}
public int addTrack(MediaFormat mediaFormat, boolean isVideo) throws Exception {
tracks.add(new Track(tracks.size(), mediaFormat, isVideo));
public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception {
tracks.add(new Track(tracks.size(), mediaFormat, isAudio));
return tracks.size() - 1;
}
}
......@@ -18,32 +18,44 @@ package org.telegram.android.video;
import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.GLES20;
import android.view.Surface;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
@TargetApi(17)
@TargetApi(16)
public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private static final int EGL_OPENGL_ES2_BIT = 4;
private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
private EGL10 mEGL;
private EGLDisplay mEGLDisplay;
private EGLContext mEGLContext;
private EGLSurface mEGLSurface;
private EGLDisplay mEGLDisplay = null;
private EGLContext mEGLContext = null;
private EGLSurface mEGLSurface = null;
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
private final Object mFrameSyncObject = new Object();
private boolean mFrameAvailable;
private TextureRenderer mTextureRender;
private int mWidth;
private int mHeight;
private ByteBuffer mPixelBuf;
public OutputSurface(int width, int height) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException();
}
mWidth = width;
mHeight = height;
mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
mPixelBuf.order(ByteOrder.LITTLE_ENDIAN);
eglSetup(width, height);
makeCurrent();
setup();
......@@ -64,28 +76,35 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private void eglSetup(int width, int height) {
mEGL = (EGL10) EGLContext.getEGL();
mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {
throw new RuntimeException("unable to get EGL10 display");
}
if (!mEGL.eglInitialize(mEGLDisplay, null)) {
mEGLDisplay = null;
throw new RuntimeException("unable to initialize EGL10");
}
int[] attribList = {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, 1, numConfigs)) {
if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, configs.length, numConfigs)) {
throw new RuntimeException("unable to find RGB888+pbuffer EGL config");
}
int[] attrib_list = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL10.EGL_NONE
};
mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT,
attrib_list);
mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT, attrib_list);
checkEglError("eglCreateContext");
if (mEGLContext == null) {
throw new RuntimeException("null context");
......@@ -139,7 +158,7 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
public void awaitNewImage() {
final int TIMEOUT_MS = 500;
final int TIMEOUT_MS = 2500;
synchronized (mFrameSyncObject) {
while (!mFrameAvailable) {
try {
......@@ -157,8 +176,8 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
mSurfaceTexture.updateTexImage();
}
public void drawImage() {
mTextureRender.drawFrame(mSurfaceTexture);
public void drawImage(boolean invert) {
mTextureRender.drawFrame(mSurfaceTexture, invert);
}
@Override
......@@ -172,6 +191,12 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
}
public ByteBuffer getFrame() {
mPixelBuf.rewind();
GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
return mPixelBuf;
}
private void checkEglError(String msg) {
if (mEGL.eglGetError() != EGL10.EGL_SUCCESS) {
throw new RuntimeException("EGL error encountered (see log)");
......
......@@ -26,20 +26,21 @@ import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.Matrix;
@TargetApi(17)
@TargetApi(16)
public class TextureRenderer {
private static final int FLOAT_SIZE_BYTES = 4;
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
private static final float[] mTriangleVerticesData = {
// X, Y, Z, U, V
-1.0f, -1.0f, 0, 0.f, 0.f,
1.0f, -1.0f, 0, 1.f, 0.f,
-1.0f, 1.0f, 0, 0.f, 1.f,
1.0f, 1.0f, 0, 1.f, 1.f,
};
private FloatBuffer mTriangleVertices;
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
......@@ -50,14 +51,16 @@ public class TextureRenderer {
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
"}\n";
private static final String FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" + // highp here doesn't seem to matter
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
private float[] mMVPMatrix = new float[16];
private float[] mSTMatrix = new float[16];
private int mProgram;
......@@ -77,11 +80,15 @@ public class TextureRenderer {
return mTextureID;
}
public void drawFrame(SurfaceTexture st) {
public void drawFrame(SurfaceTexture st, boolean invert) {
checkGlError("onDrawFrame start");
st.getTransformMatrix(mSTMatrix);
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
if (invert) {
mSTMatrix[5] = -mSTMatrix[5];
mSTMatrix[13] = 1.0f - mSTMatrix[13];
}
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
......@@ -96,9 +103,8 @@ public class TextureRenderer {
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glFinish();
......@@ -139,6 +145,8 @@ public class TextureRenderer {
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
checkGlError("glTexParameter");
Matrix.setIdentityM(mMVPMatrix, 0);
}
public void changeFragmentShader(String fragmentShader) {
......
......@@ -67,9 +67,9 @@ public class Track {
samplingFrequencyIndexMap.put(8000, 0xb);
}
public Track(int id, MediaFormat format, boolean isVideo) throws Exception {
public Track(int id, MediaFormat format, boolean isAudio) throws Exception {
trackId = id;
if (isVideo) {
if (!isAudio) {
sampleDurations.add((long)3015);
duration = 3015;
width = format.getInteger(MediaFormat.KEY_WIDTH);
......@@ -79,6 +79,8 @@ public class Track {
handler = "vide";
headerBox = new VideoMediaHeaderBox();
sampleDescriptionBox = new SampleDescriptionBox();
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.equals("video/avc")) {
VisualSampleEntry visualSampleEntry = new VisualSampleEntry("avc1");
visualSampleEntry.setDataReferenceIndex(1);
visualSampleEntry.setDepth(24);
......@@ -90,6 +92,7 @@ public class Track {
AvcConfigurationBox avcConfigurationBox = new AvcConfigurationBox();
if (format.getByteBuffer("csd-0") != null) {
ArrayList<byte[]> spsArray = new ArrayList<byte[]>();
ByteBuffer spsBuff = format.getByteBuffer("csd-0");
spsBuff.position(4);
......@@ -103,11 +106,12 @@ public class Track {
byte[] ppsBytes = new byte[ppsBuff.remaining()];
ppsBuff.get(ppsBytes);
ppsArray.add(ppsBytes);
avcConfigurationBox.setSequenceParameterSets(spsArray);
avcConfigurationBox.setPictureParameterSets(ppsArray);
}
//ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(spsBytes);
//SeqParameterSet seqParameterSet = SeqParameterSet.read(byteArrayInputStream);
avcConfigurationBox.setSequenceParameterSets(spsArray);
avcConfigurationBox.setPictureParameterSets(ppsArray);
avcConfigurationBox.setAvcLevelIndication(13);
avcConfigurationBox.setAvcProfileIndication(100);
avcConfigurationBox.setBitDepthLumaMinus8(-1);
......@@ -119,6 +123,18 @@ public class Track {
visualSampleEntry.addBox(avcConfigurationBox);
sampleDescriptionBox.addBox(visualSampleEntry);
} else if (mime.equals("video/mp4v")) {
VisualSampleEntry visualSampleEntry = new VisualSampleEntry("mp4v");
visualSampleEntry.setDataReferenceIndex(1);
visualSampleEntry.setDepth(24);
visualSampleEntry.setFrameCount(1);
visualSampleEntry.setHorizresolution(72);
visualSampleEntry.setVertresolution(72);
visualSampleEntry.setWidth(width);
visualSampleEntry.setHeight(height);
sampleDescriptionBox.addBox(visualSampleEntry);
}
} else {
sampleDurations.add((long)1024);
duration = 1024;
......
......@@ -9,6 +9,7 @@
package org.telegram.messenger;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
......@@ -37,6 +38,7 @@ public class FileLoader {
private ConcurrentHashMap<String, FileUploadOperation> uploadOperationPathsEnc = new ConcurrentHashMap<String, FileUploadOperation>();
private ConcurrentHashMap<String, FileLoadOperation> loadOperationPaths = new ConcurrentHashMap<String, FileLoadOperation>();
private ConcurrentHashMap<String, Float> fileProgresses = new ConcurrentHashMap<String, Float>();
private HashMap<String, Long> uploadSizes = new HashMap<String, Long>();
private FileLoaderDelegate delegate = null;
......@@ -70,6 +72,7 @@ public class FileLoader {
} else {
operation = uploadOperationPathsEnc.get(location);
}
uploadSizes.remove(location);
if (operation != null) {
uploadOperationQueue.remove(operation);
uploadSmallOperationQueue.remove(operation);
......@@ -95,6 +98,8 @@ public class FileLoader {
}
if (operation != null) {
operation.checkNewDataAvailable(finalSize);
} else if (finalSize != 0) {
uploadSizes.put(location, finalSize);
}
}
});
......@@ -117,7 +122,15 @@ public class FileLoader {
return;
}
}
FileUploadOperation operation = new FileUploadOperation(location, encrypted, estimatedSize);
int esimated = estimatedSize;
if (esimated != 0) {
Long finalSize = uploadSizes.get(location);
if (finalSize != null) {
esimated = 0;
uploadSizes.remove(location);
}
}
FileUploadOperation operation = new FileUploadOperation(location, encrypted, esimated);
if (encrypted) {
uploadOperationPathsEnc.put(location, operation);
} else {
......
......@@ -14,7 +14,6 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
......@@ -51,7 +50,6 @@ import java.security.spec.RSAPublicKeySpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
......@@ -74,23 +72,6 @@ public class Utilities {
public static volatile DispatchQueue searchQueue = new DispatchQueue("searchQueue");
public static volatile DispatchQueue photoBookQueue = new DispatchQueue("photoBookQueue");
public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002};
public static int[] arrUsersAvatars = {
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_green,
R.drawable.group_red,
R.drawable.group_blue,
R.drawable.group_yellow};
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static ProgressDialog progressDialog;
......@@ -132,6 +113,7 @@ public class Utilities {
public native static long doPQNative(long _what);
public native static void loadBitmap(String path, int[] bitmap, int scale, int format, int width, int height);
public native static void blurBitmap(Object bitmap);
public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding);
private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length);
public static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, boolean changeIv, int offset, int length) {
......@@ -509,54 +491,6 @@ public class Utilities {
return true;
}
public static int getColorIndex(int id) {
int[] arr;
if (id >= 0) {
arr = arrUsersAvatars;
} else {
arr = arrGroupsAvatars;
}
try {
String str;
if (id >= 0) {
str = String.format(Locale.US, "%d%d", id, UserConfig.getClientUserId());
} else {
str = String.format(Locale.US, "%d", id);
}
if (str.length() > 15) {
str = str.substring(0, 15);
}
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
int b = digest[Math.abs(id % 16)];
if (b < 0) {
b += 256;
}
return Math.abs(b) % arr.length;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return id % arr.length;
}
public static int getColorForId(int id) {
if (id / 1000 == 333) {
return 0xff0f94ed;
}
return arrColors[getColorIndex(id)];
}
public static int getUserAvatarForId(int id) {
if (id / 1000 == 333 || id / 1000 == 777) {
return R.drawable.telegram_avatar;
}
return arrUsersAvatars[getColorIndex(id)];
}
public static int getGroupAvatarForId(int id) {
return arrGroupsAvatars[getColorIndex(-Math.abs(id))];
}
public static String MD5(String md5) {
if (md5 == null) {
return null;
......@@ -757,16 +691,6 @@ public class Utilities {
return null;
}
public static String formatName(String firstName, String lastName) {
String result = firstName;
if (result == null || result.length() == 0) {
result = lastName;
} else if (result.length() != 0 && lastName != null && lastName.length() != 0) {
result += " " + lastName;
}
return result.trim();
}
public static String formatFileSize(long size) {
if (size < 1024) {
return String.format("%d B", size);
......@@ -816,8 +740,4 @@ public class Utilities {
UpdateManager.register(context, BuildVars.HOCKEY_APP_HASH);
}
}
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
}
......@@ -23,7 +23,6 @@ import org.telegram.android.MediaController;
import org.telegram.messenger.TLRPC;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.ImageReceiver;
import org.telegram.ui.Views.ProgressView;
......@@ -355,9 +354,9 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
if (audioUser.photo != null) {
currentPhoto = audioUser.photo.photo_small;
}
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(Utilities.getUserAvatarForId(uid)));
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)));
} else {
avatarImage.setImage((TLRPC.FileLocation)null, "50_50", getResources().getDrawable(Utilities.getUserAvatarForId(uid)));
avatarImage.setImage((TLRPC.FileLocation)null, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(uid)));
}
if (messageObject.isOut()) {
......
......@@ -23,11 +23,11 @@ import android.view.SoundEffectConstants;
import android.view.ViewConfiguration;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController;
import org.telegram.android.LocaleController;
import org.telegram.messenger.TLRPC;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.ImageReceiver;
......@@ -233,7 +233,7 @@ public class ChatBaseCell extends BaseCell {
String newNameString = null;
if (drawName && isChat && newUser != null && !currentMessageObject.isOut()) {
newNameString = Utilities.formatName(newUser.first_name, newUser.last_name);
newNameString = ContactsController.formatName(newUser.first_name, newUser.last_name);
}
if (currentNameString == null && newNameString != null || currentNameString != null && newNameString == null || currentNameString != null && newNameString != null && !currentNameString.equals(newNameString)) {
......@@ -243,7 +243,7 @@ public class ChatBaseCell extends BaseCell {
newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.fwd_from_id);
newNameString = null;
if (newUser != null && drawForwardedName && currentMessageObject.messageOwner instanceof TLRPC.TL_messageForwarded) {
newNameString = Utilities.formatName(newUser.first_name, newUser.last_name);
newNameString = ContactsController.formatName(newUser.first_name, newUser.last_name);
}
return currentForwardNameString == null && newNameString != null || currentForwardNameString != null && newNameString == null || currentForwardNameString != null && newNameString != null && !currentForwardNameString.equals(newNameString);
}
......@@ -265,7 +265,7 @@ public class ChatBaseCell extends BaseCell {
} else {
currentPhoto = null;
}
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(Utilities.getUserAvatarForId(currentUser.id)));
avatarImage.setImage(currentPhoto, "50_50", getResources().getDrawable(AndroidUtilities.getUserAvatarForId(currentUser.id)));
} else {
avatarImage.setImage((TLRPC.FileLocation)null, "50_50", null);
}
......@@ -287,7 +287,7 @@ public class ChatBaseCell extends BaseCell {
namesOffset = 0;
if (drawName && isChat && currentUser != null && !currentMessageObject.isOut()) {
currentNameString = Utilities.formatName(currentUser.first_name, currentUser.last_name);
currentNameString = ContactsController.formatName(currentUser.first_name, currentUser.last_name);
nameWidth = getMaxNameWidth();
CharSequence nameStringFinal = TextUtils.ellipsize(currentNameString.replace("\n", " "), namePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
......@@ -308,7 +308,7 @@ public class ChatBaseCell extends BaseCell {
if (drawForwardedName && messageObject.messageOwner instanceof TLRPC.TL_messageForwarded) {
currentForwardUser = MessagesController.getInstance().getUser(messageObject.messageOwner.fwd_from_id);
if (currentForwardUser != null) {
currentForwardNameString = Utilities.formatName(currentForwardUser.first_name, currentForwardUser.last_name);
currentForwardNameString = ContactsController.formatName(currentForwardUser.first_name, currentForwardUser.last_name);
forwardedNameWidth = getMaxNameWidth();
......@@ -520,7 +520,7 @@ public class ChatBaseCell extends BaseCell {
if (drawName && nameLayout != null) {
canvas.save();
canvas.translate(currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19) - nameOffsetX, AndroidUtilities.dp(10));
namePaint.setColor(Utilities.getColorForId(currentUser.id));
namePaint.setColor(AndroidUtilities.getColorForId(currentUser.id));
nameLayout.draw(canvas);
canvas.restore();
}
......
......@@ -11,6 +11,7 @@ package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
......@@ -19,6 +20,7 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.animation.DecelerateInterpolator;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ImageLoader;
......@@ -32,7 +34,6 @@ import org.telegram.android.PhotoObject;
import org.telegram.ui.PhotoViewer;
import org.telegram.ui.Views.GifDrawable;
import org.telegram.android.ImageReceiver;
import org.telegram.ui.Views.RoundProgressView;
import java.io.File;
import java.util.Locale;
......@@ -54,6 +55,9 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private static MessageObject lastDownloadedGifMessage = null;
private static TextPaint namePaint;
private static Paint docBackPaint;
private static Paint progressPaint;
private static Paint progressBackgroundPaint;
private static DecelerateInterpolator decelerateInterpolator;
private GifDrawable gifDrawable = null;
......@@ -63,7 +67,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private String currentUrl;
private String currentPhotoFilter;
private ImageReceiver photoImage;
private RoundProgressView progressView;
private boolean progressVisible = false;
private boolean photoNotSet = false;
private boolean cancelLoading = false;
......@@ -87,6 +90,15 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
public ChatMediaCellDelegate mediaDelegate = null;
private float currentProgress = 0;
private RectF progressRect = new RectF();
private long lastUpdateTime = 0;
private boolean animationStarted = false;
private float radOffset = 0;
private float animatedProgressValue = 0;
private long currentProgressTime = 0;
private float animationProgressStart = 0;
public ChatMediaCell(Context context) {
super(context);
......@@ -113,12 +125,21 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
namePaint.setTextSize(AndroidUtilities.dp(16));
docBackPaint = new Paint();
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
decelerateInterpolator = new DecelerateInterpolator();
progressBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressBackgroundPaint.setStyle(Paint.Style.STROKE);
progressBackgroundPaint.setStrokeWidth(AndroidUtilities.dp(2));
}
TAG = MediaController.getInstance().generateObserverTag();
photoImage = new ImageReceiver(this);
progressView = new RoundProgressView();
}
public void clearGifImage() {
......@@ -260,6 +281,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video);
}
progressVisible = true;
startAnimation();
buttonState = 1;
invalidate();
} else if (buttonState == 1) {
......@@ -280,6 +302,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.video);
}
progressVisible = false;
stopAnimation();
buttonState = 0;
invalidate();
}
......@@ -342,7 +365,17 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
if (name == null || name.length() == 0) {
name = LocaleController.getString("AttachDocument", R.string.AttachDocument);
}
int maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122 + 86 + 24);
int maxWidth;
if (AndroidUtilities.isTablet()) {
int min = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
int leftWidth = min / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
maxWidth = min - leftWidth - AndroidUtilities.dp(122 + 86 + 24);
} else {
maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122 + 86 + 24);
}
if (currentNameString == null || !currentNameString.equals(name)) {
currentNameString = name;
nameWidth = Math.min(maxWidth, (int) Math.ceil(namePaint.measureText(currentNameString)));
......@@ -426,8 +459,17 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
double lon = messageObject.messageOwner.media.geo._long;
currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=13&size=100x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int)Math.ceil(AndroidUtilities.density)), lat, lon);
photoImage.setImage(currentUrl, null, messageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable);
} else {
if (AndroidUtilities.isTablet()) {
int min = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
int leftWidth = min / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
photoWidth = (int)((min - leftWidth) * 0.7f);
} else {
photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
}
photoHeight = photoWidth + AndroidUtilities.dp(100);
if (photoWidth > 800) {
......@@ -549,13 +591,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
if (currentMessageObject.messageOwner.attachPath != null) {
MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this);
progressVisible = true;
startAnimation();
buttonState = 1;
Float progress = FileLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath);
if (progress != null) {
progressView.setProgress(progress);
} else {
progressView.setProgress(0);
}
setProgress(progress != null ? progress : 0, false);
invalidate();
}
} else {
......@@ -571,25 +610,25 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
if (cancelLoading || currentMessageObject.type != 1 || !MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) {
buttonState = 0;
progressVisible = false;
stopAnimation();
} else {
buttonState = 1;
progressVisible = true;
startAnimation();
}
progressView.setProgress(0);
setProgress(0, false);
} else {
buttonState = 1;
progressVisible = true;
startAnimation();
Float progress = FileLoader.getInstance().getFileProgress(fileName);
if (progress != null) {
progressView.setProgress(progress);
} else {
progressView.setProgress(0);
}
setProgress(progress != null ? progress : 0, false);
}
invalidate();
} else {
MediaController.getInstance().removeLoadingFileObserver(this);
progressVisible = false;
stopAnimation();
if (currentMessageObject.type == 8 && (gifDrawable == null || gifDrawable != null && !gifDrawable.isRunning())) {
buttonState = 2;
} else if (currentMessageObject.type == 3) {
......@@ -602,6 +641,54 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
}
private void updateAnimation() {
long newTime = System.currentTimeMillis();
long dt = newTime - lastUpdateTime;
lastUpdateTime = newTime;
radOffset += 360 * dt / 3000.0f;
float progressDiff = currentProgress - animationProgressStart;
if (progressDiff > 0) {
currentProgressTime += dt;
if (currentProgressTime >= 300) {
animatedProgressValue = currentProgress;
animationProgressStart = currentProgress;
currentProgressTime = 0;
} else {
animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f);
}
}
invalidateProgress();
}
private void startAnimation() {
lastUpdateTime = System.currentTimeMillis();
animationStarted = true;
invalidateProgress();
}
private void setProgress(float value, boolean animated) {
if (!animated) {
animatedProgressValue = value;
animationProgressStart = value;
} else {
animationProgressStart = animatedProgressValue;
}
currentProgress = value;
currentProgressTime = 0;
}
private void invalidateProgress() {
int offset = AndroidUtilities.dp(1);
invalidate((int)progressRect.left - offset, (int)progressRect.top - offset, (int)progressRect.right + offset * 2, (int)progressRect.bottom + offset * 2);
}
private void stopAnimation() {
radOffset = 0;
animationStarted = false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), photoHeight + AndroidUtilities.dp(14));
......@@ -629,7 +716,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
int size = AndroidUtilities.dp(44);
buttonX = (int)(x + (photoWidth - size) / 2.0f);
buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f);
progressView.rect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(43), buttonY + AndroidUtilities.dp(43));
progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(43), buttonY + AndroidUtilities.dp(43));
}
@Override
......@@ -646,6 +733,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
drawTime = photoImage.getVisible();
}
boolean needProgressBackground = false;
if (currentMessageObject.type == 9) {
if (currentMessageObject.isOut()) {
infoPaint.setColor(0xff75b166);
......@@ -664,15 +753,21 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
drawable.draw(canvas);
}
if (currentMessageObject.isOut()) {
progressView.setColor(0xff81bd72);
progressPaint.setColor(0xff81bd72);
progressBackgroundPaint.setColor(0xffbae4a2);
} else {
progressView.setColor(0xffadbdcc);
progressPaint.setColor(0xffadbdcc);
progressBackgroundPaint.setColor(0xffd5dee7);
}
needProgressBackground = true;
} else {
progressView.setColor(0xffffffff);
progressPaint.setColor(0xffffffff);
needProgressBackground = false;
}
} else {
progressView.setColor(0xffffffff);
progressPaint.setColor(0xffffffff);
needProgressBackground = false;
}
if (buttonState >= 0 && buttonState < 4) {
......@@ -687,7 +782,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
}
if (progressVisible) {
progressView.draw(canvas);
if (needProgressBackground) {
canvas.drawArc(progressRect, 0, 360, false, progressBackgroundPaint);
}
canvas.drawArc(progressRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint);
}
if (nameLayout != null) {
......@@ -717,6 +815,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
infoLayout.draw(canvas);
canvas.restore();
}
if (animationStarted) {
updateAnimation();
}
}
@Override
......@@ -738,17 +840,17 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
@Override
public void onProgressDownload(String fileName, float progress) {
progressVisible = true;
progressView.setProgress(progress);
setProgress(progress, true);
if (buttonState != 1) {
updateButtonState();
}
invalidate();
invalidateProgress();
}
@Override
public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {
progressView.setProgress(progress);
invalidate();
setProgress(progress, true);
invalidateProgress();
}
@Override
......
......@@ -131,6 +131,21 @@ public class ChatMessageCell extends ChatBaseCell {
}
pressedLink = null;
int maxWidth;
if (AndroidUtilities.isTablet()) {
int min = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
int leftWidth = min / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
if (isChat && !messageObject.isOut()) {
maxWidth = min - leftWidth - AndroidUtilities.dp(122);
drawName = true;
} else {
maxWidth = min - leftWidth - AndroidUtilities.dp(80);
drawName = false;
}
} else {
if (isChat && !messageObject.isOut()) {
maxWidth = AndroidUtilities.displaySize.x - AndroidUtilities.dp(122);
drawName = true;
......@@ -138,6 +153,7 @@ public class ChatMessageCell extends ChatBaseCell {
maxWidth = AndroidUtilities.displaySize.x - AndroidUtilities.dp(80);
drawName = false;
}
}
backgroundWidth = maxWidth;
......
......@@ -19,13 +19,13 @@ import android.text.TextUtils;
import org.telegram.android.AndroidUtilities;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.android.ContactsController;
import org.telegram.android.LocaleController;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.android.ImageReceiver;
public class ChatOrUserCell extends BaseCell {
......@@ -157,12 +157,16 @@ public class ChatOrUserCell extends BaseCell {
if (user.photo != null) {
photo = user.photo.photo_small;
}
placeHolderId = Utilities.getUserAvatarForId(user.id);
placeHolderId = AndroidUtilities.getUserAvatarForId(user.id);
} else if (chat != null) {
if (chat.photo != null) {
photo = chat.photo.photo_small;
}
placeHolderId = Utilities.getGroupAvatarForId(chat.id);
if (chat.id > 0) {
placeHolderId = AndroidUtilities.getGroupAvatarForId(chat.id);
} else {
placeHolderId = AndroidUtilities.getBroadcastAvatarForId(chat.id);
}
}
if (mask != 0) {
......@@ -339,7 +343,7 @@ public class ChatOrUserCell extends BaseCell {
if (chat != null) {
nameString2 = chat.title;
} else if (user != null) {
nameString2 = Utilities.formatName(user.first_name, user.last_name);
nameString2 = ContactsController.formatName(user.first_name, user.last_name);
}
nameString = nameString2.replace("\n", " ");
}
......
......@@ -27,7 +27,6 @@ import org.telegram.android.Emoji;
import org.telegram.android.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.ImageReceiver;
......@@ -155,6 +154,10 @@ public class DialogCell extends BaseCell {
update(0);
}
public TLRPC.TL_dialog getDialog() {
return currentDialog;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
......@@ -249,12 +252,16 @@ public class DialogCell extends BaseCell {
if (user.photo != null) {
photo = user.photo.photo_small;
}
placeHolderId = Utilities.getUserAvatarForId(user.id);
placeHolderId = AndroidUtilities.getUserAvatarForId(user.id);
} else if (chat != null) {
if (chat.photo != null) {
photo = chat.photo.photo_small;
}
placeHolderId = Utilities.getGroupAvatarForId(chat.id);
if (chat.id > 0) {
placeHolderId = AndroidUtilities.getGroupAvatarForId(chat.id);
} else {
placeHolderId = AndroidUtilities.getBroadcastAvatarForId(chat.id);
}
}
avatarImage.setImage(photo, "50_50", placeHolderId == 0 ? null : getResources().getDrawable(placeHolderId));
......@@ -564,17 +571,17 @@ public class DialogCell extends BaseCell {
} else if (user != null) {
if (user.id / 1000 != 777 && user.id / 1000 != 333 && ContactsController.getInstance().contactsDict.get(user.id) == null) {
if (ContactsController.getInstance().contactsDict.size() == 0 && (!ContactsController.getInstance().contactsLoaded || ContactsController.getInstance().isLoadingContacts())) {
nameString = Utilities.formatName(user.first_name, user.last_name);
nameString = ContactsController.formatName(user.first_name, user.last_name);
} else {
if (user.phone != null && user.phone.length() != 0) {
nameString = PhoneFormat.getInstance().format("+" + user.phone);
} else {
currentNamePaint = nameUnknownPaint;
nameString = Utilities.formatName(user.first_name, user.last_name);
nameString = ContactsController.formatName(user.first_name, user.last_name);
}
}
} else {
nameString = Utilities.formatName(user.first_name, user.last_name);
nameString = ContactsController.formatName(user.first_name, user.last_name);
}
if (encryptedChat != null) {
currentNamePaint = nameEncryptedPaint;
......
......@@ -20,11 +20,11 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.Html;
......@@ -83,6 +83,7 @@ import org.telegram.ui.Views.LayoutListView;
import org.telegram.ui.Views.MessageActionLayout;
import org.telegram.ui.Views.SizeNotifierRelativeLayout;
import org.telegram.ui.Views.TimerButton;
import org.telegram.ui.Views.TypingDotsDrawable;
import java.io.File;
import java.util.ArrayList;
......@@ -112,6 +113,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private BackupImageView avatarImageView;
private TextView bottomOverlayChatText;
private View bottomOverlayChat;
private TypingDotsDrawable typingDotsDrawable;
private TextView bottomOverlayText;
......@@ -146,6 +148,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private boolean loading = false;
private boolean cacheEndReaced = false;
private boolean firstLoading = true;
private int loadsCount = 0;
private int minDate = 0;
private boolean first = true;
......@@ -348,6 +351,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
userBlocked = MessagesController.getInstance().blockedUsers.contains(currentUser.id);
}
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, dialog_id);
}
typingDotsDrawable = new TypingDotsDrawable();
typingDotsDrawable.setIsChat(currentChat != null);
return true;
}
......@@ -376,6 +386,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.screenshotTook);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.blockedUsersDidLoaded);
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, (long)0);
}
if (currentEncryptedChat != null) {
MediaController.getInstance().stopMediaObserver();
}
......@@ -387,6 +400,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public View createView(LayoutInflater inflater, ViewGroup container) {
if (fragmentView == null) {
actionBarLayer.setDisplayHomeAsUpEnabled(true, R.drawable.ic_ab_back);
if (AndroidUtilities.isTablet()) {
actionBarLayer.setExtraLeftMargin(4);
}
actionBarLayer.setBackOverlay(R.layout.updating_state_layout);
actionBarLayer.setActionBarMenuOnItemClick(new ActionBarLayer.ActionBarMenuOnItemClick() {
@Override
......@@ -554,7 +570,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
menuItem = item;
ActionBarMenu actionMode = actionBarLayer.createActionMode();
actionMode.addItem(-2, R.drawable.ic_ab_done_gray);
actionMode.addItem(-2, R.drawable.ic_ab_done_gray, R.drawable.bar_selector_mode);
FrameLayout layout = new FrameLayout(actionMode.getContext());
layout.setBackgroundColor(0xffe5e5e5);
......@@ -573,7 +589,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
selectedMessagesCountTextView.setSingleLine(true);
selectedMessagesCountTextView.setLines(1);
selectedMessagesCountTextView.setEllipsize(TextUtils.TruncateAt.END);
selectedMessagesCountTextView.setPadding(AndroidUtilities.dp(6), 0, 0, 0);
selectedMessagesCountTextView.setPadding(AndroidUtilities.dp(11), 0, 0, 0);
selectedMessagesCountTextView.setGravity(Gravity.CENTER_VERTICAL);
selectedMessagesCountTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
......@@ -589,12 +605,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
selectedMessagesCountTextView.setLayoutParams(layoutParams);
if (currentEncryptedChat == null) {
actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy);
actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward);
actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete);
actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy, R.drawable.bar_selector_mode);
actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode);
actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode);
} else {
actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy);
actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete);
actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy, R.drawable.bar_selector_mode);
actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode);
}
actionMode.getItem(copy).setVisibility(selectedMessagesCanCopyIds.size() != 0 ? View.VISIBLE : View.GONE);
......@@ -1023,12 +1039,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentUser.photo != null) {
photo = currentUser.photo.photo_small;
}
placeHolderId = Utilities.getUserAvatarForId(currentUser.id);
placeHolderId = AndroidUtilities.getUserAvatarForId(currentUser.id);
} else if (currentChat != null) {
if (currentChat.photo != null) {
photo = currentChat.photo.photo_small;
}
placeHolderId = Utilities.getGroupAvatarForId(currentChat.id);
if (isBraodcast) {
placeHolderId = AndroidUtilities.getBroadcastAvatarForId(currentChat.id);
} else {
placeHolderId = AndroidUtilities.getGroupAvatarForId(currentChat.id);
}
}
avatarImageView.setImage(photo, "50_50", placeHolderId);
}
......@@ -1215,10 +1235,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentUser.phone != null && currentUser.phone.length() != 0) {
actionBarLayer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone));
} else {
actionBarLayer.setTitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
}
} else {
actionBarLayer.setTitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
}
}
......@@ -1268,7 +1288,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentUser.photo != null) {
newPhoto = currentUser.photo.photo_small;
}
placeHolderId = Utilities.getUserAvatarForId(currentUser.id);
placeHolderId = AndroidUtilities.getUserAvatarForId(currentUser.id);
} else if (currentChat != null) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(currentChat.id);
if (chat == null) {
......@@ -1278,7 +1298,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentChat.photo != null) {
newPhoto = currentChat.photo.photo_small;
}
placeHolderId = Utilities.getGroupAvatarForId(currentChat.id);
if (isBraodcast) {
placeHolderId = AndroidUtilities.getBroadcastAvatarForId(currentChat.id);
} else {
placeHolderId = AndroidUtilities.getGroupAvatarForId(currentChat.id);
}
}
if (avatarImageView != null) {
avatarImageView.setImage(newPhoto, "50_50", placeHolderId);
......@@ -1331,15 +1355,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
currentPicturePath = null;
}
/*if(android.os.Build.VERSION.SDK_INT >= 18) {
if(android.os.Build.VERSION.SDK_INT >= 16) {
Bundle args = new Bundle();
args.putString("videoPath", videoPath);
VideoEditorActivity fragment = new VideoEditorActivity(args);
fragment.setDelegate(this);
presentFragment(fragment);
} else {*/
} else {
processSendingVideo(videoPath, null, 0, 0, 0, 0);
//}
}
} else if (requestCode == 21) {
if (data == null || data.getData() == null) {
showAttachmentError();
......@@ -1703,6 +1727,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (id == NotificationCenter.messagesDidLoaded) {
long did = (Long)args[0];
if (did == dialog_id) {
loadsCount++;
int count = (Integer)args[1];
boolean isCache = (Boolean)args[3];
int fnid = (Integer)args[4];
......@@ -1721,6 +1746,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int newRowsCount = 0;
unread_end_reached = last_unread_id == 0;
if (loadsCount == 1 && messArr.size() > 20) {
loadsCount++;
}
if (firstLoading) {
if (!unread_end_reached) {
messages.clear();
......@@ -2488,19 +2517,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (start) {
try {
if (currentChat != null) {
actionBarLayer.setSubTitleIcon(R.drawable.typing_dots_chat, AndroidUtilities.dp(4));
} else {
actionBarLayer.setSubTitleIcon(R.drawable.typing_dots, AndroidUtilities.dp(4));
}
AnimationDrawable mAnim = (AnimationDrawable)actionBarLayer.getSubTitleIcon();
mAnim.setAlpha(200);
mAnim.start();
actionBarLayer.setSubTitleIcon(0, typingDotsDrawable, AndroidUtilities.dp(4));
typingDotsDrawable.start();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else {
actionBarLayer.setSubTitleIcon(0, 0);
actionBarLayer.setSubTitleIcon(0, null, 0);
typingDotsDrawable.stop();
}
}
......@@ -2567,7 +2591,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return true;
}
int height = AndroidUtilities.dp(48);
if (!Utilities.isTablet(getParentActivity()) && getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
height = AndroidUtilities.dp(40);
selectedMessagesCountTextView.setTextSize(16);
} else {
......@@ -2782,7 +2806,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return;
}
if (option == 0) {
if (SendMessagesHelper.getInstance().retrySendMessage(selectedObject)) {
if (SendMessagesHelper.getInstance().retrySendMessage(selectedObject, false)) {
chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop());
}
} else if (option == 1) {
......@@ -3196,6 +3220,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
progressBar.setBackgroundResource(R.drawable.system_loader1);
}
progressBar.setVisibility(loadsCount > 1 ? View.VISIBLE : View.INVISIBLE);
}
return view;
}
......@@ -3440,33 +3465,42 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (fromUser.photo != null) {
photo = fromUser.photo.photo_small;
}
int placeHolderId = Utilities.getUserAvatarForId(fromUser.id);
int placeHolderId = AndroidUtilities.getUserAvatarForId(fromUser.id);
avatarImageView.setImage(photo, "50_50", placeHolderId);
}
if (type != 12 && type != 13 && nameTextView != null && fromUser != null && type != 8 && type != 9) {
nameTextView.setText(Utilities.formatName(fromUser.first_name, fromUser.last_name));
nameTextView.setTextColor(Utilities.getColorForId(message.messageOwner.from_id));
nameTextView.setText(ContactsController.formatName(fromUser.first_name, fromUser.last_name));
nameTextView.setTextColor(AndroidUtilities.getColorForId(message.messageOwner.from_id));
}
if (type == 11 || type == 10) {
int width = AndroidUtilities.displaySize.x - AndroidUtilities.dp(30);
int width = 0;
if (AndroidUtilities.isTablet()) {
int leftWidth = AndroidUtilities.displaySize.x / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
width = AndroidUtilities.displaySize.x - leftWidth - AndroidUtilities.dp(30);
} else {
width = AndroidUtilities.displaySize.x - AndroidUtilities.dp(30);
}
messageTextView.setText(message.messageText);
messageTextView.setMaxWidth(width);
if (type == 11) {
if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
photoImage.setImage(message.messageOwner.action.newUserPhoto.photo_small, "50_50", Utilities.getUserAvatarForId(currentUser.id));
photoImage.setImage(message.messageOwner.action.newUserPhoto.photo_small, "50_50", AndroidUtilities.getUserAvatarForId(currentUser.id));
} else {
PhotoObject photo = PhotoObject.getClosestImageWithSize(message.photoThumbs, AndroidUtilities.dp(64), AndroidUtilities.dp(64));
if (photo != null) {
if (photo.image != null) {
photoImage.setImageBitmap(photo.image);
} else {
photoImage.setImage(photo.photoOwner.location, "50_50", Utilities.getGroupAvatarForId(currentChat.id));
photoImage.setImage(photo.photoOwner.location, "50_50", AndroidUtilities.getGroupAvatarForId(currentChat.id));
}
} else {
photoImage.setImageResource(Utilities.getGroupAvatarForId(currentChat.id));
photoImage.setImageResource(AndroidUtilities.getGroupAvatarForId(currentChat.id));
}
}
photoImage.imageReceiver.setVisible(!PhotoViewer.getInstance().isShowingImage(message), false);
......@@ -3474,8 +3508,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (type == 12 || type == 13) {
TLRPC.User contactUser = MessagesController.getInstance().getUser(message.messageOwner.media.user_id);
if (contactUser != null) {
nameTextView.setText(Utilities.formatName(message.messageOwner.media.first_name, message.messageOwner.media.last_name));
nameTextView.setTextColor(Utilities.getColorForId(contactUser.id));
nameTextView.setText(ContactsController.formatName(message.messageOwner.media.first_name, message.messageOwner.media.last_name));
nameTextView.setTextColor(AndroidUtilities.getColorForId(contactUser.id));
String phone = message.messageOwner.media.phone_number;
if (phone != null && phone.length() != 0) {
if (!phone.startsWith("+")) {
......@@ -3489,7 +3523,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (contactUser.photo != null) {
photo = contactUser.photo.photo_small;
}
int placeHolderId = Utilities.getUserAvatarForId(contactUser.id);
int placeHolderId = AndroidUtilities.getUserAvatarForId(contactUser.id);
contactAvatar.setImage(photo, "50_50", placeHolderId);
if (contactUser.id != UserConfig.getClientUserId() && ContactsController.getInstance().contactsDict.get(contactUser.id) == null) {
addContactView.setVisibility(View.VISIBLE);
......@@ -3497,8 +3531,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
addContactView.setVisibility(View.GONE);
}
} else {
nameTextView.setText(Utilities.formatName(message.messageOwner.media.first_name, message.messageOwner.media.last_name));
nameTextView.setTextColor(Utilities.getColorForId(message.messageOwner.media.user_id));
nameTextView.setText(ContactsController.formatName(message.messageOwner.media.first_name, message.messageOwner.media.last_name));
nameTextView.setTextColor(AndroidUtilities.getColorForId(message.messageOwner.media.user_id));
String phone = message.messageOwner.media.phone_number;
if (phone != null && phone.length() != 0) {
if (message.messageOwner.media.user_id != 0 && !phone.startsWith("+")) {
......@@ -3508,7 +3542,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
phoneTextView.setText("Unknown");
}
contactAvatar.setImageResource(Utilities.getUserAvatarForId(message.messageOwner.media.user_id));
contactAvatar.setImageResource(AndroidUtilities.getUserAvatarForId(message.messageOwner.media.user_id));
addContactView.setVisibility(View.GONE);
}
} else if (type == 6) {
......@@ -3632,8 +3666,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
FileLog.e("tmessages", e);
}
} else if (i == 0) {
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(message.messageOwner.media.phone_number);
} else {
......
......@@ -641,7 +641,7 @@ public class ChatProfileActivity extends BaseFragment implements NotificationCen
photo = chat.photo.photo_small;
photoBig = chat.photo.photo_big;
}
avatarImage.setImage(photo, "50_50", Utilities.getGroupAvatarForId(chat.id));
avatarImage.setImage(photo, "50_50", chat_id > 0 ? AndroidUtilities.getGroupAvatarForId(chat.id) : AndroidUtilities.getBroadcastAvatarForId(chat.id));
avatarImage.imageReceiver.setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false);
return view;
} else if (type == 1) {
......
......@@ -29,7 +29,6 @@ import org.telegram.messenger.TLRPC;
import org.telegram.android.MessagesController;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ActionBar.BaseFragment;
......@@ -165,7 +164,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
if (user.photo != null) {
photo = user.photo.photo_small;
}
avatarImage.setImage(photo, "50_50", Utilities.getUserAvatarForId(user.id));
avatarImage.setImage(photo, "50_50", AndroidUtilities.getUserAvatarForId(user.id));
}
public void didReceivedNotification(int id, Object... args) {
......
......@@ -349,7 +349,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, Utilities.formatName(user.first_name, user.last_name)));
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, ContactsController.formatName(user.first_name, user.last_name)));
final EditText editText = new EditText(getParentActivity());
if (android.os.Build.VERSION.SDK_INT < 11) {
editText.setBackgroundResource(android.R.drawable.editbox_background_normal);
......
......@@ -332,7 +332,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
LayoutInflater lf = (LayoutInflater)ApplicationLoader.applicationContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View textView = lf.inflate(R.layout.group_create_bubble, null);
TextView text = (TextView)textView.findViewById(R.id.bubble_text_view);
String name = Utilities.formatName(user.first_name, user.last_name);
String name = ContactsController.formatName(user.first_name, user.last_name);
if (name.length() == 0 && user.phone != null && user.phone.length() != 0) {
name = PhoneFormat.getInstance().format("+" + user.phone);
}
......@@ -539,7 +539,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
if (searchWas && searching) {
holder.nameTextView.setText(searchResultNames.get(position));
} else {
String name = Utilities.formatName(user.first_name, user.last_name);
String name = ContactsController.formatName(user.first_name, user.last_name);
if (name.length() == 0) {
if (user.phone != null && user.phone.length() != 0) {
name = PhoneFormat.getInstance().format("+" + user.phone);
......@@ -554,7 +554,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
if (user.photo != null) {
photo = user.photo.photo_small;
}
int placeHolderId = Utilities.getUserAvatarForId(user.id);
int placeHolderId = AndroidUtilities.getUserAvatarForId(user.id);
holder.avatarImage.setImage(photo, "50_50", placeHolderId);
holder.messageTextView.setText(LocaleController.formatUserStatus(user));
......
......@@ -10,6 +10,7 @@ package org.telegram.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.os.Parcelable;
......@@ -24,6 +25,7 @@ import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
......@@ -46,7 +48,12 @@ public class IntroActivity extends Activity {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
if (AndroidUtilities.isTablet()) {
setContentView(R.layout.intro_layout_tablet);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.intro_layout);
}
if (LocaleController.isRTL) {
icons = new int[] {
......
......@@ -125,7 +125,7 @@ public class LanguageSelectActivity extends BaseFragment {
}
if (localeInfo != null) {
LocaleController.getInstance().applyLanguage(localeInfo, true);
getParentActivity().rebuildAllFragmentViews();
parentLayout.rebuildAllFragmentViews(false);
}
finishFragment();
}
......
......@@ -8,15 +8,25 @@
package org.telegram.ui;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.ContactsContract;
import android.view.ActionMode;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
......@@ -31,7 +41,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.ActionBar.ActionBarActivity;
import org.telegram.ui.Views.ActionBar.ActionBarLayout;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import java.io.BufferedReader;
......@@ -40,7 +50,7 @@ import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Map;
public class LaunchActivity extends ActionBarActivity implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
private boolean finished = false;
private String videoPath = null;
private String sendingText = null;
......@@ -49,6 +59,16 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
private ArrayList<String> documentsOriginalPathsArray = null;
private ArrayList<TLRPC.User> contactsToSend = null;
private int currentConnectionState;
private static ArrayList<BaseFragment> mainFragmentsStack = new ArrayList<BaseFragment>();
private static ArrayList<BaseFragment> layerFragmentsStack = new ArrayList<BaseFragment>();
private static ArrayList<BaseFragment> rightFragmentsStack = new ArrayList<BaseFragment>();
private ActionBarLayout actionBarLayout = null;
private ActionBarLayout layersActionBarLayout = null;
private ActionBarLayout rightActionBarLayout = null;
private FrameLayout shadowTablet = null;
private LinearLayout buttonLayoutTablet = null;
private FrameLayout shadowTabletSide = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -57,7 +77,7 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
if (!UserConfig.isClientActivated()) {
Intent intent = getIntent();
if (intent != null && intent.getAction() != null && (Intent.ACTION_SEND.equals(intent.getAction()) || intent.getAction().equals(Intent.ACTION_SEND_MULTIPLE))) {
super.onCreateFinish(savedInstanceState);
super.onCreate(savedInstanceState);
finish();
return;
}
......@@ -67,15 +87,123 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
if (state.isEmpty()) {
Intent intent2 = new Intent(this, IntroActivity.class);
startActivity(intent2);
super.onCreateFinish(savedInstanceState);
super.onCreate(savedInstanceState);
finish();
return;
}
}
}
requestWindowFeature(Window.FEATURE_NO_TITLE);
setTheme(R.style.Theme_TMessages);
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
super.onCreate(savedInstanceState);
actionBarLayout = new ActionBarLayout(this);
if (AndroidUtilities.isTablet()) {
setContentView(R.layout.launch_layout_tablet);
shadowTablet = (FrameLayout)findViewById(R.id.shadow_tablet);
buttonLayoutTablet = (LinearLayout)findViewById(R.id.launch_button_layout);
shadowTabletSide = (FrameLayout)findViewById(R.id.shadow_tablet_side);
shadowTablet.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
RelativeLayout launchLayout = (RelativeLayout)findViewById(R.id.launch_layout);
layersActionBarLayout = new ActionBarLayout(this);
layersActionBarLayout.setBackgroundView(shadowTablet);
layersActionBarLayout.setUseAlphaAnimations(true);
layersActionBarLayout.setBackgroundResource(R.drawable.boxshadow);
launchLayout.addView(layersActionBarLayout);
RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams)layersActionBarLayout.getLayoutParams();
relativeLayoutParams.width = AndroidUtilities.dp(498);
relativeLayoutParams.height = AndroidUtilities.dp(528);
relativeLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
layersActionBarLayout.setLayoutParams(relativeLayoutParams);
layersActionBarLayout.init(layerFragmentsStack);
layersActionBarLayout.setDelegate(this);
layersActionBarLayout.setVisibility(View.GONE);
launchLayout.addView(actionBarLayout, 2);
relativeLayoutParams = (RelativeLayout.LayoutParams)actionBarLayout.getLayoutParams();
relativeLayoutParams.width = AndroidUtilities.dp(320);
relativeLayoutParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;
actionBarLayout.setLayoutParams(relativeLayoutParams);
rightActionBarLayout = new ActionBarLayout(this);
launchLayout.addView(rightActionBarLayout, 3);
relativeLayoutParams = (RelativeLayout.LayoutParams)rightActionBarLayout.getLayoutParams();
relativeLayoutParams.width = AndroidUtilities.dp(320);
relativeLayoutParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;
rightActionBarLayout.setLayoutParams(relativeLayoutParams);
rightActionBarLayout.init(rightFragmentsStack);
rightActionBarLayout.setDelegate(this);
rightActionBarLayout.setVisibility(rightFragmentsStack.isEmpty() ? View.GONE : View.VISIBLE);
buttonLayoutTablet.setVisibility(rightFragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
TextView button = (TextView)findViewById(R.id.new_group_button);
button.setText(LocaleController.getString("NewGroup", R.string.NewGroup));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presentFragment(new GroupCreateActivity());
}
});
button = (TextView)findViewById(R.id.new_secret_button);
button.setText(LocaleController.getString("NewSecretChat", R.string.NewSecretChat));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle args = new Bundle();
args.putBoolean("onlyUsers", true);
args.putBoolean("destroyAfterSelect", true);
args.putBoolean("usersAsSections", true);
args.putBoolean("createSecretChat", true);
presentFragment(new ContactsActivity(args));
}
});
button = (TextView)findViewById(R.id.new_broadcast_button);
button.setText(LocaleController.getString("NewBroadcastList", R.string.NewBroadcastList));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle args = new Bundle();
args.putBoolean("broadcast", true);
presentFragment(new GroupCreateActivity(args));
}
});
button = (TextView)findViewById(R.id.contacts_button);
button.setText(LocaleController.getString("Contacts", R.string.Contacts));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presentFragment(new ContactsActivity(null));
}
});
button = (TextView)findViewById(R.id.settings_button);
button.setText(LocaleController.getString("Settings", R.string.Settings));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presentFragment(new SettingsActivity());
}
});
} else {
setContentView(actionBarLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
actionBarLayout.init(mainFragmentsStack);
actionBarLayout.setDelegate(this);
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
AndroidUtilities.statusBarHeight = getResources().getDimensionPixelSize(resourceId);
......@@ -88,11 +216,11 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeOtherAppActivities);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.didUpdatedConnectionState);
if (fragmentsStack.isEmpty()) {
if (actionBarLayout.fragmentsStack.isEmpty()) {
if (!UserConfig.isClientActivated()) {
addFragmentToStack(new LoginActivity());
actionBarLayout.addFragmentToStack(new LoginActivity());
} else {
addFragmentToStack(new MessagesActivity(null));
actionBarLayout.addFragmentToStack(new MessagesActivity(null));
}
try {
......@@ -103,31 +231,31 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
if (fragmentName.equals("chat")) {
if (args != null) {
ChatActivity chat = new ChatActivity(args);
if (addFragmentToStack(chat)) {
if (actionBarLayout.addFragmentToStack(chat)) {
chat.restoreSelfArgs(savedInstanceState);
}
}
} else if (fragmentName.equals("settings")) {
SettingsActivity settings = new SettingsActivity();
addFragmentToStack(settings);
actionBarLayout.addFragmentToStack(settings);
settings.restoreSelfArgs(savedInstanceState);
} else if (fragmentName.equals("group")) {
if (args != null) {
GroupCreateFinalActivity group = new GroupCreateFinalActivity(args);
if (addFragmentToStack(group)) {
if (actionBarLayout.addFragmentToStack(group)) {
group.restoreSelfArgs(savedInstanceState);
}
}
} else if (fragmentName.equals("chat_profile")) {
if (args != null) {
ChatProfileActivity profile = new ChatProfileActivity(args);
if (addFragmentToStack(profile)) {
if (actionBarLayout.addFragmentToStack(profile)) {
profile.restoreSelfArgs(savedInstanceState);
}
}
} else if (fragmentName.equals("wallpapers")) {
SettingsWallpapersActivity settings = new SettingsWallpapersActivity();
addFragmentToStack(settings);
actionBarLayout.addFragmentToStack(settings);
settings.restoreSelfArgs(savedInstanceState);
}
}
......@@ -138,6 +266,7 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
}
handleIntent(getIntent(), false, savedInstanceState != null);
needLayout();
}
private void handleIntent(Intent intent, boolean isNew, boolean restore) {
......@@ -382,7 +511,7 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
Bundle args = new Bundle();
args.putInt("user_id", push_user_id);
ChatActivity fragment = new ChatActivity(args);
if (presentFragment(fragment, false, true)) {
if (actionBarLayout.presentFragment(fragment, false, true)) {
pushOpened = true;
}
}
......@@ -390,19 +519,19 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
Bundle args = new Bundle();
args.putInt("chat_id", push_chat_id);
ChatActivity fragment = new ChatActivity(args);
if (presentFragment(fragment, false, true)) {
if (actionBarLayout.presentFragment(fragment, false, true)) {
pushOpened = true;
}
} else if (push_enc_id != 0) {
Bundle args = new Bundle();
args.putInt("enc_id", push_enc_id);
ChatActivity fragment = new ChatActivity(args);
if (presentFragment(fragment, false, true)) {
if (actionBarLayout.presentFragment(fragment, false, true)) {
pushOpened = true;
}
} else if (showDialogsList) {
for (int a = 1; a < fragmentsStack.size(); a++) {
removeFragmentFromStack(fragmentsStack.get(a));
for (int a = 1; a < actionBarLayout.fragmentsStack.size(); a++) {
actionBarLayout.removeFragmentFromStack(actionBarLayout.fragmentsStack.get(a));
a--;
}
pushOpened = false;
......@@ -415,25 +544,29 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo));
MessagesActivity fragment = new MessagesActivity(args);
fragment.setDelegate(this);
presentFragment(fragment, false, true);
actionBarLayout.presentFragment(fragment, false, true);
pushOpened = true;
if (PhotoViewer.getInstance().isVisible()) {
PhotoViewer.getInstance().closePhoto(true);
}
}
if (open_settings != 0) {
presentFragment(new SettingsActivity(), false, true);
actionBarLayout.presentFragment(new SettingsActivity(), false, true);
pushOpened = true;
}
if (!pushOpened && !isNew) {
if (fragmentsStack.isEmpty()) {
if (actionBarLayout.fragmentsStack.isEmpty()) {
if (!UserConfig.isClientActivated()) {
addFragmentToStack(new LoginActivity());
actionBarLayout.addFragmentToStack(new LoginActivity());
} else {
addFragmentToStack(new MessagesActivity(null));
actionBarLayout.addFragmentToStack(new MessagesActivity(null));
}
}
actionBarLayout.showLastFragment();
if (AndroidUtilities.isTablet()) {
layersActionBarLayout.showLastFragment();
rightActionBarLayout.showLastFragment();
}
showLastFragment();
}
intent.setAction(null);
......@@ -468,7 +601,7 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
args.putInt("enc_id", high_id);
}
ChatActivity fragment = new ChatActivity(args);
presentFragment(fragment, true);
actionBarLayout.presentFragment(fragment, true);
if (videoPath != null) {
fragment.processSendingVideo(videoPath, null, 0, 0, 0, 0);
}
......@@ -496,18 +629,98 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
}
}
private void onFinish() {
if (finished) {
return;
}
finished = true;
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appDidLogout);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeOtherAppActivities);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didUpdatedConnectionState);
}
public void presentFragment(BaseFragment fragment) {
actionBarLayout.presentFragment(fragment);
}
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation) {
return actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
}
public void needLayout() {
if (AndroidUtilities.isTablet()) {
int leftWidth = AndroidUtilities.displaySize.x / 100 * 35;
if (leftWidth < AndroidUtilities.dp(320)) {
leftWidth = AndroidUtilities.dp(320);
}
RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) actionBarLayout.getLayoutParams();
relativeLayoutParams.width = leftWidth;
relativeLayoutParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;
actionBarLayout.setLayoutParams(relativeLayoutParams);
relativeLayoutParams = (RelativeLayout.LayoutParams) shadowTabletSide.getLayoutParams();
relativeLayoutParams.leftMargin = leftWidth;
shadowTabletSide.setLayoutParams(relativeLayoutParams);
relativeLayoutParams = (RelativeLayout.LayoutParams) rightActionBarLayout.getLayoutParams();
relativeLayoutParams.width = AndroidUtilities.displaySize.x - leftWidth;
relativeLayoutParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;
relativeLayoutParams.leftMargin = leftWidth;
rightActionBarLayout.setLayoutParams(relativeLayoutParams);
relativeLayoutParams = (RelativeLayout.LayoutParams) buttonLayoutTablet.getLayoutParams();
relativeLayoutParams.width = AndroidUtilities.displaySize.x - leftWidth;
relativeLayoutParams.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
relativeLayoutParams.leftMargin = leftWidth;
buttonLayoutTablet.setLayoutParams(relativeLayoutParams);
}
}
public void fixLayout() {
if (AndroidUtilities.isTablet()) {
final ViewTreeObserver obs = actionBarLayout.getViewTreeObserver();
obs.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
needLayout();
if (Build.VERSION.SDK_INT < 16) {
obs.removeGlobalOnLayoutListener(this);
} else {
obs.removeOnGlobalLayoutListener(this);
}
}
});
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (fragmentsStack.size() != 0) {
BaseFragment fragment = fragmentsStack.get(fragmentsStack.size() - 1);
if (actionBarLayout.fragmentsStack.size() != 0) {
BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
fragment.onActivityResultFragment(requestCode, resultCode, data);
}
if (AndroidUtilities.isTablet()) {
if (rightActionBarLayout.fragmentsStack.size() != 0) {
BaseFragment fragment = rightActionBarLayout.fragmentsStack.get(rightActionBarLayout.fragmentsStack.size() - 1);
fragment.onActivityResultFragment(requestCode, resultCode, data);
}
if (layersActionBarLayout.fragmentsStack.size() != 0) {
BaseFragment fragment = layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1);
fragment.onActivityResultFragment(requestCode, resultCode, data);
}
}
}
@Override
protected void onPause() {
super.onPause();
actionBarLayout.onPause();
if (AndroidUtilities.isTablet()) {
rightActionBarLayout.onPause();
layersActionBarLayout.onPause();
}
ApplicationLoader.mainInterfacePaused = true;
ConnectionsManager.getInstance().setAppPaused(true, false);
}
......@@ -522,38 +735,43 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
@Override
protected void onResume() {
super.onResume();
actionBarLayout.onResume();
if (AndroidUtilities.isTablet()) {
rightActionBarLayout.onResume();
layersActionBarLayout.onResume();
}
Utilities.checkForCrashes(this);
Utilities.checkForUpdates(this);
ApplicationLoader.mainInterfacePaused = false;
ConnectionsManager.getInstance().setAppPaused(false, false);
actionBar.setBackOverlayVisible(currentConnectionState != 0);
}
@Override
protected void onFinish() {
if (finished) {
return;
}
finished = true;
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appDidLogout);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeOtherAppActivities);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didUpdatedConnectionState);
actionBarLayout.getActionBar().setBackOverlayVisible(currentConnectionState != 0);
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
AndroidUtilities.checkDisplaySize();
super.onConfigurationChanged(newConfig);
fixLayout();
}
@Override
@SuppressWarnings("unchecked")
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.appDidLogout) {
for (BaseFragment fragment : fragmentsStack) {
for (BaseFragment fragment : actionBarLayout.fragmentsStack) {
fragment.onFragmentDestroy();
}
actionBarLayout.fragmentsStack.clear();
if (AndroidUtilities.isTablet()) {
for (BaseFragment fragment : layersActionBarLayout.fragmentsStack) {
fragment.onFragmentDestroy();
}
layersActionBarLayout.fragmentsStack.clear();
for (BaseFragment fragment : rightActionBarLayout.fragmentsStack) {
fragment.onFragmentDestroy();
}
fragmentsStack.clear();
rightActionBarLayout.fragmentsStack.clear();
}
Intent intent2 = new Intent(this, IntroActivity.class);
startActivity(intent2);
onFinish();
......@@ -567,35 +785,17 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
if (currentConnectionState != state) {
FileLog.e("tmessages", "switch to state " + state);
currentConnectionState = state;
actionBar.setBackOverlayVisible(currentConnectionState != 0);
}
actionBarLayout.getActionBar().setBackOverlayVisible(currentConnectionState != 0);
}
}
@Override
public void onOverlayShow(View view, BaseFragment fragment) {
if (view == null || fragment == null || fragmentsStack.isEmpty()) {
return;
}
View backStatusButton = view.findViewById(R.id.back_button);
TextView statusText = (TextView)view.findViewById(R.id.status_text);
backStatusButton.setVisibility(fragmentsStack.get(0) == fragment ? View.GONE : View.VISIBLE);
view.setEnabled(fragmentsStack.get(0) != fragment);
if (currentConnectionState == 1) {
statusText.setText(LocaleController.getString("WaitingForNetwork", R.string.WaitingForNetwork));
} else if (currentConnectionState == 2) {
statusText.setText(LocaleController.getString("Connecting", R.string.Connecting));
} else if (currentConnectionState == 3) {
statusText.setText(LocaleController.getString("Updating", R.string.Updating));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
try {
super.onSaveInstanceState(outState);
if (!fragmentsStack.isEmpty()) {
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
if (!actionBarLayout.fragmentsStack.isEmpty()) {
BaseFragment lastFragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
Bundle args = lastFragment.getArguments();
if (lastFragment instanceof ChatActivity && args != null) {
outState.putBundle("args", args);
......@@ -623,7 +823,52 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
if (PhotoViewer.getInstance().isVisible()) {
PhotoViewer.getInstance().closePhoto(true);
} else {
super.onBackPressed();
if (AndroidUtilities.isTablet()) {
if (layersActionBarLayout.getVisibility() == View.VISIBLE) {
layersActionBarLayout.onBackPressed();
} else {
boolean cancel = false;
if (rightActionBarLayout.getVisibility() == View.VISIBLE && !rightActionBarLayout.fragmentsStack.isEmpty()) {
BaseFragment lastFragment = rightActionBarLayout.fragmentsStack.get(rightActionBarLayout.fragmentsStack.size() - 1);
cancel = !lastFragment.onBackPressed();
}
if (!cancel) {
actionBarLayout.onBackPressed();
}
}
} else {
actionBarLayout.onBackPressed();
}
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
actionBarLayout.onLowMemory();
if (AndroidUtilities.isTablet()) {
rightActionBarLayout.onLowMemory();
layersActionBarLayout.onLowMemory();
}
}
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
actionBarLayout.onActionModeStarted(mode);
if (AndroidUtilities.isTablet()) {
rightActionBarLayout.onActionModeStarted(mode);
layersActionBarLayout.onActionModeStarted(mode);
}
}
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
actionBarLayout.onActionModeFinished(mode);
if (AndroidUtilities.isTablet()) {
rightActionBarLayout.onActionModeFinished(mode);
layersActionBarLayout.onActionModeFinished(mode);
}
}
......@@ -633,11 +878,150 @@ public class LaunchActivity extends ActionBarActivity implements NotificationCen
PhotoViewer.getInstance().closePhoto(true);
return true;
}
return super.onPreIme();
return false;
}
@Override
public void onLowMemory() {
super.onLowMemory();
public void onOverlayShow(View view, BaseFragment fragment) {
if (view == null || fragment == null || actionBarLayout.fragmentsStack.isEmpty()) {
return;
}
View backStatusButton = view.findViewById(R.id.back_button);
TextView statusText = (TextView)view.findViewById(R.id.status_text);
backStatusButton.setVisibility(actionBarLayout.fragmentsStack.get(0) == fragment ? View.GONE : View.VISIBLE);
view.setEnabled(actionBarLayout.fragmentsStack.get(0) != fragment);
if (currentConnectionState == 1) {
statusText.setText(LocaleController.getString("WaitingForNetwork", R.string.WaitingForNetwork));
} else if (currentConnectionState == 2) {
statusText.setText(LocaleController.getString("Connecting", R.string.Connecting));
} else if (currentConnectionState == 3) {
statusText.setText(LocaleController.getString("Updating", R.string.Updating));
}
}
@Override
public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
if (fragment instanceof MessagesActivity) {
MessagesActivity messagesActivity = (MessagesActivity)fragment;
if (messagesActivity.getDelegate() == null && layout != actionBarLayout) {
actionBarLayout.removeAllFragments();
actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
layersActionBarLayout.removeAllFragments();
layersActionBarLayout.setVisibility(View.GONE);
if (rightFragmentsStack.isEmpty()) {
buttonLayoutTablet.setVisibility(View.VISIBLE);
}
return false;
}
} else if (fragment instanceof ChatActivity) {
if (layout != rightActionBarLayout) {
rightActionBarLayout.setVisibility(View.VISIBLE);
buttonLayoutTablet.setVisibility(View.GONE);
rightActionBarLayout.removeAllFragments();
rightActionBarLayout.presentFragment(fragment, removeLast, true);
if (removeLast) {
layout.closeLastFragment(true);
}
return false;
}
} else if (layout != layersActionBarLayout) {
layersActionBarLayout.setVisibility(View.VISIBLE);
if (fragment instanceof LoginActivity) {
buttonLayoutTablet.setVisibility(View.GONE);
shadowTablet.setBackgroundColor(0x00000000);
} else {
shadowTablet.setBackgroundColor(0x7F000000);
}
layersActionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
return false;
}
return true;
} else {
return true;
}
}
@Override
public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
if (fragment instanceof MessagesActivity) {
MessagesActivity messagesActivity = (MessagesActivity)fragment;
if (messagesActivity.getDelegate() == null && layout != actionBarLayout) {
actionBarLayout.removeAllFragments();
actionBarLayout.addFragmentToStack(fragment);
layersActionBarLayout.removeAllFragments();
layersActionBarLayout.setVisibility(View.GONE);
if (rightFragmentsStack.isEmpty()) {
buttonLayoutTablet.setVisibility(View.VISIBLE);
}
return false;
}
} else if (fragment instanceof ChatActivity) {
if (layout != rightActionBarLayout) {
rightActionBarLayout.setVisibility(View.VISIBLE);
buttonLayoutTablet.setVisibility(View.GONE);
rightActionBarLayout.removeAllFragments();
rightActionBarLayout.addFragmentToStack(fragment);
return false;
}
} else if (layout != layersActionBarLayout) {
layersActionBarLayout.setVisibility(View.VISIBLE);
if (fragment instanceof LoginActivity) {
buttonLayoutTablet.setVisibility(View.GONE);
shadowTablet.setBackgroundColor(0x00000000);
} else {
shadowTablet.setBackgroundColor(0x7F000000);
}
layersActionBarLayout.addFragmentToStack(fragment);
return false;
}
return true;
} else {
return true;
}
}
@Override
public boolean needCloseLastFragment(ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
if (layout == actionBarLayout && layout.fragmentsStack.size() <= 1) {
onFinish();
finish();
return false;
} else if (layout == rightActionBarLayout) {
buttonLayoutTablet.setVisibility(View.VISIBLE);
}
} else {
if (layout.fragmentsStack.size() <= 1) {
onFinish();
finish();
return false;
}
}
return true;
}
@Override
public void onRebuildAllFragments(ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
if (layout == layersActionBarLayout) {
rightActionBarLayout.rebuildAllFragmentViews(true);
rightActionBarLayout.showLastFragment();
actionBarLayout.rebuildAllFragmentViews(true);
actionBarLayout.showLastFragment();
TextView button = (TextView)findViewById(R.id.new_group_button);
button.setText(LocaleController.getString("NewGroup", R.string.NewGroup));
button = (TextView)findViewById(R.id.new_secret_button);
button.setText(LocaleController.getString("NewSecretChat", R.string.NewSecretChat));
button = (TextView)findViewById(R.id.new_broadcast_button);
button.setText(LocaleController.getString("NewBroadcastList", R.string.NewBroadcastList));
button = (TextView)findViewById(R.id.contacts_button);
button.setText(LocaleController.getString("Contacts", R.string.Contacts));
button = (TextView)findViewById(R.id.settings_button);
button.setText(LocaleController.getString("Settings", R.string.Settings));
}
}
}
}
......@@ -27,6 +27,8 @@ 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.android.AndroidUtilities;
import org.telegram.android.ContactsController;
import org.telegram.messenger.FileLog;
import org.telegram.android.LocaleController;
import org.telegram.messenger.TLRPC;
......@@ -34,7 +36,6 @@ import org.telegram.android.MessageObject;
import org.telegram.android.MessagesController;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
......@@ -235,8 +236,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
if (user.photo != null) {
photo = user.photo.photo_small;
}
avatarImageView.setImage(photo, "50_50", Utilities.getUserAvatarForId(user.id));
nameTextView.setText(Utilities.formatName(user.first_name, user.last_name));
avatarImageView.setImage(photo, "50_50", AndroidUtilities.getUserAvatarForId(user.id));
nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name));
}
userLocation = new Location("network");
userLocation.setLatitude(messageObject.messageOwner.media.geo.lat);
......@@ -284,8 +285,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
if (user.photo != null) {
photo = user.photo.photo_small;
}
avatarImageView.setImage(photo, null, Utilities.getUserAvatarForId(user.id));
nameTextView.setText(Utilities.formatName(user.first_name, user.last_name));
avatarImageView.setImage(photo, null, AndroidUtilities.getUserAvatarForId(user.id));
nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name));
}
}
}
......
......@@ -326,15 +326,21 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE);
int rotation = manager.getDefaultDisplay().getRotation();
if (AndroidUtilities.isTablet()) {
listView.setNumColumns(4);
itemWidth = AndroidUtilities.dp(490) / 4 - AndroidUtilities.dp(2) * 3;
listView.setColumnWidth(itemWidth);
} else {
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
listView.setNumColumns(6);
itemWidth = getParentActivity().getResources().getDisplayMetrics().widthPixels / 6 - AndroidUtilities.dp(2) * 5;
itemWidth = AndroidUtilities.displaySize.x / 6 - AndroidUtilities.dp(2) * 5;
listView.setColumnWidth(itemWidth);
} else {
listView.setNumColumns(4);
itemWidth = getParentActivity().getResources().getDisplayMetrics().widthPixels / 4 - AndroidUtilities.dp(2) * 3;
itemWidth = AndroidUtilities.displaySize.x / 4 - AndroidUtilities.dp(2) * 3;
listView.setColumnWidth(itemWidth);
}
}
listView.setPadding(listView.getPaddingLeft(), AndroidUtilities.dp(4), listView.getPaddingRight(), listView.getPaddingBottom());
listAdapter.notifyDataSetChanged();
......
......@@ -68,6 +68,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
private MessagesActivityDelegate delegate;
private long openedDialogId = 0;
private final static int messages_list_menu_new_messages = 1;
private final static int messages_list_menu_new_chat = 2;
private final static int messages_list_menu_other = 6;
......@@ -94,6 +96,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.contactsDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.appDidLogout);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.openedChatChanged);
if (getArguments() != null) {
onlySelect = arguments.getBoolean("onlySelect", false);
serverOnly = arguments.getBoolean("serverOnly", false);
......@@ -116,6 +119,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatUpdated);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.contactsDidLoaded);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appDidLogout);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.openedChatChanged);
delegate = null;
}
......@@ -224,6 +228,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view);
messagesListView.setAdapter(messagesListViewAdapter);
if (delegate == null && AndroidUtilities.isTablet()) {
messagesListView.setDivider(inflater.getContext().getResources().getDrawable(R.drawable.messages_list_divider2));
messagesListView.setDividerHeight(1);
}
progressView = fragmentView.findViewById(R.id.progressLayout);
messagesListViewAdapter.notifyDataSetChanged();
......@@ -305,7 +313,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
} else {
args.putInt("enc_id", high_id);
}
if (AndroidUtilities.isTablet()) {
if (openedDialogId == dialog_id) {
return;
}
openedDialogId = dialog_id;
}
presentFragment(new ChatActivity(args));
updateVisibleRows(0);
}
}
});
......@@ -469,6 +484,11 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
updateVisibleRows(0);
} else if (id == NotificationCenter.contactsDidLoaded) {
updateVisibleRows(0);
} else if (id == NotificationCenter.openedChatChanged) {
if (!serverOnly && AndroidUtilities.isTablet()) {
openedDialogId = (Long)args[0];
updateVisibleRows(0);
}
}
}
......@@ -480,7 +500,15 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
for (int a = 0; a < count; a++) {
View child = messagesListView.getChildAt(a);
if (child instanceof DialogCell) {
((DialogCell) child).update(mask);
DialogCell cell = (DialogCell) child;
if (!serverOnly && AndroidUtilities.isTablet() && cell.getDialog() != null) {
if (cell.getDialog().id == openedDialogId) {
child.setBackgroundColor(0x0f000000);
} else {
child.setBackgroundColor(0);
}
}
cell.update(mask);
} else if (child instanceof ChatOrUserCell) {
((ChatOrUserCell) child).update(mask);
}
......@@ -491,6 +519,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
this.delegate = delegate;
}
public MessagesActivityDelegate getDelegate() {
return delegate;
}
private void didSelectResult(final long dialog_id, boolean useAlert, final boolean param) {
if (useAlert && selectAlertString != null) {
if (getParentActivity() == null) {
......@@ -513,7 +545,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
if (user == null) {
return;
}
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, Utilities.formatName(user.first_name, user.last_name)));
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, ContactsController.formatName(user.first_name, user.last_name)));
} else if (lower_part < 0) {
TLRPC.Chat chat = MessagesController.getInstance().getChat(-lower_part);
if (chat == null) {
......@@ -528,7 +560,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
if (user == null) {
return;
}
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, Utilities.formatName(user.first_name, user.last_name)));
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, ContactsController.formatName(user.first_name, user.last_name)));
}
CheckBox checkBox = null;
/*if (delegate instanceof ChatActivity) {
......@@ -713,7 +745,15 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
if (serverOnly) {
((DialogCell)view).setDialog(MessagesController.getInstance().dialogsServerOnly.get(i));
} else {
((DialogCell)view).setDialog(MessagesController.getInstance().dialogs.get(i));
TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs.get(i);
if (AndroidUtilities.isTablet()) {
if (dialog.id == openedDialogId) {
view.setBackgroundColor(0x0f000000);
} else {
view.setBackgroundColor(0);
}
}
((DialogCell)view).setDialog(dialog);
}
return view;
......
......@@ -12,17 +12,14 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
......@@ -302,14 +299,12 @@ public class PhotoCropActivity extends BaseFragment {
return false;
}
}
Point displaySize = new Point();
Display display = ((WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(android.os.Build.VERSION.SDK_INT < 13) {
displaySize.set(display.getWidth(), display.getHeight());
int size = 0;
if (AndroidUtilities.isTablet()) {
size = AndroidUtilities.dp(520);
} else {
display.getSize(displaySize);
size = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y);
}
int size = Math.max(displaySize.x, displaySize.y);
imageToCrop = ImageLoader.loadBitmap(photoPath, photoUri, size, size);
if (imageToCrop == null) {
return false;
......
......@@ -394,18 +394,26 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
int columnsCount = 2;
if (selectedAlbum != null) {
if (AndroidUtilities.isTablet()) {
columnsCount = 3;
} else {
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
columnsCount = 5;
} else {
columnsCount = 3;
}
}
} else {
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
columnsCount = 4;
}
}
listView.setNumColumns(columnsCount);
itemWidth = (getParentActivity().getResources().getDisplayMetrics().widthPixels - ((columnsCount + 1) * AndroidUtilities.dp(4))) / columnsCount;
if (AndroidUtilities.isTablet()) {
itemWidth = (AndroidUtilities.dp(490) - ((columnsCount + 1) * AndroidUtilities.dp(4))) / columnsCount;
} else {
itemWidth = (AndroidUtilities.displaySize.x - ((columnsCount + 1) * AndroidUtilities.dp(4))) / columnsCount;
}
listView.setColumnWidth(itemWidth);
listAdapter.notifyDataSetChanged();
......
......@@ -47,6 +47,7 @@ import android.widget.Scroller;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController;
import org.telegram.android.MessagesStorage;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLoader;
......@@ -62,7 +63,6 @@ import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.PhotoObject;
import org.telegram.ui.Views.ActionBar.ActionBar;
import org.telegram.ui.Views.ActionBar.ActionBarActivity;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.ActionBarMenuItem;
......@@ -521,7 +521,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
closePhoto(false);
Bundle args2 = new Bundle();
args2.putLong("dialog_id", currentDialogId);
((ActionBarActivity)parentActivity).presentFragment(new MediaActivity(args2), false, true);
((LaunchActivity)parentActivity).presentFragment(new MediaActivity(args2), false, true);
}
} else if (id == gallery_menu_send) {
/*Intent intent = new Intent(this, MessagesActivity.class);
......@@ -1219,7 +1219,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
currentMessageObject = imagesArr.get(currentIndex);
TLRPC.User user = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id);
if (user != null) {
nameTextView.setText(Utilities.formatName(user.first_name, user.last_name));
nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name));
} else {
nameTextView.setText("");
}
......
......@@ -13,7 +13,6 @@ import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.AttributeSet;
......@@ -43,7 +42,6 @@ import org.telegram.messenger.FileLog;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.PhotoObject;
import org.telegram.ui.Views.ActionBar.ActionBar;
......@@ -53,6 +51,7 @@ import org.telegram.ui.Views.BackupImageView;
import org.telegram.ui.Views.ChatActivityEnterView;
import org.telegram.ui.Views.FrameLayoutFixed;
import org.telegram.ui.Views.PopupAudioView;
import org.telegram.ui.Views.TypingDotsDrawable;
import java.io.File;
import java.util.ArrayList;
......@@ -71,6 +70,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
private ArrayList<ViewGroup> imageViews = new ArrayList<ViewGroup>();
private ArrayList<ViewGroup> audioViews = new ArrayList<ViewGroup>();
private VelocityTracker velocityTracker = null;
private TypingDotsDrawable typingDotsDrawable;
private int classGuid;
private TLRPC.User currentUser;
......@@ -151,6 +151,8 @@ public class PopupNotificationActivity extends Activity implements NotificationC
NotificationCenter.getInstance().addObserver(this, NotificationCenter.contactsDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.emojiDidLoaded);
typingDotsDrawable = new TypingDotsDrawable();
chatActivityEnterView = new ChatActivityEnterView();
chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() {
@Override
......@@ -624,7 +626,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
messageContainer.getViewTreeObserver().removeOnPreDrawListener(this);
if (!checkTransitionAnimation() && !startedMoving) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)messageContainer.getLayoutParams();
if (!Utilities.isTablet(PopupNotificationActivity.this) && PopupNotificationActivity.this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && PopupNotificationActivity.this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
layoutParams.topMargin = AndroidUtilities.dp(40);
} else {
layoutParams.topMargin = AndroidUtilities.dp(48);
......@@ -739,10 +741,10 @@ public class PopupNotificationActivity extends Activity implements NotificationC
if (currentChat != null && currentUser != null) {
actionBarLayer.setTitle(currentChat.title);
actionBarLayer.setSubtitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setSubtitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitleIcon(0, 0);
} else if (currentUser != null) {
actionBarLayer.setTitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
if ((int)dialog_id == 0) {
actionBarLayer.setTitleIcon(R.drawable.ic_lock_white, AndroidUtilities.dp(4));
} else {
......@@ -767,10 +769,10 @@ public class PopupNotificationActivity extends Activity implements NotificationC
if (currentUser.phone != null && currentUser.phone.length() != 0) {
actionBarLayer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone));
} else {
actionBarLayer.setTitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
}
} else {
actionBarLayer.setTitle(Utilities.formatName(currentUser.first_name, currentUser.last_name));
actionBarLayer.setTitle(ContactsController.formatName(currentUser.first_name, currentUser.last_name));
}
CharSequence printString = MessagesController.getInstance().printingStrings.get(currentMessageObject.getDialogId());
if (printString == null || printString.length() == 0) {
......@@ -800,7 +802,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
if (currentChat.photo != null) {
newPhoto = currentChat.photo.photo_small;
}
placeHolderId = Utilities.getGroupAvatarForId(currentChat.id);
placeHolderId = AndroidUtilities.getGroupAvatarForId(currentChat.id);
} else if (currentUser != null) {
TLRPC.User user = MessagesController.getInstance().getUser(currentUser.id);
if (user == null) {
......@@ -810,7 +812,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
if (currentUser.photo != null) {
newPhoto = currentUser.photo.photo_small;
}
placeHolderId = Utilities.getUserAvatarForId(currentUser.id);
placeHolderId = AndroidUtilities.getUserAvatarForId(currentUser.id);
}
if (avatarImageView != null) {
avatarImageView.setImage(newPhoto, "50_50", placeHolderId);
......@@ -823,15 +825,14 @@ public class PopupNotificationActivity extends Activity implements NotificationC
}
if (start) {
try {
actionBarLayer.setSubTitleIcon(R.drawable.typing_dots, AndroidUtilities.dp(4));
AnimationDrawable mAnim = (AnimationDrawable)actionBarLayer.getSubTitleIcon();
mAnim.setAlpha(200);
mAnim.start();
actionBarLayer.setSubTitleIcon(0, typingDotsDrawable, AndroidUtilities.dp(4));
typingDotsDrawable.start();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else {
actionBarLayer.setSubTitleIcon(0, 0);
actionBarLayer.setSubTitleIcon(0, null, 0);
typingDotsDrawable.stop();
}
}
......
......@@ -52,7 +52,6 @@ import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.android.PhotoObject;
import org.telegram.ui.Adapters.BaseFragmentAdapter;
......@@ -817,7 +816,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
user = UserConfig.getCurrentUser();
}
if (user != null) {
textView.setText(Utilities.formatName(user.first_name, user.last_name));
textView.setText(ContactsController.formatName(user.first_name, user.last_name));
BackupImageView avatarImage = (BackupImageView)view.findViewById(R.id.settings_avatar_image);
avatarImage.processDetach = false;
TLRPC.FileLocation photo = null;
......@@ -826,7 +825,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
photo = user.photo.photo_small;
photoBig = user.photo.photo_big;
}
avatarImage.setImage(photo, "50_50", Utilities.getUserAvatarForId(user.id));
avatarImage.setImage(photo, "50_50", AndroidUtilities.getUserAvatarForId(user.id));
avatarImage.imageReceiver.setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false);
}
return view;
......@@ -979,7 +978,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
View divider = view.findViewById(R.id.settings_row_divider);
if (i == textSizeRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
int size = preferences.getInt("fons_size", 16);
int size = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
detailTextView.setText(String.format("%d", size));
textView.setText(LocaleController.getString("TextSize", R.string.TextSize));
divider.setVisibility(View.VISIBLE);
......
......@@ -34,7 +34,6 @@ import org.telegram.android.MessagesController;
import org.telegram.android.MessagesStorage;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.android.MessageObject;
import org.telegram.ui.Adapters.BaseFragmentAdapter;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
......@@ -542,7 +541,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
Typeface typeface = AndroidUtilities.getTypeface("fonts/rmedium.ttf");
textView.setTypeface(typeface);
textView.setText(Utilities.formatName(user.first_name, user.last_name));
textView.setText(ContactsController.formatName(user.first_name, user.last_name));
onlineText.setText(LocaleController.formatUserStatus(user));
TLRPC.FileLocation photo = null;
......@@ -551,7 +550,7 @@ public class UserProfileActivity extends BaseFragment implements NotificationCen
photo = user.photo.photo_small;
photoBig = user.photo.photo_big;
}
avatarImage.setImage(photo, "50_50", Utilities.getUserAvatarForId(user.id));
avatarImage.setImage(photo, "50_50", AndroidUtilities.getUserAvatarForId(user.id));
avatarImage.imageReceiver.setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false);
return view;
} else if (type == 1) {
......
......@@ -10,16 +10,19 @@ package org.telegram.ui;
import android.annotation.TargetApi;
import android.content.res.Configuration;
import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
......@@ -28,14 +31,20 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.coremedia.iso.IsoFile;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.Container;
import com.coremedia.iso.boxes.MediaBox;
import com.coremedia.iso.boxes.MediaHeaderBox;
import com.coremedia.iso.boxes.SampleSizeBox;
import com.coremedia.iso.boxes.TrackBox;
import com.coremedia.iso.boxes.TrackHeaderBox;
import com.coremedia.iso.boxes.h264.AvcConfigurationBox;
import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.googlecode.mp4parser.authoring.tracks.CroppedTrack;
import com.googlecode.mp4parser.util.Matrix;
import com.googlecode.mp4parser.util.Path;
import org.telegram.android.AndroidUtilities;
......@@ -58,22 +67,24 @@ import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@TargetApi(18)
public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.Callback {
@TargetApi(16)
public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener {
private final static int OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100;
private final static int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
private final static int OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
private final static int OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002;
private final static int OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04;
private final static String MIME_TYPE = "video/avc";
private final static int PROCESSOR_TYPE_OTHER = 0;
private final static int PROCESSOR_TYPE_QCOM = 1;
private MediaPlayer videoPlayer = null;
private SurfaceHolder surfaceHolder = null;
private VideoTimelineView videoTimelineView = null;
private View videoContainerView = null;
private TextView originalSizeTextView = null;
......@@ -81,21 +92,33 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
private View textContainerView = null;
private ImageView playButton = null;
private VideoSeekBarView videoSeekBarView = null;
private TextureView textureView = null;
private View controlView = null;
private boolean initied = false;
private String videoPath = null;
private int videoWidth;
private int videoHeight;
private int editedVideoWidth;
private int editedVideoHeight;
private int editedVideoDuration;
private float lastProgress = 0;
private boolean needSeek = false;
private VideoEditorActivityDelegate delegate;
private long esimatedFileSize = 0;
private boolean firstWrite = true;
//MediaMetadataRetriever TODO
private int rotationValue = 0;
private int originalWidth = 0;
private int originalHeight = 0;
private int resultWidth = 0;
private int resultHeight = 0;
private int bitrate = 0;
private float videoDuration = 0;
private long startTime = 0;
private long endTime = 0;
private int audioFramesSize = 0;
private int videoFramesSize = 0;
private int estimatedSize = 0;
private long esimatedDuration = 0;
public interface VideoEditorActivityDelegate {
public abstract void didStartVideoConverting(String videoPath, String originalPath, long esimatedSize, int duration, int width, int height);
public abstract void didStartVideoConverting(String videoPath, String originalPath, long estimatedSize, int duration, int width, int height);
public abstract void didAppenedVideoData(String videoPath, long finalSize);
}
......@@ -107,12 +130,14 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
@Override
public void run() {
if (videoPlayer.isPlaying()) {
float startTime = videoTimelineView.getLeftProgress() * videoPlayer.getDuration();
float endTime = videoTimelineView.getRightProgress() * videoPlayer.getDuration();
float startTime = videoTimelineView.getLeftProgress() * videoDuration;
float endTime = videoTimelineView.getRightProgress() * videoDuration;
if (startTime == endTime) {
startTime = endTime - 0.01f;
}
float progress = (videoPlayer.getCurrentPosition() - startTime) / (endTime - startTime);
float lrdiff = videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress();
progress = videoTimelineView.getLeftProgress() + lrdiff * progress;
if (progress > lastProgress) {
videoSeekBarView.setProgress(progress);
lastProgress = progress;
......@@ -144,7 +169,7 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
@Override
public boolean onFragmentCreate() {
if (videoPath == null) {
if (videoPath == null || !processOpenVideo()) {
return false;
}
videoPlayer = new MediaPlayer();
......@@ -204,6 +229,11 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
editedSizeTextView = (TextView) fragmentView.findViewById(R.id.edited_size);
videoContainerView = fragmentView.findViewById(R.id.video_container);
textContainerView = fragmentView.findViewById(R.id.info_container);
controlView = fragmentView.findViewById(R.id.control_layout);
TextView titleTextView = (TextView) fragmentView.findViewById(R.id.original_title);
titleTextView.setText(LocaleController.getString("OriginalVideo", R.string.OriginalVideo));
titleTextView = (TextView) fragmentView.findViewById(R.id.edited_title);
titleTextView.setText(LocaleController.getString("EditedVideo", R.string.EditedVideo));
videoTimelineView = (VideoTimelineView) fragmentView.findViewById(R.id.video_timeline_view);
videoTimelineView.setVideoPath(videoPath);
......@@ -216,12 +246,12 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
playButton.setImageResource(R.drawable.video_play);
}
videoPlayer.setOnSeekCompleteListener(null);
videoPlayer.seekTo((int) (videoPlayer.getDuration() * progress));
videoPlayer.seekTo((int) (videoDuration * progress));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
needSeek = true;
videoSeekBarView.setProgress(0);
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
updateVideoEditedInfo();
}
......@@ -233,12 +263,12 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
playButton.setImageResource(R.drawable.video_play);
}
videoPlayer.setOnSeekCompleteListener(null);
videoPlayer.seekTo((int) (videoPlayer.getDuration() * progress));
videoPlayer.seekTo((int) (videoDuration * progress));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
needSeek = true;
videoSeekBarView.setProgress(0);
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
updateVideoEditedInfo();
}
});
......@@ -250,7 +280,7 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
if (videoPlayer.isPlaying()) {
try {
float prog = videoTimelineView.getLeftProgress() + (videoTimelineView.getRightProgress() - videoTimelineView.getLeft()) * progress;
videoPlayer.seekTo((int) (videoPlayer.getDuration() * prog));
videoPlayer.seekTo((int) (videoDuration * prog));
lastProgress = progress;
} catch (Exception e) {
FileLog.e("tmessages", e);
......@@ -266,18 +296,12 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (surfaceHolder.isCreating()) {
return;
}
play();
}
});
SurfaceView surfaceView = (SurfaceView) fragmentView.findViewById(R.id.video_view);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.setFixedSize(270, 480);
textureView = (TextureView) fragmentView.findViewById(R.id.video_view);
textureView.setSurfaceTextureListener(this);
updateVideoOriginalInfo();
updateVideoEditedInfo();
......@@ -303,102 +327,114 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
videoPlayer.setDisplay(holder);
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
try {
Surface s = new Surface(surface);
videoPlayer.setSurface(s);
videoPlayer.setDataSource(videoPath);
videoPlayer.prepare();
videoWidth = videoPlayer.getVideoWidth();
videoHeight = videoPlayer.getVideoHeight();
fixVideoSize();
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoPlayer.getDuration()));
initied = true;
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
updateVideoOriginalInfo();
updateVideoEditedInfo();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
videoPlayer.setDisplay(null);
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
private void onPlayComplete() {
playButton.setImageResource(R.drawable.video_play);
videoSeekBarView.setProgress(0);
videoSeekBarView.setProgress(videoTimelineView.getLeftProgress());
try {
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoPlayer.getDuration()));
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
private void updateVideoOriginalInfo() {
if (!initied || originalSizeTextView == null) {
if (originalSizeTextView == null) {
return;
}
File file = new File(videoPath);
String videoDimension = String.format("%dx%d", videoPlayer.getVideoWidth(), videoPlayer.getVideoHeight());
int minutes = videoPlayer.getDuration() / 1000 / 60;
int seconds = (int) Math.ceil(videoPlayer.getDuration() / 1000) - minutes * 60;
int width = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth;
int height = rotationValue == 90 || rotationValue == 270 ? originalWidth : originalHeight;
String videoDimension = String.format("%dx%d", width, height);
int minutes = (int)(videoDuration / 1000 / 60);
int seconds = (int) Math.ceil(videoDuration / 1000) - minutes * 60;
String videoTimeSize = String.format("%d:%02d, %s", minutes, seconds, Utilities.formatFileSize(file.length()));
originalSizeTextView.setText(String.format("%s: %s, %s", LocaleController.getString("OriginalVideo", R.string.OriginalVideo), videoDimension, videoTimeSize));
originalSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize));
}
private void updateVideoEditedInfo() {
if (!initied || editedSizeTextView == null) {
if (editedSizeTextView == null) {
return;
}
File file = new File(videoPath);
long size = file.length();
editedVideoWidth = videoPlayer.getVideoWidth();
editedVideoHeight = videoPlayer.getVideoHeight();
if (editedVideoWidth > 640 || editedVideoHeight > 640) {
float scale = editedVideoWidth > editedVideoHeight ? 640.0f / editedVideoWidth : 640.0f / editedVideoHeight;
editedVideoWidth *= scale;
editedVideoHeight *= scale;
size *= (scale * scale) * 1.02f;
}
String videoDimension = String.format("%dx%d", editedVideoWidth, editedVideoHeight);
editedVideoDuration = videoPlayer.getDuration();
int minutes = editedVideoDuration / 1000 / 60;
int seconds = (int) Math.ceil(editedVideoDuration / 1000) - minutes * 60;
String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, Utilities.formatFileSize(size));
esimatedFileSize = size;
editedSizeTextView.setText(String.format("%s: %s, %s", LocaleController.getString("EditedVideo", R.string.EditedVideo), videoDimension, videoTimeSize));
int width = rotationValue == 90 || rotationValue == 270 ? resultHeight : resultWidth;
int height = rotationValue == 90 || rotationValue == 270 ? resultWidth : resultHeight;
String videoDimension = String.format("%dx%d", resultWidth, resultHeight);
esimatedDuration = (long)Math.max(1000, (videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration);
estimatedSize = calculateEstimatedSize((float)esimatedDuration / videoDuration);
startTime = (long)(videoTimelineView.getLeftProgress() * videoDuration) * 1000;
endTime = (long)(videoTimelineView.getRightProgress() * videoDuration) * 1000;
int minutes = (int)(esimatedDuration / 1000 / 60);
int seconds = (int) Math.ceil(esimatedDuration / 1000) - minutes * 60;
String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, Utilities.formatFileSize(estimatedSize));
editedSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize));
}
private void fixVideoSize() {
if (videoWidth == 0 || videoHeight == 0 || fragmentView == null || getParentActivity() == null) {
if (fragmentView == null || getParentActivity() == null) {
return;
}
int viewHeight = 0;
if (!Utilities.isTablet(getParentActivity()) && getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (AndroidUtilities.isTablet()) {
viewHeight = AndroidUtilities.dp(472);
} else {
if (!AndroidUtilities.isTablet() && getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(40);
} else {
viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(48);
}
}
int width = 0;
int height = 0;
if (AndroidUtilities.isTablet()) {
width = AndroidUtilities.dp(490);
height = viewHeight - AndroidUtilities.dp(276);
} else {
if (getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
width = AndroidUtilities.displaySize.x - AndroidUtilities.displaySize.x / 2 - AndroidUtilities.dp(24);
width = AndroidUtilities.displaySize.x / 3 - AndroidUtilities.dp(24);
height = viewHeight - AndroidUtilities.dp(32);
} else {
width = AndroidUtilities.displaySize.x;
height = viewHeight - AndroidUtilities.dp(176);
height = viewHeight - AndroidUtilities.dp(276);
}
}
float wr = (float) width / (float) videoWidth;
float hr = (float) height / (float) videoHeight;
float ar = (float) videoWidth / (float) videoHeight;
int aWidth = width;
int aHeight = height;
int vwidth = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth;
int vheight = rotationValue == 90 || rotationValue == 270 ? originalWidth : originalHeight;
float wr = (float) width / (float) vwidth;
float hr = (float) height / (float) vheight;
float ar = (float) vwidth / (float) vheight;
if (wr > hr) {
width = (int) (height * ar);
......@@ -406,7 +442,12 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
height = (int) (width / ar);
}
surfaceHolder.setFixedSize(width, height);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)textureView.getLayoutParams();
layoutParams.width = width;
layoutParams.height = height;
layoutParams.leftMargin = 0;
layoutParams.topMargin = 0;
textureView.setLayoutParams(layoutParams);
}
private void fixLayout() {
......@@ -417,35 +458,49 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
@Override
public boolean onPreDraw() {
originalSizeTextView.getViewTreeObserver().removeOnPreDrawListener(this);
if (getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoContainerView.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(16);
layoutParams.bottomMargin = AndroidUtilities.dp(16);
layoutParams.width = AndroidUtilities.displaySize.x / 2 - AndroidUtilities.dp(24);
layoutParams.width = AndroidUtilities.displaySize.x / 3 - AndroidUtilities.dp(24);
layoutParams.leftMargin = AndroidUtilities.dp(16);
videoContainerView.setLayoutParams(layoutParams);
layoutParams = (FrameLayout.LayoutParams) controlView.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(16);
layoutParams.bottomMargin = 0;
layoutParams.width = AndroidUtilities.displaySize.x / 3 * 2 - AndroidUtilities.dp(32);
layoutParams.leftMargin = AndroidUtilities.displaySize.x / 3 + AndroidUtilities.dp(16);
layoutParams.gravity = Gravity.TOP;
controlView.setLayoutParams(layoutParams);
layoutParams = (FrameLayout.LayoutParams) textContainerView.getLayoutParams();
layoutParams.height = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.width = AndroidUtilities.displaySize.x / 2 - AndroidUtilities.dp(24);
layoutParams.leftMargin = AndroidUtilities.displaySize.x / 2 + AndroidUtilities.dp(8);
layoutParams.width = AndroidUtilities.displaySize.x / 3 * 2 - AndroidUtilities.dp(32);
layoutParams.leftMargin = AndroidUtilities.displaySize.x / 3 + AndroidUtilities.dp(16);
layoutParams.rightMargin = AndroidUtilities.dp(16);
layoutParams.topMargin = AndroidUtilities.dp(16);
layoutParams.bottomMargin = AndroidUtilities.dp(16);
textContainerView.setLayoutParams(layoutParams);
} else {
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoContainerView.getLayoutParams();
layoutParams.topMargin = AndroidUtilities.dp(16);
layoutParams.bottomMargin = AndroidUtilities.dp(160);
layoutParams.bottomMargin = AndroidUtilities.dp(260);
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.leftMargin = 0;
videoContainerView.setLayoutParams(layoutParams);
layoutParams = (FrameLayout.LayoutParams) controlView.getLayoutParams();
layoutParams.topMargin = 0;
layoutParams.leftMargin = 0;
layoutParams.bottomMargin = AndroidUtilities.dp(150);
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.gravity = Gravity.BOTTOM;
controlView.setLayoutParams(layoutParams);
layoutParams = (FrameLayout.LayoutParams) textContainerView.getLayoutParams();
layoutParams.height = AndroidUtilities.dp(143);
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.leftMargin = 0;
layoutParams.rightMargin = 0;
layoutParams.topMargin = 0;
layoutParams.leftMargin = AndroidUtilities.dp(16);
layoutParams.rightMargin = AndroidUtilities.dp(16);
layoutParams.bottomMargin = AndroidUtilities.dp(16);
textContainerView.setLayoutParams(layoutParams);
}
fixVideoSize();
......@@ -465,18 +520,20 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
lastProgress = 0;
if (needSeek) {
float prog = videoTimelineView.getLeftProgress() + (videoTimelineView.getRightProgress() - videoTimelineView.getLeft()) * videoSeekBarView.getProgress();
videoPlayer.seekTo((int) (videoPlayer.getDuration() * prog));
videoPlayer.seekTo((int) (videoDuration * prog));
needSeek = false;
}
videoPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mp) {
float startTime = videoTimelineView.getLeftProgress() * videoPlayer.getDuration();
float endTime = videoTimelineView.getRightProgress() * videoPlayer.getDuration();
float startTime = videoTimelineView.getLeftProgress() * videoDuration;
float endTime = videoTimelineView.getRightProgress() * videoDuration;
if (startTime == endTime) {
startTime = endTime - 0.01f;
}
lastProgress = (videoPlayer.getCurrentPosition() - startTime) / (endTime - startTime);
float lrdiff = videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress();
lastProgress = videoTimelineView.getLeftProgress() + lrdiff * lastProgress;
videoSeekBarView.setProgress(lastProgress);
}
});
......@@ -538,12 +595,14 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
}
}
private void didWriteData(final String videoPath, final boolean first, final long finalSize) {
private void didWriteData(final String videoPath, final long finalSize) {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (first) {
delegate.didStartVideoConverting(videoPath, VideoEditorActivity.this.videoPath, esimatedFileSize, editedVideoDuration, editedVideoWidth, editedVideoHeight);
if (firstWrite) {
delegate.didStartVideoConverting(videoPath, VideoEditorActivity.this.videoPath, estimatedSize, (int)esimatedDuration, resultWidth, resultHeight);
firstWrite = false;
finishFragment();
} else {
delegate.didAppenedVideoData(videoPath, finalSize);
}
......@@ -551,106 +610,286 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
});
}
private boolean startConvert2() {
MediaCodec decoder = null;
MediaCodec encoder = null;
MediaExtractor extractor = null;
InputSurface inputSurface = null;
OutputSurface outputSurface = null;
MP4Builder mediaMuxer = null;
File cacheFile = null;
long time = System.currentTimeMillis();
boolean finished = true;
boolean firstWrite = true;
class AudioBufferTemp {
ByteBuffer buffer;
int flags;
int size;
long presentationTimeUs;
private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (String type : types) {
if (type.equalsIgnoreCase(mimeType)) {
return codecInfo;
}
}
}
return null;
}
try {
File inputFile = new File(videoPath);
if (!inputFile.canRead()) {
private static boolean isRecognizedFormat(int colorFormat) {
switch (colorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
return true;
default:
return false;
}
}
boolean outputDone = false;
private static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
for (int i = 0; i < capabilities.colorFormats.length; i++) {
int colorFormat = capabilities.colorFormats[i];
if (isRecognizedFormat(colorFormat)) {
return colorFormat;
}
}
return 0;
}
private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception {
int trackIndex = selectTrack(extractor, isAudio);
if (trackIndex >= 0) {
extractor.selectTrack(trackIndex);
MediaFormat trackFormat = extractor.getTrackFormat(trackIndex);
int muxerTrackIndex = mediaMuxer.addTrack(trackFormat, isAudio);
int maxBufferSize = trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
boolean inputDone = false;
boolean decoderDone = false;
boolean muxerStarted = false;
int videoTrackIndex = -5;
int audioTrackIndex = -5;
int audioIndex = -5;
int videoIndex = -5;
int audioBufferSize = 0;
ByteBuffer audioBuffer = null;
ArrayList<AudioBufferTemp> audioBuffers = new ArrayList<AudioBufferTemp>();
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(inputFile.toString());
String rotation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
int rotationValue = 0;
if (rotation != null) {
extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
long startTime = -1;
while (!inputDone) {
boolean eof = false;
int index = extractor.getSampleTrackIndex();
if (index == trackIndex) {
info.size = extractor.readSampleData(buffer, 0);
if (info.size < 0) {
info.size = 0;
eof = true;
} else {
info.presentationTimeUs = extractor.getSampleTime();
if (startTime == -1) {
startTime = info.presentationTimeUs;
}
if (info.presentationTimeUs < end) {
info.offset = 0;
info.flags = extractor.getSampleFlags();
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
didWriteData(file.toString(), 0);
}
extractor.advance();
} else {
eof = true;
}
}
} else if (index == -1) {
eof = true;
}
if (eof) {
inputDone = true;
}
}
extractor.unselectTrack(trackIndex);
return startTime;
}
return -1;
}
private boolean processOpenVideo() {
try {
IsoFile isoFile = new IsoFile(videoPath);
List<Box> boxes = Path.getPaths(isoFile, "/moov/trak/");
TrackHeaderBox trackHeaderBox = null;
for (Box box : boxes) {
TrackBox trackBox = (TrackBox)box;
int sampleSizes = 0;
int trackBitrate = 0;
try {
rotationValue = Integer.parseInt(rotation);
MediaBox mediaBox = trackBox.getMediaBox();
MediaHeaderBox mediaHeaderBox = mediaBox.getMediaHeaderBox();
SampleSizeBox sampleSizeBox = mediaBox.getMediaInformationBox().getSampleTableBox().getSampleSizeBox();
for (long size : sampleSizeBox.getSampleSizes()) {
sampleSizes += size;
}
videoDuration = mediaHeaderBox.getDuration() / mediaHeaderBox.getTimescale();
trackBitrate = (int)(sampleSizes * 8 / videoDuration);
} catch (Exception e) {
//don't promt
FileLog.e("tmessages", e);
}
TrackHeaderBox headerBox = trackBox.getTrackHeaderBox();
if (headerBox.getWidth() != 0 && headerBox.getHeight() != 0) {
trackHeaderBox = headerBox;
bitrate = trackBitrate / 100000 * 100000;
if (bitrate > 900000) {
bitrate = 900000;
}
} else {
audioFramesSize += sampleSizes;
}
}
if (trackHeaderBox == null) {
return false;
}
extractor = new MediaExtractor();
extractor.setDataSource(inputFile.toString());
Matrix matrix = trackHeaderBox.getMatrix();
if (matrix.equals(Matrix.ROTATE_90)) {
rotationValue = 90;
} else if (matrix.equals(Matrix.ROTATE_180)) {
rotationValue = 180;
} else if (matrix.equals(Matrix.ROTATE_270)) {
rotationValue = 270;
}
resultWidth = originalWidth = (int)trackHeaderBox.getWidth();
resultHeight = originalHeight = (int)trackHeaderBox.getHeight();
if (resultWidth > 640 || resultHeight > 640) {
float scale = resultWidth > resultHeight ? 640.0f / resultWidth : 640.0f / resultHeight;
resultWidth *= scale;
resultHeight *= scale;
if (bitrate != 0) {
bitrate *= scale;
videoFramesSize = (int)(bitrate / 8 * videoDuration);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
return false;
}
videoDuration *= 1000;
updateVideoOriginalInfo();
updateVideoEditedInfo();
return true;
}
private int calculateEstimatedSize(float timeDelta) {
int size = (int)((audioFramesSize + videoFramesSize) * timeDelta);
size += size / (32 * 1024) * 16;
return size;
}
private boolean startConvert2() {
File inputFile = new File(videoPath);
if (!inputFile.canRead()) {
return false;
}
firstWrite = true;
File cacheFile = null;
boolean error = false;
long videoStartTime = startTime;
long time = System.currentTimeMillis();
if (resultWidth != 0 && resultHeight != 0) {
MP4Builder mediaMuxer = null;
MediaExtractor extractor = null;
MediaCodec decoder = null;
MediaCodec encoder = null;
InputSurface inputSurface = null;
OutputSurface outputSurface = null;
try {
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
UserConfig.lastLocalId--;
cacheFile = new File(AndroidUtilities.getCacheDir(), fileName);
UserConfig.saveConfig(false);
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
Mp4Movie movie = new Mp4Movie();
movie.setCacheFile(cacheFile);
movie.setRotation(rotationValue);
movie.setSize(640, 360);
movie.setSize(resultWidth, resultHeight);
mediaMuxer = new MP4Builder().createMovie(movie);
extractor = new MediaExtractor();
extractor.setDataSource(inputFile.toString());
if (resultWidth != originalWidth || resultHeight != originalHeight) {
int videoIndex = -5;
videoIndex = selectTrack(extractor, false);
if (videoIndex < 0) {
return false;
if (videoIndex >= 0) {
boolean outputDone = false;
boolean inputDone = false;
boolean decoderDone = false;
int videoTrackIndex = -5;
long videoTime = -1;
int colorFormat = 0;
int processorType = PROCESSOR_TYPE_OTHER;
if (Build.VERSION.SDK_INT < 18) {
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
if (codecInfo.getName().contains("OMX.qcom.")) {
processorType = PROCESSOR_TYPE_QCOM;
}
extractor.selectTrack(videoIndex);
MediaFormat inputFormat = extractor.getTrackFormat(videoIndex);
String mime = inputFormat.getString(MediaFormat.KEY_MIME);
FileLog.e("tmessages", "codec = " + codecInfo.getName());
} else {
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
}
FileLog.e("tmessages", "colorFormat = " + colorFormat);
audioIndex = selectTrack(extractor, true);
if (audioIndex >= 0) {
extractor.selectTrack(audioIndex);
MediaFormat audioFormat = extractor.getTrackFormat(audioIndex);
audioTrackIndex = mediaMuxer.addTrack(audioFormat, false);
audioBufferSize = audioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
int resultHeightAligned = resultHeight;
int padding = 0;
int bufferSize = resultWidth * resultHeight * 3 / 2;
if (processorType == PROCESSOR_TYPE_OTHER) {
if (resultHeight % 16 != 0) {
resultHeightAligned += (16 - (resultHeight % 16));
padding = resultWidth * (resultHeightAligned - resultHeight);
bufferSize += padding * 5 / 4;
}
} else if (processorType == PROCESSOR_TYPE_QCOM) {
int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
padding = uvoffset - (resultWidth * resultHeight);
bufferSize += padding;
}
MediaFormat outputFormat = MediaFormat.createVideoFormat(mime, 640, 360);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1000000);
extractor.selectTrack(videoIndex);
extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
MediaFormat inputFormat = extractor.getTrackFormat(videoIndex);
MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate != 0 ? bitrate : 921600);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
if (Build.VERSION.SDK_INT < 18) {
outputFormat.setInteger("stride", resultWidth);
outputFormat.setInteger("slice-height", resultHeightAligned);
}
encoder = MediaCodec.createEncoderByType(mime);
encoder = MediaCodec.createEncoderByType(MIME_TYPE);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
if (Build.VERSION.SDK_INT >= 18) {
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
}
encoder.start();
decoder = MediaCodec.createDecoderByType(mime);
decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
if (Build.VERSION.SDK_INT >= 18) {
outputSurface = new OutputSurface();
} else {
outputSurface = new OutputSurface(resultWidth, resultHeight);
}
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
decoder.start();
final int TIMEOUT_USEC = 10000;
final int TIMEOUT_USEC = 2500;
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
ByteBuffer[] encoderInputBuffers = null;
if (Build.VERSION.SDK_INT < 18) {
encoderInputBuffers = encoder.getInputBuffers();
}
while (!outputDone) {
if (!inputDone) {
......@@ -669,31 +908,6 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
extractor.advance();
}
}
} else if (index == audioIndex) {
if (audioBuffer == null) {
audioBuffer = ByteBuffer.allocate(audioBufferSize);
}
info.size = extractor.readSampleData(audioBuffer, 0);
if (info.size < 0) {
info.size = 0;
eof = true;
} else {
if (muxerStarted) {
info.offset = 0;
info.presentationTimeUs = extractor.getSampleTime();
info.flags = extractor.getSampleFlags();
mediaMuxer.writeSampleData(audioTrackIndex, audioBuffer, info);
} else {
AudioBufferTemp audioBufferTemp = new AudioBufferTemp();
audioBufferTemp.buffer = audioBuffer;
audioBufferTemp.presentationTimeUs = extractor.getSampleTime();
audioBufferTemp.flags = extractor.getSampleFlags();
audioBufferTemp.size = info.size;
audioBuffers.add(audioBufferTemp);
audioBuffer = null;
}
extractor.advance();
}
} else if (index == -1) {
eof = true;
}
......@@ -716,44 +930,51 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
encoderOutputBuffers = encoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = encoder.getOutputFormat();
if (muxerStarted) {
throw new RuntimeException("format changed twice");
}
videoTrackIndex = mediaMuxer.addTrack(newFormat, true);
muxerStarted = true;
if (!audioBuffers.isEmpty()) {
for (AudioBufferTemp audioBufferTemp : audioBuffers) {
info.size = audioBufferTemp.size;
info.offset = 0;
info.presentationTimeUs = audioBufferTemp.presentationTimeUs;
info.flags = audioBufferTemp.flags;
mediaMuxer.writeSampleData(audioTrackIndex, audioBufferTemp.buffer, info);
}
audioBuffers.clear();
if (videoTrackIndex == -5) {
videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
}
} else if (encoderStatus < 0) {
FileLog.e("tmessages", "unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
return false;
throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
FileLog.e("tmessages", "encoderOutputBuffer " + encoderStatus + " was null");
return false;
}
if (info.size != 0) {
if (!muxerStarted) {
throw new RuntimeException("muxer hasn't started");
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
}
if (info.size > 1) {
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
encodedData.limit(info.size);
encodedData.limit(info.offset + info.size);
encodedData.position(info.offset);
encodedData.putInt(Integer.reverseBytes(info.size - 4));
mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info);
didWriteData(cacheFile.toString(), firstWrite, 0);
if (firstWrite) {
firstWrite = false;
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
didWriteData(cacheFile.toString(), 0);
}
} else if (videoTrackIndex == -5) {
byte[] csd = new byte[info.size];
encodedData.limit(info.offset + info.size);
encodedData.position(info.offset);
encodedData.get(csd);
ByteBuffer sps = null;
ByteBuffer pps = null;
for (int a = info.size - 1; a >= 0; a--) {
if (a > 3) {
if (csd[a] == 1 && csd[a - 1] == 0 && csd[a - 2] == 0 && csd[a - 3] == 0) {
sps = ByteBuffer.allocate(a - 3);
pps = ByteBuffer.allocate(info.size - (a - 3));
sps.put(csd, 0, a - 3).position(0);
pps.put(csd, a - 3, info.size - (a - 3)).position(0);
break;
}
} else {
break;
}
}
MediaFormat newFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight);
if (sps != null && pps != null) {
newFormat.setByteBuffer("csd-0", sps);
newFormat.setByteBuffer("csd-1", pps);
}
videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
}
}
outputDone = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
......@@ -772,64 +993,93 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
} else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = decoder.getOutputFormat();
} else if (decoderStatus < 0) {
FileLog.e("tmessages", "unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
return false;
throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else {
boolean doRender = false;
if (Build.VERSION.SDK_INT >= 18) {
doRender = info.size != 0;
} else {
doRender = info.size != 0 || info.presentationTimeUs != 0;
}
if (info.presentationTimeUs >= endTime) {
inputDone = true;
decoderDone = true;
doRender = false;
info.flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
}
if (videoTime == -1) {
if (info.presentationTimeUs < startTime) {
doRender = false;
FileLog.e("tmessages", "drop frame startTime = " + startTime + " present time = " + info.presentationTimeUs);
} else {
boolean doRender = (info.size != 0);
videoTime = info.presentationTimeUs;
}
}
decoder.releaseOutputBuffer(decoderStatus, doRender);
if (doRender) {
boolean errorWait = false;
try {
outputSurface.awaitNewImage();
outputSurface.drawImage();
} catch (Exception e) {
errorWait = true;
FileLog.e("tmessages", e);
}
if (!errorWait) {
if (Build.VERSION.SDK_INT >= 18) {
outputSurface.drawImage(false);
inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
inputSurface.swapBuffers();
} else {
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
outputSurface.drawImage(true);
ByteBuffer rgbBuf = outputSurface.getFrame();
ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex];
yuvBuf.clear();
Utilities.convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding);
encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
} else {
FileLog.e("tmessages", "input buffer not available");
}
}
}
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
FileLog.e("tmessages", "signaling input EOS");
//if (WORK_AROUND_BUGS) {
// Bail early, possibly dropping a frame.
// return;
//} else {
decoderOutputAvailable = false;
FileLog.e("tmessages", "decoder stream end");
if (Build.VERSION.SDK_INT >= 18) {
encoder.signalEndOfInputStream();
//}
} else {
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
}
}
}
/*if (!outputDone) { without surface
int decoderStatus = decoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
if (decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
FileLog.e("tmessages", "no output from decoder available");
} else if (decoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
FileLog.e("tmessages", "decoder output buffers changed");
decoderOutputBuffers = decoder.getOutputBuffers();
} else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
decoderOutputFormat = decoder.getOutputFormat();
FileLog.e("tmessages", "decoder output format changed: " + decoderOutputFormat);
} else if (decoderStatus < 0) {
FileLog.e("tmessages", "unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
return false;
} else {
ByteBuffer outputFrame = decoderOutputBuffers[decoderStatus];
outputFrame.position(info.offset);
outputFrame.limit(info.offset + info.size);
if (info.size == 0) {
FileLog.e("tmessages", "got empty frame");
} else {
FileLog.e("tmessages", "decoded, checking frame format = " + decoderOutputFormat + " size = " + outputFrame.limit());
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
FileLog.e("tmessages", "output EOS");
outputDone = true;
}
decoder.releaseOutputBuffer(decoderStatus, false);
extractor.unselectTrack(videoIndex);
if (videoTime != -1) {
videoStartTime = videoTime;
}
}
} else {
long videoTime = readAndWriteTrack(extractor, mediaMuxer, info, startTime, endTime, cacheFile, false);
if (videoTime != -1) {
videoStartTime = videoTime;
}
}*/
}
readAndWriteTrack(extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true);
} catch (Exception e) {
error = true;
FileLog.e("tmessages", e);
finished = false;
} finally {
if (extractor != null) {
extractor.release();
extractor = null;
}
if (outputSurface != null) {
outputSurface.release();
outputSurface = null;
......@@ -848,10 +1098,6 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
encoder.release();
encoder = null;
}
if (extractor != null) {
extractor.release();
extractor = null;
}
if (mediaMuxer != null) {
try {
mediaMuxer.finishMovie(false);
......@@ -862,16 +1108,13 @@ public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.C
}
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
}
if (finished) {
didWriteData(cacheFile.toString(), firstWrite, cacheFile.length());
} else {
return false;
}
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
finishFragment();
if (!error && cacheFile != null) {
didWriteData(cacheFile.toString(), cacheFile.length());
}
});
return finished;
return true;
}
private void startConvert() throws Exception {
......
......@@ -21,7 +21,6 @@ import android.widget.FrameLayout;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import java.util.ArrayList;
......@@ -171,7 +170,7 @@ public class ActionBar extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(40), MeasureSpec.EXACTLY));
} else {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY));
......
......@@ -23,7 +23,6 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
public class ActionBarLayer extends FrameLayout {
......@@ -55,6 +54,7 @@ public class ActionBarLayer extends FrameLayout {
private boolean isBackOverlayVisible;
protected BaseFragment parentFragment;
public ActionBarMenuOnItemClick actionBarMenuOnItemClick;
private int leftMargin = 0;
public ActionBarLayer(Context context, ActionBar actionBar) {
super(context);
......@@ -94,13 +94,17 @@ public class ActionBarLayer extends FrameLayout {
super(context, attrs, defStyleAttr);
}
public void setExtraLeftMargin(int margin) {
leftMargin = margin;
}
private void positionBackImage(int height) {
if (backButtonImageView != null) {
LayoutParams layoutParams = (LayoutParams)backButtonImageView.getLayoutParams();
layoutParams.width = LayoutParams.WRAP_CONTENT;
layoutParams.height = LayoutParams.WRAP_CONTENT;
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
layoutParams.setMargins(AndroidUtilities.dp(3), (height - backButtonImageView.getDrawable().getIntrinsicHeight()) / 2, 0, 0);
layoutParams.setMargins(AndroidUtilities.dp(3 + leftMargin), (height - backButtonImageView.getDrawable().getIntrinsicHeight()) / 2, 0, 0);
backButtonImageView.setLayoutParams(layoutParams);
}
}
......@@ -108,7 +112,7 @@ public class ActionBarLayer extends FrameLayout {
private void positionLogoImage(int height) {
if (logoImageView != null) {
LayoutParams layoutParams = (LayoutParams) logoImageView.getLayoutParams();
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
layoutParams.width = (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f);
layoutParams.height = (int)(logoImageView.getDrawable().getIntrinsicHeight() / 1.3f);
layoutParams.setMargins(AndroidUtilities.dp(12), (height - layoutParams.height) / 2, 0, 0);
......@@ -124,7 +128,7 @@ public class ActionBarLayer extends FrameLayout {
private void positionTitle(int width, int height) {
int offset = AndroidUtilities.dp(2);
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
offset = AndroidUtilities.dp(1);
}
int maxTextWidth = 0;
......@@ -132,7 +136,7 @@ public class ActionBarLayer extends FrameLayout {
LayoutParams layoutParams = null;
if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) {
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
titleTextView.setTextSize(16);
} else {
titleTextView.setTextSize(18);
......@@ -147,7 +151,7 @@ public class ActionBarLayer extends FrameLayout {
maxTextWidth = titleTextView.getMeasuredWidth();
}
if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) {
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
subTitleTextView.setTextSize(12);
} else {
subTitleTextView.setTextSize(14);
......@@ -164,12 +168,12 @@ public class ActionBarLayer extends FrameLayout {
int x = 0;
if (logoImageView == null || logoImageView.getVisibility() == GONE) {
x = AndroidUtilities.dp(16);
x = AndroidUtilities.dp(16 + leftMargin);
} else {
if (!Utilities.isTablet(getContext()) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
x = AndroidUtilities.dp(22) + (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f);
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
x = AndroidUtilities.dp(22 + leftMargin) + (int)(logoImageView.getDrawable().getIntrinsicWidth() / 1.3f);
} else {
x = AndroidUtilities.dp(22) + logoImageView.getDrawable().getIntrinsicWidth();
x = AndroidUtilities.dp(22 + leftMargin) + logoImageView.getDrawable().getIntrinsicWidth();
}
}
......@@ -258,8 +262,8 @@ public class ActionBarLayer extends FrameLayout {
}
}
public void setSubTitleIcon(int resourceId, int padding) {
if (resourceId != 0 && subTitleTextView == null) {
public void setSubTitleIcon(int resourceId, Drawable drawable, int padding) {
if ((resourceId != 0 || drawable != null) && subTitleTextView == null) {
subTitleTextView = new TextView(getContext());
backButtonFrameLayout.addView(subTitleTextView);
subTitleTextView.setGravity(Gravity.LEFT);
......@@ -271,7 +275,11 @@ public class ActionBarLayer extends FrameLayout {
positionTitle(getMeasuredWidth(), getMeasuredHeight());
}
if (subTitleTextView != null) {
if (drawable != null) {
subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
} else {
subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(resourceId, 0, 0, 0);
}
subTitleTextView.setCompoundDrawablePadding(padding);
}
}
......@@ -479,7 +487,7 @@ public class ActionBarLayer extends FrameLayout {
}
isBackOverlayVisible = visible;
if (visible) {
((ActionBarActivity)getContext()).onOverlayShow(actionOverlay, parentFragment);
parentFragment.parentLayout.onOverlayShow(actionOverlay, parentFragment);
}
positionBackOverlay(getMeasuredWidth(), getMeasuredHeight());
}
......
......@@ -16,7 +16,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.ActionMode;
import android.view.Gravity;
......@@ -26,7 +25,6 @@ import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
......@@ -35,11 +33,10 @@ import android.widget.FrameLayout;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import java.util.ArrayList;
public class ActionBarActivity extends Activity {
public class ActionBarLayout extends FrameLayout {
private class FrameLayoutAnimationListener extends FrameLayout {
public FrameLayoutAnimationListener(Context context) {
......@@ -49,18 +46,30 @@ public class ActionBarActivity extends Activity {
@Override
protected void onAnimationEnd() {
super.onAnimationEnd();
ActionBarActivity.this.onAnimationEnd();
ActionBarLayout.this.onAnimationEndCheck();
}
}
public static interface ActionBarLayoutDelegate {
public abstract boolean onPreIme();
public abstract void onOverlayShow(View view, BaseFragment fragment);
public abstract boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout);
public abstract boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout);
public abstract boolean needCloseLastFragment(ActionBarLayout layout);
public abstract void onRebuildAllFragments(ActionBarLayout layout);
}
protected ActionBar actionBar;
private FrameLayoutAnimationListener containerView;
private FrameLayoutAnimationListener containerViewBack;
protected FrameLayout contentView;
private View shadowView;
private Animation openAnimation;
private Animation closeAnimation;
private Animation alphaOpenAnimation;
private Animation alphaOpenAnimation2;
private Animation alphaCloseAnimation;
private Animation alphaCloseAnimation2;
private boolean maybeStartTracking = false;
protected boolean startedTracking = false;
......@@ -75,69 +84,35 @@ public class ActionBarActivity extends Activity {
private int startedTrackingPointerId;
private Runnable onCloseAnimationEndRunnable = null;
private Runnable onOpenAnimationEndRunnable = null;
private boolean useAlphaAnimations = false;
private View backgroundView;
private class FrameLayoutTouch extends FrameLayout {
public FrameLayoutTouch(Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return !(!animationInProgress && !checkTransitionAnimation()) || ((ActionBarActivity) getContext()).onTouchEvent(ev);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
((ActionBarActivity)getContext()).onTouchEvent(null);
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return ((ActionBarActivity)getContext()).onPreIme() || super.dispatchKeyEventPreIme(event);
}
return super.dispatchKeyEventPreIme(event);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
return super.onKeyPreIme(keyCode, event);
}
}
public static ArrayList<BaseFragment> fragmentsStack = new ArrayList<BaseFragment>();
private ActionBarLayoutDelegate delegate = null;
protected Activity parentActivity = null;
protected void onCreateFinish(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
public ArrayList<BaseFragment> fragmentsStack = null;
public ActionBarLayout(Context context) {
super(context);
parentActivity = (Activity)context;
try {
openAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_in);
closeAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_out);
openAnimation = AnimationUtils.loadAnimation(context, R.anim.scale_in);
closeAnimation = AnimationUtils.loadAnimation(context, R.anim.scale_out);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
setTheme(R.style.Theme_TMessages);
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
contentView = new FrameLayoutTouch(this);
setContentView(contentView, new ViewGroup.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
containerViewBack = new FrameLayoutAnimationListener(this);
contentView.addView(containerViewBack);
public void init(ArrayList<BaseFragment> stack) {
fragmentsStack = stack;
containerViewBack = new FrameLayoutAnimationListener(parentActivity);
addView(containerViewBack);
containerView = new FrameLayoutAnimationListener(this);
contentView.addView(containerView);
containerView = new FrameLayoutAnimationListener(parentActivity);
addView(containerView);
shadowView = new FrameLayout(this);
contentView.addView(shadowView);
shadowView = new FrameLayout(parentActivity);
addView(shadowView);
shadowView.setBackgroundResource(R.drawable.shadow);
ViewGroup.LayoutParams layoutParams = shadowView.getLayoutParams();
layoutParams.width = AndroidUtilities.dp(2);
......@@ -145,14 +120,14 @@ public class ActionBarActivity extends Activity {
shadowView.setLayoutParams(layoutParams);
shadowView.setVisibility(View.INVISIBLE);
actionBar = new ActionBar(this);
contentView.addView(actionBar);
actionBar = new ActionBar(parentActivity);
addView(actionBar);
layoutParams = actionBar.getLayoutParams();
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
actionBar.setLayoutParams(layoutParams);
for (BaseFragment fragment : fragmentsStack) {
fragment.setParentActivity(this);
fragment.setParentLayout(this);
}
needLayout();
......@@ -168,9 +143,7 @@ public class ActionBarActivity extends Activity {
}
}
@Override
protected void onResume() {
super.onResume();
public void onResume() {
fixLayout();
if (transitionAnimationInProgress) {
if (onCloseAnimationEndRunnable != null) {
......@@ -189,15 +162,42 @@ public class ActionBarActivity extends Activity {
}
}
@Override
protected void onPause() {
super.onPause();
public void onPause() {
if (!fragmentsStack.isEmpty()) {
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
lastFragment.onPause();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return !(!animationInProgress && !checkTransitionAnimation()) || onTouchEvent(ev);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
onTouchEvent(null);
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return delegate != null && delegate.onPreIme() || super.dispatchKeyEventPreIme(event);
}
return super.dispatchKeyEventPreIme(event);
}
@Override
protected void onAnimationEnd() {
super.onAnimationEnd();
onAnimationEndCheck();
}
public void setDelegate(ActionBarLayoutDelegate delegate) {
this.delegate = delegate;
}
private void onSlideAnimationEnd(boolean backAnimation) {
containerView.setX(0);
containerViewBack.setX(0);
......@@ -208,7 +208,7 @@ public class ActionBarActivity extends Activity {
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
lastFragment.onPause();
lastFragment.onFragmentDestroy();
lastFragment.setParentActivity(null);
lastFragment.setParentLayout(null);
fragmentsStack.remove(fragmentsStack.size() - 1);
FrameLayoutAnimationListener temp = containerView;
......@@ -230,7 +230,7 @@ public class ActionBarActivity extends Activity {
}
}
containerViewBack.setVisibility(View.GONE);
AndroidUtilities.unlockOrientation(this);
AndroidUtilities.unlockOrientation(parentActivity);
startedTracking = false;
animationInProgress = false;
}
......@@ -246,7 +246,7 @@ public class ActionBarActivity extends Activity {
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 2);
actionBar.prepareForMoving(lastFragment.actionBarLayer);
View fragmentView = lastFragment.createView(getLayoutInflater(), null);
View fragmentView = lastFragment.createView(parentActivity.getLayoutInflater(), null);
ViewGroup parentView = (ViewGroup)fragmentView.getParent();
if (parentView != null) {
parentView.removeView(fragmentView);
......@@ -261,7 +261,7 @@ public class ActionBarActivity extends Activity {
}
lastFragment.onResume();
AndroidUtilities.lockOrientation(this);
AndroidUtilities.lockOrientation(parentActivity);
}
public boolean onTouchEvent(MotionEvent ev) {
......@@ -289,8 +289,8 @@ public class ActionBarActivity extends Activity {
prepareForMoving(ev);
} else if (startedTracking) {
if (!beginTrackingSent) {
if (getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(getCurrentFocus());
if (parentActivity.getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
}
BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1);
currentFragment.onBeginSlide();
......@@ -377,7 +377,10 @@ public class ActionBarActivity extends Activity {
return false;
}
@Override
public ActionBar getActionBar() {
return actionBar;
}
public void onBackPressed() {
if (startedTracking || checkTransitionAnimation() || fragmentsStack.isEmpty()) {
return;
......@@ -388,58 +391,54 @@ public class ActionBarActivity extends Activity {
}
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
if (lastFragment.onBackPressed()) {
if (fragmentsStack.size() == 1) {
fragmentsStack.get(0).onFragmentDestroy();
fragmentsStack.clear();
onFinish();
finish();
} else if (!fragmentsStack.isEmpty()) {
if (!fragmentsStack.isEmpty()) {
closeLastFragment(true);
}
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
for (BaseFragment fragment : fragmentsStack) {
fragment.onLowMemory();
}
}
private void onAnimationEndCheck() {
onCloseAnimationEnd(false);
onOpenAnimationEnd(false);
}
public boolean checkTransitionAnimation() {
if (transitionAnimationInProgress && transitionAnimationStartTime < System.currentTimeMillis() - 400) {
transitionAnimationInProgress = false;
onAnimationEnd();
onAnimationEndCheck();
}
return transitionAnimationInProgress;
}
private void fixLayout() {
if (contentView != null) {
ViewTreeObserver obs = contentView.getViewTreeObserver();
ViewTreeObserver obs = getViewTreeObserver();
obs.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
needLayout();
if (Build.VERSION.SDK_INT < 16) {
contentView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
contentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
public void needLayout() {
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager manager = (WindowManager)parentActivity.getSystemService(Context.WINDOW_SERVICE);
int rotation = manager.getDefaultDisplay().getRotation();
int height = 0;
if (actionBar.getVisibility() == View.VISIBLE) {
if (!Utilities.isTablet(this) && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
height = AndroidUtilities.dp(40);
} else {
height = AndroidUtilities.dp(48);
......@@ -475,7 +474,7 @@ public class ActionBarActivity extends Activity {
fragment.onPause();
if (removeLast) {
fragment.onFragmentDestroy();
fragment.setParentActivity(null);
fragment.setParentLayout(null);
fragmentsStack.remove(fragment);
} else {
if (fragment.fragmentView != null) {
......@@ -497,18 +496,21 @@ public class ActionBarActivity extends Activity {
}
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation) {
if (checkTransitionAnimation() || !fragment.onFragmentCreate()) {
if (checkTransitionAnimation() || delegate != null && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) {
return false;
}
if (getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(getCurrentFocus());
if (parentActivity.getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
}
boolean needAnimation = openAnimation != null && !forceWithoutAnimation && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
if (useAlphaAnimations && fragmentsStack.size() == 0 && alphaOpenAnimation == null) {
needAnimation = false;
}
boolean needAnimation = openAnimation != null && !forceWithoutAnimation && getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
final BaseFragment currentFragment = !fragmentsStack.isEmpty() ? fragmentsStack.get(fragmentsStack.size() - 1) : null;
fragment.setParentActivity(this);
View fragmentView = fragment.createView(getLayoutInflater(), null);
fragment.setParentLayout(this);
View fragmentView = fragment.createView(parentActivity.getLayoutInflater(), null);
containerViewBack.addView(fragmentView);
ViewGroup.LayoutParams layoutParams = fragmentView.getLayoutParams();
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
......@@ -534,6 +536,14 @@ public class ActionBarActivity extends Activity {
}
if (needAnimation) {
if (useAlphaAnimations && fragmentsStack.size() == 1) {
presentFragmentInternalRemoveOld(removeLast, currentFragment);
startAnimation(alphaOpenAnimation);
if (backgroundView != null) {
backgroundView.setVisibility(VISIBLE);
backgroundView.startAnimation(alphaOpenAnimation2);
}
} else {
transitionAnimationStartTime = System.currentTimeMillis();
transitionAnimationInProgress = true;
onOpenAnimationEndRunnable = new Runnable() {
......@@ -545,6 +555,7 @@ public class ActionBarActivity extends Activity {
};
openAnimation.reset();
containerView.startAnimation(openAnimation);
}
} else {
fragment.onOpenAnimationEnd();
}
......@@ -552,10 +563,10 @@ public class ActionBarActivity extends Activity {
}
public boolean addFragmentToStack(BaseFragment fragment) {
if (!fragment.onFragmentCreate()) {
if (delegate != null && !delegate.needAddFragmentToStack(fragment, this) || !fragment.onFragmentCreate()) {
return false;
}
fragment.setParentActivity(this);
fragment.setParentLayout(this);
fragmentsStack.add(fragment);
return true;
}
......@@ -563,7 +574,7 @@ public class ActionBarActivity extends Activity {
private void closeLastFragmentInternalRemoveOld(BaseFragment fragment) {
fragment.onPause();
fragment.onFragmentDestroy();
fragment.setParentActivity(null);
fragment.setParentLayout(null);
fragmentsStack.remove(fragment);
containerViewBack.setVisibility(View.GONE);
ViewGroup parent = (ViewGroup)containerView.getParent();
......@@ -572,23 +583,30 @@ public class ActionBarActivity extends Activity {
}
public void closeLastFragment(boolean animated) {
if (fragmentsStack.size() <= 1 || checkTransitionAnimation()) {
if (delegate != null && !delegate.needCloseLastFragment(this) || checkTransitionAnimation()) {
return;
}
if (getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(getCurrentFocus());
if (parentActivity.getCurrentFocus() != null) {
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
}
boolean needAnimation = animated && closeAnimation != null && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
if (useAlphaAnimations && fragmentsStack.size() == 1 && alphaCloseAnimation == null) {
needAnimation = false;
}
boolean needAnimation = animated && closeAnimation != null && getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
final BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1);
BaseFragment previousFragment = fragmentsStack.get(fragmentsStack.size() - 2);
BaseFragment previousFragment = null;
if (fragmentsStack.size() > 1) {
previousFragment = fragmentsStack.get(fragmentsStack.size() - 2);
}
if (previousFragment != null) {
FrameLayoutAnimationListener temp = containerView;
containerView = containerViewBack;
containerViewBack = temp;
containerView.setVisibility(View.VISIBLE);
previousFragment.setParentActivity(this);
View fragmentView = previousFragment.createView(getLayoutInflater(), null);
previousFragment.setParentLayout(this);
View fragmentView = previousFragment.createView(parentActivity.getLayoutInflater(), null);
containerView.addView(fragmentView);
ViewGroup.LayoutParams layoutParams = fragmentView.getLayoutParams();
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
......@@ -616,6 +634,34 @@ public class ActionBarActivity extends Activity {
};
containerViewBack.startAnimation(closeAnimation);
}
} else {
if (needAnimation && useAlphaAnimations) {
transitionAnimationStartTime = System.currentTimeMillis();
transitionAnimationInProgress = true;
alphaCloseAnimation.reset();
alphaCloseAnimation2.reset();
startAnimation(alphaCloseAnimation);
if (backgroundView != null) {
backgroundView.startAnimation(alphaCloseAnimation2);
}
onCloseAnimationEndRunnable = new Runnable() {
@Override
public void run() {
removeFragmentFromStack(currentFragment);
setVisibility(GONE);
if (backgroundView != null) {
backgroundView.setVisibility(GONE);
}
}
};
} else {
removeFragmentFromStack(currentFragment);
setVisibility(GONE);
if (backgroundView != null) {
backgroundView.setVisibility(GONE);
}
}
}
}
public void showLastFragment() {
......@@ -623,8 +669,8 @@ public class ActionBarActivity extends Activity {
return;
}
BaseFragment previousFragment = fragmentsStack.get(fragmentsStack.size() - 1);
previousFragment.setParentActivity(this);
View fragmentView = previousFragment.createView(getLayoutInflater(), null);
previousFragment.setParentLayout(this);
View fragmentView = previousFragment.createView(parentActivity.getLayoutInflater(), null);
containerView.addView(fragmentView);
ViewGroup.LayoutParams layoutParams = fragmentView.getLayoutParams();
layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT;
......@@ -640,19 +686,25 @@ public class ActionBarActivity extends Activity {
public void removeFragmentFromStack(BaseFragment fragment) {
fragment.onPause();
fragment.onFragmentDestroy();
fragment.setParentActivity(null);
fragment.setParentLayout(null);
fragmentsStack.remove(fragment);
}
public void rebuildAllFragmentViews() {
for (int a = 0; a < fragmentsStack.size() - 1; a++) {
fragmentsStack.get(a).setParentActivity(null);
fragmentsStack.get(a).setParentActivity(this);
public void removeAllFragments() {
for (int a = 0; a < fragmentsStack.size(); a++) {
removeFragmentFromStack(fragmentsStack.get(a));
a--;
}
}
protected void onFinish() {
public void rebuildAllFragmentViews(boolean last) {
for (int a = 0; a < fragmentsStack.size() - (last ? 0 : 1); a++) {
fragmentsStack.get(a).setParentLayout(null);
fragmentsStack.get(a).setParentLayout(this);
}
if (delegate != null) {
delegate.onRebuildAllFragments(this);
}
}
public void showActionBar() {
......@@ -672,28 +724,22 @@ public class ActionBarActivity extends Activity {
return super.onKeyUp(keyCode, event);
}
public void onOverlayShow(View view, BaseFragment fragment) {
protected void onOverlayShow(View view, BaseFragment fragment) {
if (delegate != null) {
delegate.onOverlayShow(view, fragment);
}
}
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
hideActionBar();
inActionMode = true;
}
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
showActionBar();
inActionMode = false;
}
public boolean onPreIme() {
return false;
}
private void onCloseAnimationEnd(boolean post) {
if (transitionAnimationInProgress && onCloseAnimationEndRunnable != null) {
transitionAnimationInProgress = false;
......@@ -730,12 +776,6 @@ public class ActionBarActivity extends Activity {
}
}
private void onAnimationEnd() {
onCloseAnimationEnd(false);
onOpenAnimationEnd(false);
}
@Override
public void startActivityForResult(final Intent intent, final int requestCode) {
if (transitionAnimationInProgress) {
if (onCloseAnimationEndRunnable != null) {
......@@ -747,12 +787,26 @@ public class ActionBarActivity extends Activity {
}
containerView.invalidate();
if (intent != null) {
super.startActivityForResult(intent, requestCode);
parentActivity.startActivityForResult(intent, requestCode);
}
} else {
if (intent != null) {
super.startActivityForResult(intent, requestCode);
parentActivity.startActivityForResult(intent, requestCode);
}
}
}
public void setUseAlphaAnimations(boolean value) {
useAlphaAnimations = value;
if (useAlphaAnimations) {
alphaOpenAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.icon_anim_fade_in);
alphaOpenAnimation2 = AnimationUtils.loadAnimation(getContext(), R.anim.icon_anim_fade_in);
alphaCloseAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.icon_anim_fade_out);
alphaCloseAnimation2 = AnimationUtils.loadAnimation(getContext(), R.anim.icon_anim_fade_out);
}
}
public void setBackgroundView(View view) {
backgroundView = view;
}
}
......@@ -61,7 +61,11 @@ public class ActionBarMenu extends LinearLayout {
}
public ActionBarMenuItem addItem(int id, int icon) {
ActionBarMenuItem menuItem = new ActionBarMenuItem(getContext(), this, parentActionBar, parentActionBarLayer.itemsBackgroundResourceId);
return addItem(id, icon, parentActionBarLayer.itemsBackgroundResourceId);
}
public ActionBarMenuItem addItem(int id, int icon, int backgroundResource) {
ActionBarMenuItem menuItem = new ActionBarMenuItem(getContext(), this, parentActionBar, backgroundResource);
menuItem.setTag(id);
menuItem.setScaleType(ImageView.ScaleType.CENTER);
menuItem.setImageResource(icon);
......
......@@ -14,8 +14,12 @@ import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
......@@ -28,7 +32,6 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import java.lang.reflect.Field;
......@@ -257,6 +260,30 @@ public class ActionBarMenuItem extends ImageView {
searchField.setBackgroundResource(R.drawable.search_light_states);
searchField.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0);
searchField.setInputType(EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
if (android.os.Build.VERSION.SDK_INT < 11) {
searchField.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.clear();
}
});
} else {
searchField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
}
searchField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
......
......@@ -8,6 +8,7 @@
package org.telegram.ui.Views.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
......@@ -23,7 +24,7 @@ import org.telegram.messenger.R;
public class BaseFragment {
private boolean isFinished = false;
protected View fragmentView;
private ActionBarActivity parentActivity;
protected ActionBarLayout parentLayout;
protected ActionBarLayer actionBarLayer;
protected int classGuid = 0;
protected Bundle arguments;
......@@ -47,9 +48,9 @@ public class BaseFragment {
return arguments;
}
public void setParentActivity(ActionBarActivity activity) {
if (parentActivity != activity) {
parentActivity = activity;
public void setParentLayout(ActionBarLayout layout) {
if (parentLayout != layout) {
parentLayout = layout;
if (fragmentView != null) {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
......@@ -57,11 +58,11 @@ public class BaseFragment {
}
fragmentView = null;
}
if (parentActivity != null) {
if (parentLayout != null) {
if (actionBarLayer != null) {
actionBarLayer.onDestroy();
}
actionBarLayer = parentActivity.getInternalActionBar().createLayer();
actionBarLayer = parentLayout.getInternalActionBar().createLayer();
actionBarLayer.parentFragment = this;
actionBarLayer.setBackgroundResource(R.color.header);
actionBarLayer.setItemsBackground(R.drawable.bar_selector);
......@@ -74,17 +75,17 @@ public class BaseFragment {
}
public void finishFragment(boolean animated) {
if (isFinished || parentActivity == null) {
if (isFinished || parentLayout == null) {
return;
}
parentActivity.closeLastFragment(animated);
parentLayout.closeLastFragment(animated);
}
public void removeSelfFromStack() {
if (isFinished || parentActivity == null) {
if (isFinished || parentLayout == null) {
return;
}
parentActivity.removeFragmentFromStack(this);
parentLayout.removeFragmentFromStack(this);
}
public boolean onFragmentCreate() {
......@@ -139,39 +140,39 @@ public class BaseFragment {
}
public void presentFragment(BaseFragment fragment) {
if (parentActivity == null) {
if (parentLayout == null) {
return;
}
parentActivity.presentFragment(fragment);
parentLayout.presentFragment(fragment);
}
public void presentFragment(BaseFragment fragment, boolean removeLast) {
if (parentActivity == null) {
if (parentLayout == null) {
return;
}
parentActivity.presentFragment(fragment, removeLast);
parentLayout.presentFragment(fragment, removeLast);
}
public void presentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation) {
if (parentActivity == null) {
if (parentLayout == null) {
return;
}
parentActivity.presentFragment(fragment, removeLast, forceWithoutAnimation);
parentLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
}
public ActionBarActivity getParentActivity() {
return parentActivity;
public Activity getParentActivity() {
return parentLayout.parentActivity;
}
public void showActionBar() {
if (parentActivity != null) {
parentActivity.showActionBar();
if (parentLayout != null) {
parentLayout.showActionBar();
}
}
public void hideActionBar() {
if (parentActivity != null) {
parentActivity.hideActionBar();
if (parentLayout != null) {
parentLayout.hideActionBar();
}
}
......@@ -198,7 +199,7 @@ public class BaseFragment {
}
protected void showAlertDialog(AlertDialog.Builder builder) {
if (parentActivity == null || parentActivity.checkTransitionAnimation() || parentActivity.animationInProgress || parentActivity.startedTracking) {
if (parentLayout == null || parentLayout.checkTransitionAnimation() || parentLayout.animationInProgress || parentLayout.startedTracking) {
return;
}
try {
......
......@@ -451,7 +451,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
}
emojiPopup.setHeight(View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY));
if (sizeNotifierRelativeLayout != null) {
emojiPopup.setWidth(View.MeasureSpec.makeMeasureSpec(sizeNotifierRelativeLayout.getWidth(), View.MeasureSpec.EXACTLY));
emojiPopup.setWidth(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY));
}
emojiPopup.showAtLocation(parentActivity.getWindow().getDecorView(), 83, 0, 0);
......@@ -585,7 +585,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
if (emojiPopup != null && emojiPopup.isShowing()) {
WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
final WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams)emojiPopup.getContentView().getLayoutParams();
layoutParams.width = sizeNotifierRelativeLayout.getWidth();
layoutParams.width = AndroidUtilities.displaySize.x;
if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
layoutParams.height = keyboardHeightLand;
} else {
......
......@@ -104,7 +104,11 @@ public class EmojiView extends LinearLayout {
setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < Emoji.data.length; i++) {
GridView gridView = new GridView(getContext());
gridView.setColumnWidth(AndroidUtilities.dpf(45.0f));
if (AndroidUtilities.isTablet()) {
gridView.setColumnWidth(AndroidUtilities.dp(60));
} else {
gridView.setColumnWidth(AndroidUtilities.dp(45));
}
gridView.setNumColumns(-1);
views.add(gridView);
......@@ -122,7 +126,7 @@ public class EmojiView extends LinearLayout {
tabs.setIndicatorColor(0xff33b5e5);
tabs.setIndicatorHeight(AndroidUtilities.dpf(2.0f));
tabs.setUnderlineHeight(AndroidUtilities.dpf(2.0f));
tabs.setUnderlineColor(1711276032);
tabs.setUnderlineColor(0x66000000);
tabs.setTabBackground(0);
LinearLayout localLinearLayout = new LinearLayout(getContext());
localLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
......@@ -138,7 +142,7 @@ public class EmojiView extends LinearLayout {
}
}
});
localLinearLayout.addView(localImageView, new LinearLayout.LayoutParams(AndroidUtilities.dpf(61.0f), LayoutParams.MATCH_PARENT));
localLinearLayout.addView(localImageView, new LinearLayout.LayoutParams(AndroidUtilities.dp(61), LayoutParams.MATCH_PARENT));
recentsWrap = new FrameLayout(getContext());
recentsWrap.addView(views.get(0));
TextView localTextView = new TextView(getContext());
......
/*
* This is the source code of Telegram for Android v. 1.7.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2014.
*/
package org.telegram.ui.Views;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import org.telegram.android.AndroidUtilities;
public class RoundProgressView {
private Paint paint;
public float currentProgress = 0;
public RectF rect = new RectF();
public RoundProgressView() {
paint = new Paint();
paint.setColor(0xffffffff);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(AndroidUtilities.dp(2));
paint.setAntiAlias(true);
}
public void setColor(int color) {
paint.setColor(color);
}
public void setProgress(float progress) {
currentProgress = progress;
if (currentProgress < 0) {
currentProgress = 0;
} else if (currentProgress > 1) {
currentProgress = 1;
}
}
public void draw(Canvas canvas) {
canvas.drawArc(rect, -90, 360 * currentProgress, false, paint);
}
}
......@@ -65,13 +65,13 @@ public class SizeNotifierRelativeLayout extends RelativeLayout {
@Override
protected void onDraw(Canvas canvas) {
if (backgroundDrawable != null) {
float scaleX = (float)AndroidUtilities.displaySize.x / (float)backgroundDrawable.getIntrinsicWidth();
float scaleY = (float)AndroidUtilities.displaySize.y / (float)backgroundDrawable.getIntrinsicHeight();
float scaleX = (float)getMeasuredWidth() / (float)backgroundDrawable.getIntrinsicWidth();
float scaleY = (float)getMeasuredHeight() / (float)backgroundDrawable.getIntrinsicHeight();
float scale = scaleX < scaleY ? scaleY : scaleX;
int width = (int)Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale);
int height = (int)Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale);
int x = (AndroidUtilities.displaySize.x - width) / 2;
int y = (AndroidUtilities.displaySize.y - height) / 2;
int x = (getMeasuredWidth() - width) / 2;
int y = (getMeasuredHeight() - height) / 2;
backgroundDrawable.setBounds(x, y, x + width, y + height);
backgroundDrawable.draw(canvas);
} else {
......
/*
* This is the source code of Telegram for Android v. 1.7.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2014.
*/
package org.telegram.ui.Views;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.view.animation.DecelerateInterpolator;
import org.telegram.android.AndroidUtilities;
public class TypingDotsDrawable extends Drawable {
private boolean isChat = false;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float[] scales = new float[3];
private float[] startTimes = new float[] {0, 150, 300};
private float[] elapsedTimes = new float[] {0, 0, 0};
private long lastUpdateTime = 0;
private boolean started = false;
private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
public TypingDotsDrawable() {
super();
paint.setColor(0xffd7e8f7);
}
public void setIsChat(boolean value) {
isChat = value;
}
private void update() {
long newTime = System.currentTimeMillis();
long dt = newTime - lastUpdateTime;
lastUpdateTime = newTime;
for (int a = 0; a < 3; a++) {
elapsedTimes[a] += dt;
float timeSinceStart = elapsedTimes[a] - startTimes[a];
if (timeSinceStart > 0) {
if (timeSinceStart <= 320) {
float diff = decelerateInterpolator.getInterpolation(timeSinceStart / 320.0f);
scales[a] = 1.33f + diff;
} else if (timeSinceStart <= 640) {
float diff = decelerateInterpolator.getInterpolation((timeSinceStart - 320.0f) / 320.0f);
scales[a] = 1.33f + (1 - diff);
} else if (timeSinceStart >= 800) {
elapsedTimes[a] = 0;
startTimes[a] = 0;
scales[a] = 1.33f;
} else {
scales[a] = 1.33f;
}
} else {
scales[a] = 1.33f;
}
}
invalidateSelf();
}
public void start() {
lastUpdateTime = System.currentTimeMillis();
started = true;
invalidateSelf();
}
public void stop() {
for (int a = 0; a < 3; a++) {
elapsedTimes[a] = 0;
scales[a] = 1.33f;
}
startTimes[0] = 0;
startTimes[1] = 150;
startTimes[2] = 300;
started = false;
}
@Override
public void draw(Canvas canvas) {
int y = 0;
if (isChat) {
y = AndroidUtilities.dp(6);
} else {
y = AndroidUtilities.dp(7);
}
canvas.drawCircle(AndroidUtilities.dp(3), y, scales[0] * AndroidUtilities.density, paint);
canvas.drawCircle(AndroidUtilities.dp(9), y, scales[1] * AndroidUtilities.density, paint);
canvas.drawCircle(AndroidUtilities.dp(15), y, scales[2] * AndroidUtilities.density, paint);
if (started) {
update();
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return 0;
}
@Override
public int getIntrinsicWidth() {
return AndroidUtilities.dp(18);
}
@Override
public int getIntrinsicHeight() {
return AndroidUtilities.dp(10);
}
}
......@@ -22,7 +22,6 @@ import org.telegram.messenger.R;
public class VideoSeekBarView extends View {
private static Drawable thumbDrawable1;
private static Drawable thumbDrawablePressed1;
private static Paint innerPaint1 = new Paint();
private static int thumbWidth;
private static int thumbHeight;
......@@ -37,8 +36,7 @@ public class VideoSeekBarView extends View {
private void init(Context context) {
if (thumbDrawable1 == null) {
thumbDrawable1 = context.getResources().getDrawable(R.drawable.playback);
thumbDrawablePressed1 = context.getResources().getDrawable(R.drawable.playback_active);
thumbDrawable1 = context.getResources().getDrawable(R.drawable.videolapse);
innerPaint1.setColor(0x99999999);
thumbWidth = thumbDrawable1.getIntrinsicWidth();
thumbHeight = thumbDrawable1.getIntrinsicHeight();
......@@ -118,16 +116,10 @@ public class VideoSeekBarView extends View {
@Override
protected void onDraw(Canvas canvas) {
Drawable thumb = null;
if (!pressed) {
thumb = thumbDrawable1;
} else {
thumb = thumbDrawablePressed1;
}
int y = (getMeasuredHeight() - thumbHeight) / 2;
int thumbX = (int)((getMeasuredWidth() - thumbWidth) * progress);
canvas.drawRect(thumbWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), getMeasuredWidth() - thumbWidth / 2, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), innerPaint1);
thumb.setBounds(thumbX, y, thumbX + thumbWidth, y + thumbHeight);
thumb.draw(canvas);
thumbDrawable1.setBounds(thumbX, y, thumbX + thumbWidth, y + thumbHeight);
thumbDrawable1.draw(canvas);
}
}
......@@ -14,6 +14,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.os.AsyncTask;
import android.util.AttributeSet;
......@@ -22,6 +23,7 @@ import android.view.View;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import java.util.ArrayList;
......@@ -44,32 +46,34 @@ public class VideoTimelineView extends View {
private int frameWidth = 0;
private int frameHeight = 0;
private int framesToLoad = 0;
private Drawable pickDrawable = null;
public abstract interface VideoTimelineViewDelegate {
public void onLeftProgressChanged(float progress);
public void onRifhtProgressChanged(float progress);
}
private void init() {
private void init(Context context) {
paint = new Paint();
paint.setColor(0xff66d1ee);
paint2 = new Paint();
paint2.setColor(0x2266d1ee);
paint2.setColor(0x7f000000);
pickDrawable = getResources().getDrawable(R.drawable.videotrimmer);
}
public VideoTimelineView(Context context) {
super(context);
init();
init(context);
}
public VideoTimelineView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
init(context);
}
public VideoTimelineView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
init(context);
}
public float getLeftProgress() {
......@@ -88,9 +92,9 @@ public class VideoTimelineView extends View {
float x = event.getX();
float y = event.getY();
int width = getMeasuredWidth() - AndroidUtilities.dp(12);
int startX = (int)(width * progressLeft) + AndroidUtilities.dp(3);
int endX = (int)(width * progressRight) + AndroidUtilities.dp(9);
int width = getMeasuredWidth() - AndroidUtilities.dp(32);
int startX = (int)(width * progressLeft) + AndroidUtilities.dp(16);
int endX = (int)(width * progressRight) + AndroidUtilities.dp(16);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int additionWidth = AndroidUtilities.dp(12);
......@@ -118,12 +122,12 @@ public class VideoTimelineView extends View {
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (pressedLeft) {
startX = (int)(x - pressDx);
if (startX < AndroidUtilities.dp(3)) {
startX = AndroidUtilities.dp(3);
} else if (startX > endX - AndroidUtilities.dp(6)) {
startX = endX - AndroidUtilities.dp(6);
if (startX < AndroidUtilities.dp(16)) {
startX = AndroidUtilities.dp(16);
} else if (startX > endX) {
startX = endX;
}
progressLeft = (float)(startX - AndroidUtilities.dp(3)) / (float)width;
progressLeft = (float)(startX - AndroidUtilities.dp(16)) / (float)width;
if (delegate != null) {
delegate.onLeftProgressChanged(progressLeft);
}
......@@ -131,12 +135,12 @@ public class VideoTimelineView extends View {
return true;
} else if (pressedRight) {
endX = (int)(x - pressDx);
if (endX < startX + AndroidUtilities.dp(6)) {
endX = startX + AndroidUtilities.dp(6);
} else if (endX > width + AndroidUtilities.dp(9)) {
endX = width + AndroidUtilities.dp(9);
if (endX < startX) {
endX = startX;
} else if (endX > width + AndroidUtilities.dp(16)) {
endX = width + AndroidUtilities.dp(16);
}
progressRight = (float)(endX - AndroidUtilities.dp(9)) / (float)width;
progressRight = (float)(endX - AndroidUtilities.dp(16)) / (float)width;
if (delegate != null) {
delegate.onRifhtProgressChanged(progressRight);
}
......@@ -163,9 +167,9 @@ public class VideoTimelineView extends View {
return;
}
if (frameNum == 0) {
frameHeight = getMeasuredHeight() - AndroidUtilities.dp(4);
framesToLoad = getMeasuredWidth() / frameHeight;
frameWidth = (int)Math.ceil((float)getMeasuredWidth() / (float)framesToLoad);
frameHeight = AndroidUtilities.dp(40);
framesToLoad = (getMeasuredWidth() - AndroidUtilities.dp(16)) / frameHeight;
frameWidth = (int)Math.ceil((float)(getMeasuredWidth() - AndroidUtilities.dp(16)) / (float)framesToLoad);
frameTimeOffset = videoLength / framesToLoad;
}
currentTask = new AsyncTask<Integer, Integer, Bitmap>() {
......@@ -262,24 +266,39 @@ public class VideoTimelineView extends View {
@Override
protected void onDraw(Canvas canvas) {
int width = getMeasuredWidth() - AndroidUtilities.dp(36);
int startX = (int)(width * progressLeft) + AndroidUtilities.dp(16);
int endX = (int)(width * progressRight) + AndroidUtilities.dp(16);
canvas.save();
canvas.clipRect(AndroidUtilities.dp(16), 0, width + AndroidUtilities.dp(20), AndroidUtilities.dp(44));
if (frames.isEmpty() && currentTask == null) {
reloadFrames(0);
} else {
int offset = 0;
for (Bitmap bitmap : frames) {
if (bitmap != null) {
canvas.drawBitmap(bitmap, offset * frameWidth, AndroidUtilities.dp(2), null);
canvas.drawBitmap(bitmap, AndroidUtilities.dp(16) + offset * frameWidth, AndroidUtilities.dp(2), null);
}
offset++;
}
}
int width = getMeasuredWidth() - AndroidUtilities.dp(12);
int startX = (int)(width * progressLeft);
int endX = (int)(width * progressRight);
canvas.drawRect(startX, 0, startX + AndroidUtilities.dp(6), getMeasuredHeight(), paint);
canvas.drawRect(endX + AndroidUtilities.dp(6), 0, endX + AndroidUtilities.dp(12), getMeasuredHeight(), paint);
canvas.drawRect(startX + AndroidUtilities.dp(6), AndroidUtilities.dp(4), endX + AndroidUtilities.dp(6), getMeasuredHeight() - AndroidUtilities.dp(4), paint2);
canvas.drawRect(startX + AndroidUtilities.dp(6), AndroidUtilities.dp(2), endX + AndroidUtilities.dp(6), AndroidUtilities.dp(4), paint);
canvas.drawRect(startX + AndroidUtilities.dp(6), getMeasuredHeight() - AndroidUtilities.dp(4), endX + AndroidUtilities.dp(6), getMeasuredHeight() - AndroidUtilities.dp(2), paint);
canvas.drawRect(AndroidUtilities.dp(16), AndroidUtilities.dp(2), startX, AndroidUtilities.dp(42), paint2);
canvas.drawRect(endX + AndroidUtilities.dp(4), AndroidUtilities.dp(2), AndroidUtilities.dp(16) + width + AndroidUtilities.dp(4), AndroidUtilities.dp(42), paint2);
canvas.drawRect(startX, 0, startX + AndroidUtilities.dp(2), AndroidUtilities.dp(44), paint);
canvas.drawRect(endX + AndroidUtilities.dp(2), 0, endX + AndroidUtilities.dp(4), AndroidUtilities.dp(44), paint);
canvas.drawRect(startX + AndroidUtilities.dp(2), 0, endX + AndroidUtilities.dp(4), AndroidUtilities.dp(2), paint);
canvas.drawRect(startX + AndroidUtilities.dp(2), AndroidUtilities.dp(42), endX + AndroidUtilities.dp(4), AndroidUtilities.dp(44), paint);
canvas.restore();
int drawableWidth = pickDrawable.getIntrinsicWidth();
int drawableHeight = pickDrawable.getIntrinsicHeight();
pickDrawable.setBounds(startX - drawableWidth / 2, getMeasuredHeight() - drawableHeight, startX + drawableWidth / 2, getMeasuredHeight());
pickDrawable.draw(canvas);
pickDrawable.setBounds(endX - drawableWidth / 2 + AndroidUtilities.dp(4), getMeasuredHeight() - drawableHeight, endX + drawableWidth / 2 + AndroidUtilities.dp(4), getMeasuredHeight());
pickDrawable.draw(canvas);
}
}
......@@ -2,17 +2,17 @@
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#40a0bcdd" />
<solid android:color="#ff45658d" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#40a0bcdd" />
<solid android:color="#ff45658d" />
</shape>
</item>
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="#40a0bcdd" />
<solid android:color="#ff45658d" />
</shape>
</item>
<item android:drawable="@drawable/transparent" />
......
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<inset android:insetBottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#fff0f0f0" />
</shape>
</inset>
</item>
<item android:state_focused="true">
<inset android:insetBottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#fff0f0f0" />
</shape>
</inset>
</item>
<item android:state_selected="true">
<inset android:insetBottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#fff0f0f0" />
</shape>
</inset>
</item>
<item android:drawable="@drawable/transparent" />
</selector>
\ No newline at end of file
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#f2f5f7" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#f2f5f7" />
</shape>
</item>
<item android:state_selected="true">
<shape android:shape="rectangle">
<solid android:color="#f2f5f7" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#ffffffff" />
</shape>
</item>
</selector>
\ No newline at end of file
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ab_progress"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
\ No newline at end of file
<inset
xmlns:android="http://schemas.android.com/apk/res/android">
<shape android:shape="rectangle">
<solid android:color="@color/divider"/>
</shape>
</inset>
\ No newline at end of file
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="@drawable/typing_dot_frame0" android:duration="120" />
<item android:drawable="@drawable/typing_dot_frame1" android:duration="120" />
<item android:drawable="@drawable/typing_dot_frame2" android:duration="120" />
<item android:drawable="@drawable/typing_dot_frame3" android:duration="120" />
<item android:drawable="@drawable/typing_dot_frame0" android:duration="120" />
</animation-list>
\ No newline at end of file
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="@drawable/typing_dot_chat_frame0" android:duration="120" />
<item android:drawable="@drawable/typing_dot_chat_frame1" android:duration="120" />
<item android:drawable="@drawable/typing_dot_chat_frame2" android:duration="120" />
<item android:drawable="@drawable/typing_dot_chat_frame3" android:duration="120" />
<item android:drawable="@drawable/typing_dot_chat_frame0" android:duration="120" />
</animation-list>
\ No newline at end of file
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/cats"
android:scaleType="centerCrop"/>
<FrameLayout
android:layout_width="498dp"
android:layout_height="528dp"
android:layout_gravity="center"
android:background="@drawable/btnshadow">
<include layout="@layout/intro_layout"/>
</FrameLayout>
</FrameLayout>
\ No newline at end of file
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/launch_layout">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/cats"
android:scaleType="centerCrop"
android:id="@+id/launch_background"/>
<LinearLayout
android:layout_width="320dp"
android:layout_height="wrap_content"
android:id="@+id/launch_button_layout"
android:layout_centerVertical="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="308dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/btnshadow"
android:layout_gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/new_group_button"
android:textColor="#ff54759e"
android:gravity="center_vertical"
android:textSize="20dp"
android:paddingLeft="17dp"
android:paddingStart="17dp"
android:paddingEnd="17dp"
android:background="@drawable/launch_button_states"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#ffd6dee4"/>
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/new_secret_button"
android:textColor="#ff54759e"
android:gravity="center_vertical"
android:textSize="20dp"
android:paddingLeft="17dp"
android:paddingStart="17dp"
android:paddingEnd="17dp"
android:background="@drawable/launch_button_states"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#ffd6dee4"/>
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/new_broadcast_button"
android:textColor="#ff54759e"
android:gravity="center_vertical"
android:textSize="20dp"
android:paddingLeft="17dp"
android:paddingStart="17dp"
android:paddingEnd="17dp"
android:background="@drawable/launch_button_states"/>
</LinearLayout>
<LinearLayout
android:layout_width="308dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/btnshadow"
android:layout_gravity="center"
android:layout_marginTop="18dp">
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/contacts_button"
android:textColor="#ff54759e"
android:gravity="center_vertical"
android:textSize="20dp"
android:paddingLeft="17dp"
android:paddingStart="17dp"
android:paddingEnd="17dp"
android:background="@drawable/launch_button_states"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#ffd6dee4"/>
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/settings_button"
android:textColor="#ff54759e"
android:gravity="center_vertical"
android:textSize="20dp"
android:paddingLeft="17dp"
android:paddingStart="17dp"
android:paddingEnd="17dp"
android:background="@drawable/launch_button_states"/>
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="1dp"
android:background="#40295274"
android:id="@+id/shadow_tablet_side"/>
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/shadow_tablet"
android:background="#7F000000"
android:visibility="gone"/>
</RelativeLayout>
\ No newline at end of file
......@@ -6,17 +6,6 @@
android:id="@+id/back_button_background"
android:layout_gravity="top">
<ProgressBar
android:layout_height="32dp"
android:layout_width="32dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/loading_header_animation"
android:indeterminateBehavior="repeat"
android:indeterminateDuration="1200"
android:indeterminateOnly="true"
android:layout_gravity="center_vertical|left"
android:layout_marginLeft="12dp"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
......@@ -28,7 +17,7 @@
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="52dp"
android:layout_marginLeft="16dp"
android:textColor="#ffffff"
android:textSize="17dp"
android:layout_gravity="center_vertical|left"
......
......@@ -12,7 +12,7 @@
android:id="@+id/video_container"
android:layout_gravity="top">
<SurfaceView
<TextureView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
......@@ -26,44 +26,75 @@
android:layout_gravity="center"
android:id="@+id/play_button"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/control_layout">
<org.telegram.ui.Views.VideoSeekBarView
android:layout_height="36dp"
android:layout_width="match_parent"
android:id="@+id/video_seekbar"
android:background="#77000000"
android:layout_gravity="bottom"/>
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"/>
<org.telegram.ui.Views.VideoTimelineView
android:layout_width="match_parent"
android:layout_height="74dp"
android:layout_marginTop="36dp"
android:id="@+id/video_timeline_view"/>
</FrameLayout>
<FrameLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="143dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:id="@+id/info_container">
android:background="#ff2d2d2d"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:id="@+id/info_container"
android:orientation="vertical">
<org.telegram.ui.Views.VideoTimelineView
android:layout_width="match_parent"
android:layout_height="45dp"
android:id="@+id/video_timeline_view"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#f0f0f0"
android:textSize="15dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="13dp"
android:id="@+id/original_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textSize="16dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="66dp"
android:textColor="#bebebe"
android:textSize="15dp"
android:layout_marginLeft="13dp"
android:id="@+id/original_size"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textSize="16dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="38dp"
android:textColor="#f0f0f0"
android:textSize="15dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="13dp"
android:id="@+id/edited_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#bebebe"
android:textSize="15dp"
android:layout_marginLeft="13dp"
android:layout_marginBottom="8dp"
android:id="@+id/edited_size"/>
</FrameLayout>
</LinearLayout>
</FrameLayout>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment