Commit f7d3faab authored by DrKLO's avatar DrKLO

Service for video encoding, update locales, bug fixes

parent f83a1b56
...@@ -80,7 +80,7 @@ android { ...@@ -80,7 +80,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 8 minSdkVersion 8
targetSdkVersion 19 targetSdkVersion 19
versionCode 332 versionCode 335
versionName "1.9.0" versionName "1.9.0"
} }
} }
...@@ -138,6 +138,7 @@ ...@@ -138,6 +138,7 @@
<service android:name="org.telegram.android.NotificationsService" android:enabled="true"/> <service android:name="org.telegram.android.NotificationsService" android:enabled="true"/>
<service android:name="org.telegram.android.NotificationRepeat" android:exported="false"/> <service android:name="org.telegram.android.NotificationRepeat" android:exported="false"/>
<service android:name="org.telegram.android.VideoEncodingService" android:enabled="true"/>
<receiver android:name="org.telegram.android.AppStartReceiver" android:enabled="true"> <receiver android:name="org.telegram.android.AppStartReceiver" android:enabled="true">
<intent-filter> <intent-filter>
......
...@@ -41,8 +41,8 @@ public class AndroidUtilities { ...@@ -41,8 +41,8 @@ public class AndroidUtilities {
public static int statusBarHeight = 0; public static int statusBarHeight = 0;
public static float density = 1; public static float density = 1;
public static Point displaySize = new Point(); public static Point displaySize = new Point();
public static Integer photoSize = null;
private static Boolean isTablet = null; private static Boolean isTablet = null;
private static Boolean isSmallTablet = null;
public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002}; public static int[] arrColors = {0xffee4928, 0xff41a903, 0xffe09602, 0xff0f94ed, 0xff8f3bf7, 0xfffc4380, 0xff00a1c4, 0xffeb7002};
public static int[] arrUsersAvatars = { public static int[] arrUsersAvatars = {
...@@ -277,11 +277,8 @@ public class AndroidUtilities { ...@@ -277,11 +277,8 @@ public class AndroidUtilities {
} }
public static boolean isSmallTablet() { public static boolean isSmallTablet() {
if (isSmallTablet == null) {
float minSide = Math.min(displaySize.x, displaySize.y) / density; float minSide = Math.min(displaySize.x, displaySize.y) / density;
isSmallTablet = minSide <= 700; return minSide <= 700;
}
return isSmallTablet;
} }
public static int getMinTabletSide() { public static int getMinTabletSide() {
...@@ -354,4 +351,15 @@ public class AndroidUtilities { ...@@ -354,4 +351,15 @@ public class AndroidUtilities {
public static int getBroadcastAvatarForId(int id) { public static int getBroadcastAvatarForId(int id) {
return arrBroadcastAvatars[getColorIndex(-Math.abs(id))]; return arrBroadcastAvatars[getColorIndex(-Math.abs(id))];
} }
public static int getPhotoSize() {
if (photoSize == null) {
if (Build.VERSION.SDK_INT >= 16) {
photoSize = 1280;
} else {
photoSize = 800;
}
}
return photoSize;
}
} }
...@@ -64,6 +64,8 @@ public class ImageLoader { ...@@ -64,6 +64,8 @@ public class ImageLoader {
private int lastImageNum = 0; private int lastImageNum = 0;
private long lastProgressUpdateTime = 0; private long lastProgressUpdateTime = 0;
private File telegramPath = null;
private class HttpTask extends AsyncTask<Void, Void, Boolean> { private class HttpTask extends AsyncTask<Void, Void, Boolean> {
private CacheImage cacheImage = null; private CacheImage cacheImage = null;
...@@ -548,6 +550,13 @@ public class ImageLoader { ...@@ -548,6 +550,13 @@ public class ImageLoader {
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (location != null) {
if (telegramPath != null && finalFile != null && finalFile.exists() && location.endsWith(".mp4") || location.endsWith(".jpg")) {
if (finalFile.toString().startsWith(telegramPath.toString())) {
Utilities.addMediaToGallery(finalFile.toString());
}
}
}
ImageLoader.this.fileDidLoaded(location, finalFile, tempFile); ImageLoader.this.fileDidLoaded(location, finalFile, tempFile);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidLoaded, location); NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidLoaded, location);
} }
...@@ -555,12 +564,12 @@ public class ImageLoader { ...@@ -555,12 +564,12 @@ public class ImageLoader {
} }
@Override @Override
public void fileDidFailedLoad(final String location, final boolean canceled) { public void fileDidFailedLoad(final String location, final int state) {
AndroidUtilities.RunOnUIThread(new Runnable() { AndroidUtilities.RunOnUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
ImageLoader.this.fileDidFailedLoad(location); ImageLoader.this.fileDidFailedLoad(location);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailedLoad, location, canceled); NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailedLoad, location, state);
} }
}); });
} }
...@@ -597,14 +606,14 @@ public class ImageLoader { ...@@ -597,14 +606,14 @@ public class ImageLoader {
try { try {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File telegramPath = new File(Environment.getExternalStorageDirectory(), LocaleController.getString("AppName", R.string.AppName)); telegramPath = new File(Environment.getExternalStorageDirectory(), LocaleController.getString("AppName", R.string.AppName));
telegramPath.mkdirs(); telegramPath.mkdirs();
if (telegramPath.isDirectory()) { if (telegramPath.isDirectory()) {
try { try {
File imagePath = new File(telegramPath, "Images"); File imagePath = new File(telegramPath, LocaleController.getString("AppName", R.string.AppName) + " Images");
imagePath.mkdir(); imagePath.mkdir();
if (imagePath.isDirectory()) { if (imagePath.isDirectory()) {
new File(imagePath, ".nomedia").createNewFile(); //new File(imagePath, ".nomedia").delete();
mediaDirs.put(FileLoader.MEDIA_DIR_IMAGE, imagePath); mediaDirs.put(FileLoader.MEDIA_DIR_IMAGE, imagePath);
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -612,10 +621,10 @@ public class ImageLoader { ...@@ -612,10 +621,10 @@ public class ImageLoader {
} }
try { try {
File videoPath = new File(telegramPath, "Video"); File videoPath = new File(telegramPath, LocaleController.getString("AppName", R.string.AppName) + " Video");
videoPath.mkdir(); videoPath.mkdir();
if (videoPath.isDirectory()) { if (videoPath.isDirectory()) {
new File(videoPath, ".nomedia").createNewFile(); //new File(videoPath, ".nomedia").delete();
mediaDirs.put(FileLoader.MEDIA_DIR_VIDEO, videoPath); mediaDirs.put(FileLoader.MEDIA_DIR_VIDEO, videoPath);
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -623,7 +632,7 @@ public class ImageLoader { ...@@ -623,7 +632,7 @@ public class ImageLoader {
} }
try { try {
File audioPath = new File(telegramPath, "Audio"); File audioPath = new File(telegramPath, LocaleController.getString("AppName", R.string.AppName) + " Audio");
audioPath.mkdir(); audioPath.mkdir();
if (audioPath.isDirectory()) { if (audioPath.isDirectory()) {
new File(audioPath, ".nomedia").createNewFile(); new File(audioPath, ".nomedia").createNewFile();
...@@ -634,7 +643,7 @@ public class ImageLoader { ...@@ -634,7 +643,7 @@ public class ImageLoader {
} }
try { try {
File documentPath = new File(telegramPath, "Documents"); File documentPath = new File(telegramPath, LocaleController.getString("AppName", R.string.AppName) + " Documents");
documentPath.mkdir(); documentPath.mkdir();
if (documentPath.isDirectory()) { if (documentPath.isDirectory()) {
new File(documentPath, ".nomedia").createNewFile(); new File(documentPath, ".nomedia").createNewFile();
...@@ -1041,22 +1050,7 @@ public class ImageLoader { ...@@ -1041,22 +1050,7 @@ public class ImageLoader {
return b; return b;
} }
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) { private static TLRPC.PhotoSize scaleAndSaveImageInternal(Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache) throws Exception {
if (bitmap == null) {
return null;
}
float photoW = bitmap.getWidth();
float photoH = bitmap.getHeight();
if (photoW == 0 || photoH == 0) {
return null;
}
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
int w = (int)(photoW / scaleFactor);
int h = (int)(photoH / scaleFactor);
if (h == 0 || w == 0) {
return null;
}
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
TLRPC.TL_fileLocation location = new TLRPC.TL_fileLocation(); TLRPC.TL_fileLocation location = new TLRPC.TL_fileLocation();
...@@ -1073,7 +1067,7 @@ public class ImageLoader { ...@@ -1073,7 +1067,7 @@ public class ImageLoader {
size.location = location; size.location = location;
size.w = (int)(photoW / scaleFactor); size.w = (int)(photoW / scaleFactor);
size.h = (int)(photoH / scaleFactor); size.h = (int)(photoH / scaleFactor);
try {
if (!cache) { if (!cache) {
String fileName = location.volume_id + "_" + location.local_id + ".jpg"; String fileName = location.volume_id + "_" + location.local_id + ".jpg";
final File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); final File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
...@@ -1089,9 +1083,38 @@ public class ImageLoader { ...@@ -1089,9 +1083,38 @@ public class ImageLoader {
if (scaledBitmap != bitmap) { if (scaledBitmap != bitmap) {
scaledBitmap.recycle(); scaledBitmap.recycle();
} }
return size; return size;
}
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
if (bitmap == null) {
return null;
}
float photoW = bitmap.getWidth();
float photoH = bitmap.getHeight();
if (photoW == 0 || photoH == 0) {
return null;
}
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
int w = (int)(photoW / scaleFactor);
int h = (int)(photoH / scaleFactor);
if (h == 0 || w == 0) {
return null;
}
try {
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache);
} catch (Throwable e) { } catch (Throwable e) {
FileLog.e("tmessages", e);
ImageLoader.getInstance().clearMemory();
System.gc();
try {
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache);
} catch (Throwable e2) {
FileLog.e("tmessages", e2);
return null; return null;
} }
} }
}
} }
...@@ -417,7 +417,7 @@ public class MessageObject { ...@@ -417,7 +417,7 @@ public class MessageObject {
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = messageOwner.media.photo.sizes; ArrayList<TLRPC.PhotoSize> sizes = messageOwner.media.photo.sizes;
if (sizes.size() > 0) { if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(sizes, 800, 800); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (sizeFull != null) { if (sizeFull != null) {
return FileLoader.getAttachFileName(sizeFull); return FileLoader.getAttachFileName(sizeFull);
} }
......
...@@ -1645,37 +1645,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter ...@@ -1645,37 +1645,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}); });
} }
public TLRPC.TL_photo generatePhotoSizes(String path, Uri imageUri) {
long time = System.currentTimeMillis();
Bitmap bitmap = ImageLoader.loadBitmap(path, imageUri, 800, 800);
ArrayList<TLRPC.PhotoSize> sizes = new ArrayList<TLRPC.PhotoSize>();
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, true);
if (size != null) {
size.type = "s";
sizes.add(size);
}
size = ImageLoader.scaleAndSaveImage(bitmap, 800, 800, 80, false);
if (size != null) {
size.type = "x";
sizes.add(size);
}
if (bitmap != null) {
bitmap.recycle();
}
if (sizes.isEmpty()) {
return null;
} else {
UserConfig.saveConfig(false);
TLRPC.TL_photo photo = new TLRPC.TL_photo();
photo.user_id = UserConfig.getClientUserId();
photo.date = ConnectionsManager.getInstance().getCurrentTime();
photo.sizes = sizes;
photo.caption = "";
photo.geo = new TLRPC.TL_geoPointEmpty();
return photo;
}
}
public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int offset, final int max_date, final boolean was, final boolean popup) { public void markDialogAsRead(final long dialog_id, final int max_id, final int max_positive_id, final int offset, final int max_date, final boolean was, final boolean popup) {
int lower_part = (int)dialog_id; int lower_part = (int)dialog_id;
int high_id = (int)(dialog_id >> 32); int high_id = (int)(dialog_id >> 32);
......
...@@ -2384,12 +2384,24 @@ public class MessagesStorage { ...@@ -2384,12 +2384,24 @@ public class MessagesStorage {
} }
} }
public void removeFromDownloadQueue(final long id, final int type) { public void removeFromDownloadQueue(final long id, final int type, final boolean move) {
storageQueue.postRunnable(new Runnable() { storageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
if (move) {
int minDate = -1;
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(date) FROM download_queue WHERE type = %d", type));
if (cursor.next()) {
minDate = cursor.intValue(0);
}
cursor.dispose();
if (minDate != -1) {
database.executeFast(String.format(Locale.US, "UPDATE download_queue SET date = %d WHERE uid = %d AND type = %d", minDate - 1, id, type)).stepThis().dispose();
}
} else {
database.executeFast(String.format(Locale.US, "DELETE FROM download_queue WHERE uid = %d AND type = %d", id, type)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "DELETE FROM download_queue WHERE uid = %d AND type = %d", id, type)).stepThis().dispose();
}
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
...@@ -2588,7 +2600,7 @@ public class MessagesStorage { ...@@ -2588,7 +2600,7 @@ public class MessagesStorage {
} }
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { } else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
if ((downloadMask & MediaController.AUTODOWNLOAD_MASK_PHOTO) != 0) { if ((downloadMask & MediaController.AUTODOWNLOAD_MASK_PHOTO) != 0) {
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.media.photo.sizes, 800, 800); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.media.photo.sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (photoSize != null) { if (photoSize != null) {
id = message.media.photo.id; id = message.media.photo.id;
type = MediaController.AUTODOWNLOAD_MASK_PHOTO; type = MediaController.AUTODOWNLOAD_MASK_PHOTO;
......
...@@ -40,6 +40,7 @@ public class NotificationCenter { ...@@ -40,6 +40,7 @@ public class NotificationCenter {
public static final int blockedUsersDidLoaded = 28; public static final int blockedUsersDidLoaded = 28;
public static final int openedChatChanged = 29; public static final int openedChatChanged = 29;
public static final int hideEmojiKeyboard = 30; public static final int hideEmojiKeyboard = 30;
public static final int stopEncodingService = 31;
public static final int wallpapersDidLoaded = 171; public static final int wallpapersDidLoaded = 171;
public static final int closeOtherAppActivities = 702; public static final int closeOtherAppActivities = 702;
......
...@@ -393,7 +393,8 @@ public class NotificationsController { ...@@ -393,7 +393,8 @@ public class NotificationsController {
String lastMessageFull = null; String lastMessageFull = null;
if (pushMessages.size() == 1) { if (pushMessages.size() == 1) {
String message = lastMessageFull = getStringForMessage(pushMessages.get(0), false); String message = lastMessageFull = getStringForMessage(pushMessages.get(0), false);
lastMessage = getStringForMessage(pushMessages.get(0), true); //lastMessage = getStringForMessage(pushMessages.get(0), true);
lastMessage = lastMessageFull;
if (message == null) { if (message == null) {
return; return;
} }
...@@ -418,7 +419,8 @@ public class NotificationsController { ...@@ -418,7 +419,8 @@ public class NotificationsController {
} }
if (i == 0) { if (i == 0) {
lastMessageFull = message; lastMessageFull = message;
lastMessage = getStringForMessage(pushMessages.get(i), true); //lastMessage = getStringForMessage(pushMessages.get(i), true);
lastMessage = lastMessageFull;
} }
if (pushDialogs.size() == 1) { if (pushDialogs.size() == 1) {
if (replace) { if (replace) {
...@@ -444,6 +446,9 @@ public class NotificationsController { ...@@ -444,6 +446,9 @@ public class NotificationsController {
if (!notifyDisabled) { if (!notifyDisabled) {
if (ApplicationLoader.mainInterfacePaused || inAppPreview) { if (ApplicationLoader.mainInterfacePaused || inAppPreview) {
if (lastMessage.length() > 100) {
lastMessage = lastMessage.substring(0, 100).replace("\n", " ").trim() + "...";
}
mBuilder.setTicker(lastMessage); mBuilder.setTicker(lastMessage);
} }
if (choosenSoundPath != null && !choosenSoundPath.equals("NoSound")) { if (choosenSoundPath != null && !choosenSoundPath.equals("NoSound")) {
......
/*
* 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.android;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.ui.ApplicationLoader;
public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate {
private NotificationCompat.Builder builder = null;
private String path = null;
private int currentProgress = 0;
public VideoEncodingService() {
super();
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.stopEncodingService);
}
public IBinder onBind(Intent arg2) {
return null;
}
public void onDestroy() {
stopForeground(true);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.FileUploadProgressChanged);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stopEncodingService);
FileLog.e("tmessages", "destroy video service");
}
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == NotificationCenter.FileUploadProgressChanged) {
String fileName = (String)args[0];
if (path.equals(fileName)) {
Float progress = (Float) args[1];
Boolean enc = (Boolean) args[2];
currentProgress = (int)(progress * 100);
builder.setProgress(100, currentProgress, currentProgress == 0);
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
}
} else if (id == NotificationCenter.stopEncodingService) {
String filepath = (String)args[0];
if (filepath == null || filepath.equals(path)) {
stopSelf();
}
}
}
public int onStartCommand(Intent intent, int flags, int startId) {
path = intent.getStringExtra("path");
if (path == null) {
stopSelf();
return Service.START_NOT_STICKY;
}
FileLog.e("tmessages", "start video service");
if (builder == null) {
builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
builder.setSmallIcon(android.R.drawable.stat_sys_upload);
builder.setWhen(System.currentTimeMillis());
builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName));
builder.setTicker(LocaleController.getString("SendingVideo", R.string.SendingVideo));
builder.setContentText(LocaleController.getString("SendingVideo", R.string.SendingVideo));
}
currentProgress = 0;
builder.setProgress(100, currentProgress, currentProgress == 0);
startForeground(4, builder.build());
NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build());
return Service.START_NOT_STICKY;
}
}
...@@ -46,14 +46,16 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener { ...@@ -46,14 +46,16 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private TextureRenderer mTextureRender; private TextureRenderer mTextureRender;
private int mWidth; private int mWidth;
private int mHeight; private int mHeight;
private int rotateRender = 0;
private ByteBuffer mPixelBuf; private ByteBuffer mPixelBuf;
public OutputSurface(int width, int height) { public OutputSurface(int width, int height, int rotate) {
if (width <= 0 || height <= 0) { if (width <= 0 || height <= 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
rotateRender = rotate;
mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4); mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
mPixelBuf.order(ByteOrder.LITTLE_ENDIAN); mPixelBuf.order(ByteOrder.LITTLE_ENDIAN);
eglSetup(width, height); eglSetup(width, height);
...@@ -66,7 +68,7 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener { ...@@ -66,7 +68,7 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
} }
private void setup() { private void setup() {
mTextureRender = new TextureRenderer(); mTextureRender = new TextureRenderer(rotateRender);
mTextureRender.surfaceCreated(); mTextureRender.surfaceCreated();
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId()); mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
mSurfaceTexture.setOnFrameAvailableListener(this); mSurfaceTexture.setOnFrameAvailableListener(this);
......
...@@ -69,8 +69,10 @@ public class TextureRenderer { ...@@ -69,8 +69,10 @@ public class TextureRenderer {
private int muSTMatrixHandle; private int muSTMatrixHandle;
private int maPositionHandle; private int maPositionHandle;
private int maTextureHandle; private int maTextureHandle;
private int rotationAngle = 0;
public TextureRenderer() { public TextureRenderer(int rotation) {
rotationAngle = rotation;
mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleVertices.put(mTriangleVerticesData).position(0); mTriangleVertices.put(mTriangleVerticesData).position(0);
Matrix.setIdentityM(mSTMatrix, 0); Matrix.setIdentityM(mSTMatrix, 0);
...@@ -147,6 +149,9 @@ public class TextureRenderer { ...@@ -147,6 +149,9 @@ public class TextureRenderer {
checkGlError("glTexParameter"); checkGlError("glTexParameter");
Matrix.setIdentityM(mMVPMatrix, 0); Matrix.setIdentityM(mMVPMatrix, 0);
if (rotationAngle != 0) {
Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
}
} }
public void changeFragmentShader(String fragmentShader) { public void changeFragmentShader(String fragmentShader) {
......
...@@ -1116,6 +1116,30 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. ...@@ -1116,6 +1116,30 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
} }
request.retryCount++; request.retryCount++;
if ((request.flags & RPCRequest.RPCRequestClassDownloadMedia) != 0) {
int retryMax = 10;
if ((request.flags & RPCRequest.RPCRequestClassForceDownload) == 0) {
if (request.wait) {
retryMax = 1;
} else {
retryMax = 3;
}
}
if (request.retryCount >= retryMax) {
FileLog.e("tmessages", "timed out " + request.rawRequest);
TLRPC.TL_error error = new TLRPC.TL_error();
error.code = -123;
error.text = "RETRY_LIMIT";
if (request.completionBlock != null) {
request.completionBlock.run(null, error);
}
runningRequests.remove(i);
i--;
continue;
}
}
NetworkMessage networkMessage = new NetworkMessage(); NetworkMessage networkMessage = new NetworkMessage();
networkMessage.protoMessage = new TLRPC.TL_protoMessage(); networkMessage.protoMessage = new TLRPC.TL_protoMessage();
...@@ -2081,6 +2105,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. ...@@ -2081,6 +2105,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
waitTime = Math.min(30, waitTime); waitTime = Math.min(30, waitTime);
discardResponse = true; discardResponse = true;
request.wait = true;
request.runningMinStartTime = (int)(System.currentTimeMillis() / 1000 + waitTime); request.runningMinStartTime = (int)(System.currentTimeMillis() / 1000 + waitTime);
request.confirmed = false; request.confirmed = false;
} }
......
...@@ -52,10 +52,11 @@ public class FileLoadOperation { ...@@ -52,10 +52,11 @@ public class FileLoadOperation {
private RandomAccessFile fiv; private RandomAccessFile fiv;
private File storePath = null; private File storePath = null;
private File tempPath = null; private File tempPath = null;
private boolean isForceRequest = false;
public static interface FileLoadOperationDelegate { public static interface FileLoadOperationDelegate {
public abstract void didFinishLoadingFile(FileLoadOperation operation, File finalFile, File tempFile); public abstract void didFinishLoadingFile(FileLoadOperation operation, File finalFile, File tempFile);
public abstract void didFailedLoadingFile(FileLoadOperation operation, boolean canceled); public abstract void didFailedLoadingFile(FileLoadOperation operation, int state);
public abstract void didChangedLoadProgress(FileLoadOperation operation, float progress); public abstract void didChangedLoadProgress(FileLoadOperation operation, float progress);
} }
...@@ -146,6 +147,14 @@ public class FileLoadOperation { ...@@ -146,6 +147,14 @@ public class FileLoadOperation {
} }
} }
public void setForceRequest(boolean forceRequest) {
isForceRequest = forceRequest;
}
public boolean isForceRequest() {
return isForceRequest;
}
public void setPaths(File store, File temp) { public void setPaths(File store, File temp) {
storePath = store; storePath = store;
tempPath = temp; tempPath = temp;
...@@ -160,7 +169,7 @@ public class FileLoadOperation { ...@@ -160,7 +169,7 @@ public class FileLoadOperation {
Utilities.stageQueue.postRunnable(new Runnable() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
}); });
return; return;
...@@ -180,7 +189,7 @@ public class FileLoadOperation { ...@@ -180,7 +189,7 @@ public class FileLoadOperation {
Utilities.stageQueue.postRunnable(new Runnable() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
}); });
return; return;
...@@ -234,7 +243,7 @@ public class FileLoadOperation { ...@@ -234,7 +243,7 @@ public class FileLoadOperation {
Utilities.stageQueue.postRunnable(new Runnable() { Utilities.stageQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
}); });
return; return;
...@@ -246,7 +255,7 @@ public class FileLoadOperation { ...@@ -246,7 +255,7 @@ public class FileLoadOperation {
try { try {
onFinishLoadingFile(); onFinishLoadingFile();
} catch (Exception e) { } catch (Exception e) {
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
} else { } else {
startDownloadRequest(); startDownloadRequest();
...@@ -257,7 +266,7 @@ public class FileLoadOperation { ...@@ -257,7 +266,7 @@ public class FileLoadOperation {
try { try {
onFinishLoadingFile(); onFinishLoadingFile();
} catch (Exception e) { } catch (Exception e) {
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
} }
} }
...@@ -276,7 +285,7 @@ public class FileLoadOperation { ...@@ -276,7 +285,7 @@ public class FileLoadOperation {
ConnectionsManager.getInstance().cancelRpc(requestInfo.requestToken, true, true); ConnectionsManager.getInstance().cancelRpc(requestInfo.requestToken, true, true);
} }
} }
delegate.didFailedLoadingFile(FileLoadOperation.this, true); delegate.didFailedLoadingFile(FileLoadOperation.this, 1);
} }
}); });
} }
...@@ -374,7 +383,7 @@ public class FileLoadOperation { ...@@ -374,7 +383,7 @@ public class FileLoadOperation {
} }
} catch (Exception e) { } catch (Exception e) {
cleanup(); cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
} else { } else {
...@@ -390,7 +399,7 @@ public class FileLoadOperation { ...@@ -390,7 +399,7 @@ public class FileLoadOperation {
} }
if (val == null) { if (val == null) {
cleanup(); cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} else { } else {
datacenter_id = val; datacenter_id = val;
nextDownloadOffset = 0; nextDownloadOffset = 0;
...@@ -403,18 +412,21 @@ public class FileLoadOperation { ...@@ -403,18 +412,21 @@ public class FileLoadOperation {
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
cleanup(); cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
} else { } else {
cleanup(); cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
} else if (error.text.contains("RETRY_LIMIT")) {
cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, 2);
} else { } else {
if (location != null) { if (location != null) {
FileLog.e("tmessages", "" + location + " id = " + location.id + " access_hash = " + location.access_hash + " volume_id = " + location.local_id + " secret = " + location.secret); FileLog.e("tmessages", "" + location + " id = " + location.id + " access_hash = " + location.access_hash + " volume_id = " + location.local_id + " secret = " + location.secret);
} }
cleanup(); cleanup();
delegate.didFailedLoadingFile(FileLoadOperation.this, false); delegate.didFailedLoadingFile(FileLoadOperation.this, 0);
} }
} }
} }
...@@ -448,7 +460,7 @@ public class FileLoadOperation { ...@@ -448,7 +460,7 @@ public class FileLoadOperation {
requestInfo.response = (TLRPC.TL_upload_file) response; requestInfo.response = (TLRPC.TL_upload_file) response;
processRequestResult(requestInfo, error); processRequestResult(requestInfo, error);
} }
}, null, true, RPCRequest.RPCRequestClassDownloadMedia, datacenter_id, isLast); }, null, true, RPCRequest.RPCRequestClassDownloadMedia | (isForceRequest ? RPCRequest.RPCRequestClassForceDownload : 0), datacenter_id, isLast);
} }
} }
......
...@@ -27,6 +27,7 @@ public class RPCRequest { ...@@ -27,6 +27,7 @@ public class RPCRequest {
public static int RPCRequestClassPush = 64; public static int RPCRequestClassPush = 64;
public static int RPCRequestClassWithoutLogin = 128; public static int RPCRequestClassWithoutLogin = 128;
public static int RPCRequestClassTryDifferentDc = 256; public static int RPCRequestClassTryDifferentDc = 256;
public static int RPCRequestClassForceDownload = 512;
static int RPCRequestClassTransportMask = (RPCRequestClassGeneric | RPCRequestClassDownloadMedia | RPCRequestClassUploadMedia); static int RPCRequestClassTransportMask = (RPCRequestClassGeneric | RPCRequestClassDownloadMedia | RPCRequestClassUploadMedia);
...@@ -35,6 +36,7 @@ public class RPCRequest { ...@@ -35,6 +36,7 @@ public class RPCRequest {
int serverFailureCount; int serverFailureCount;
int flags; int flags;
boolean wait = false;
protected int retryCount = 0; protected int retryCount = 0;
protected int lastResendTime = 0; protected int lastResendTime = 0;
protected boolean completed = false; protected boolean completed = false;
......
...@@ -314,10 +314,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD ...@@ -314,10 +314,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
photoImage.setImage(currentPhotoObject.photoOwner.location, currentPhotoFilter, currentMessageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable, currentPhotoObject.photoOwner.size); photoImage.setImage(currentPhotoObject.photoOwner.location, currentPhotoFilter, currentMessageObject.isOut() ? placeholderOutDrawable : placeholderInDrawable, currentPhotoObject.photoOwner.size);
} }
} else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) { } else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) {
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document); FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true);
lastDownloadedGifMessage = currentMessageObject; lastDownloadedGifMessage = currentMessageObject;
} else if (currentMessageObject.type == 3) { } else if (currentMessageObject.type == 3) {
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video); FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video, true);
} }
progressVisible = true; progressVisible = true;
startAnimation(); startAnimation();
...@@ -472,7 +472,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD ...@@ -472,7 +472,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
photoWidth = AndroidUtilities.dp(86); photoWidth = AndroidUtilities.dp(86);
photoHeight = AndroidUtilities.dp(86); photoHeight = AndroidUtilities.dp(86);
backgroundWidth = photoWidth + Math.max(nameWidth, infoWidth) + AndroidUtilities.dp(68); backgroundWidth = photoWidth + Math.max(nameWidth, infoWidth) + AndroidUtilities.dp(68);
currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, 800, 800); currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (currentPhotoObject != null) { if (currentPhotoObject != null) {
if (currentPhotoObject.image != null) { if (currentPhotoObject.image != null) {
photoImage.setImageBitmap(currentPhotoObject.image); photoImage.setImageBitmap(currentPhotoObject.image);
...@@ -500,14 +500,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD ...@@ -500,14 +500,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} }
photoHeight = photoWidth + AndroidUtilities.dp(100); photoHeight = photoWidth + AndroidUtilities.dp(100);
if (photoWidth > 800) { if (photoWidth > AndroidUtilities.getPhotoSize()) {
photoWidth = 800; photoWidth = AndroidUtilities.getPhotoSize();
} }
if (photoHeight > 800) { if (photoHeight > AndroidUtilities.getPhotoSize()) {
photoHeight = 800; photoHeight = AndroidUtilities.getPhotoSize();
} }
currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, 800, 800); currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (currentPhotoObject != null) { if (currentPhotoObject != null) {
boolean noSize = false; boolean noSize = false;
if (currentMessageObject.type == 3 || currentMessageObject.type == 8) { if (currentMessageObject.type == 3 || currentMessageObject.type == 8) {
...@@ -515,6 +515,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD ...@@ -515,6 +515,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
} }
float scale = (float) currentPhotoObject.photoOwner.w / (float) photoWidth; float scale = (float) currentPhotoObject.photoOwner.w / (float) photoWidth;
if (!noSize && currentPhotoObject.photoOwner.size == 0) {
currentPhotoObject.photoOwner.size = -1;
}
int w = (int) (currentPhotoObject.photoOwner.w / scale); int w = (int) (currentPhotoObject.photoOwner.w / scale);
int h = (int) (currentPhotoObject.photoOwner.h / scale); int h = (int) (currentPhotoObject.photoOwner.h / scale);
if (w == 0) { if (w == 0) {
......
...@@ -80,7 +80,7 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -80,7 +80,7 @@ public class DocumentSelectActivity extends BaseFragment {
Runnable r = new Runnable() { Runnable r = new Runnable() {
public void run() { public void run() {
try { try {
if (currentDir == null){ if (currentDir == null) {
listRoots(); listRoots();
} else { } else {
listFiles(currentDir); listFiles(currentDir);
...@@ -159,13 +159,22 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -159,13 +159,22 @@ public class DocumentSelectActivity extends BaseFragment {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
ListItem item = items.get(i); ListItem item = items.get(i);
File file = item.file; File file = item.file;
if (file.isDirectory()) { if (file == null) {
HistoryEntry he = history.remove(history.size() - 1);
actionBarLayer.setTitle(he.title);
if (he.dir != null) {
listFiles(he.dir);
} else {
listRoots();
}
listView.setSelectionFromTop(he.scrollItem, he.scrollOffset);
} else if (file.isDirectory()) {
HistoryEntry he = new HistoryEntry(); HistoryEntry he = new HistoryEntry();
he.scrollItem = listView.getFirstVisiblePosition(); he.scrollItem = listView.getFirstVisiblePosition();
he.scrollOffset = listView.getChildAt(0).getTop(); he.scrollOffset = listView.getChildAt(0).getTop();
he.dir = currentDir; he.dir = currentDir;
he.title = actionBarLayer.getTitle().toString(); he.title = actionBarLayer.getTitle().toString();
if (!listFiles(file)){ if (!listFiles(file)) {
return; return;
} }
history.add(he); history.add(he);
...@@ -212,7 +221,7 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -212,7 +221,7 @@ public class DocumentSelectActivity extends BaseFragment {
@Override @Override
public boolean onBackPressed() { public boolean onBackPressed() {
if (history.size() > 0){ if (history.size() > 0) {
HistoryEntry he = history.remove(history.size() - 1); HistoryEntry he = history.remove(history.size() - 1);
actionBarLayer.setTitle(he.title); actionBarLayer.setTitle(he.title);
if (he.dir != null) { if (he.dir != null) {
...@@ -240,7 +249,7 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -240,7 +249,7 @@ public class DocumentSelectActivity extends BaseFragment {
currentDir = dir; currentDir = dir;
items.clear(); items.clear();
String state = Environment.getExternalStorageState(); String state = Environment.getExternalStorageState();
if (Environment.MEDIA_SHARED.equals(state)){ if (Environment.MEDIA_SHARED.equals(state)) {
emptyView.setText(LocaleController.getString("UsbActive", R.string.UsbActive)); emptyView.setText(LocaleController.getString("UsbActive", R.string.UsbActive));
} else { } else {
emptyView.setText(LocaleController.getString("NotMounted", R.string.NotMounted)); emptyView.setText(LocaleController.getString("NotMounted", R.string.NotMounted));
...@@ -273,6 +282,15 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -273,6 +282,15 @@ public class DocumentSelectActivity extends BaseFragment {
return lhs.isDirectory() ? -1 : 1; return lhs.isDirectory() ? -1 : 1;
} }
return lhs.getName().compareToIgnoreCase(rhs.getName()); return lhs.getName().compareToIgnoreCase(rhs.getName());
/*long lm = lhs.lastModified();
long rm = lhs.lastModified();
if (lm == rm) {
return 0;
} else if (lm > rm) {
return -1;
} else {
return 1;
}*/
} }
}); });
for (File file : files) { for (File file : files) {
...@@ -296,6 +314,12 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -296,6 +314,12 @@ public class DocumentSelectActivity extends BaseFragment {
} }
items.add(item); items.add(item);
} }
ListItem item = new ListItem();
item.title = "..";
item.subtitle = "";
item.icon = R.drawable.ic_directory;
item.file = null;
items.add(0, item);
listAdapter.notifyDataSetChanged(); listAdapter.notifyDataSetChanged();
return true; return true;
} }
...@@ -374,10 +398,25 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -374,10 +398,25 @@ public class DocumentSelectActivity extends BaseFragment {
fs.icon = R.drawable.ic_directory; fs.icon = R.drawable.ic_directory;
fs.file = new File("/"); fs.file = new File("/");
items.add(fs); items.add(fs);
try {
File telegramPath = new File(Environment.getExternalStorageDirectory(), LocaleController.getString("AppName", R.string.AppName));
if (telegramPath.exists()) {
fs = new ListItem();
fs.title = LocaleController.getString("AppName", R.string.AppName);
fs.subtitle = telegramPath.toString();
fs.icon = R.drawable.ic_directory;
fs.file = telegramPath;
items.add(fs);
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
listAdapter.notifyDataSetChanged(); listAdapter.notifyDataSetChanged();
} }
private String getRootSubtitle(String path){ private String getRootSubtitle(String path) {
StatFs stat = new StatFs(path); StatFs stat = new StatFs(path);
long total = (long)stat.getBlockCount() * (long)stat.getBlockSize(); long total = (long)stat.getBlockCount() * (long)stat.getBlockSize();
long free = (long)stat.getAvailableBlocks() * (long)stat.getBlockSize(); long free = (long)stat.getAvailableBlocks() * (long)stat.getBlockSize();
...@@ -409,11 +448,11 @@ public class DocumentSelectActivity extends BaseFragment { ...@@ -409,11 +448,11 @@ public class DocumentSelectActivity extends BaseFragment {
return 0; return 0;
} }
public int getViewTypeCount(){ public int getViewTypeCount() {
return 2; return 2;
} }
public int getItemViewType(int pos){ public int getItemViewType(int pos) {
return items.get(pos).subtitle.length() > 0 ? 0 : 1; return items.get(pos).subtitle.length() > 0 ? 0 : 1;
} }
......
...@@ -580,7 +580,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -580,7 +580,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
actionBarLayout.presentFragment(fragment, false, true, true); actionBarLayout.presentFragment(fragment, false, true, true);
pushOpened = true; pushOpened = true;
if (PhotoViewer.getInstance().isVisible()) { if (PhotoViewer.getInstance().isVisible()) {
PhotoViewer.getInstance().closePhoto(true); PhotoViewer.getInstance().closePhoto(false);
} }
} }
if (open_settings != 0) { if (open_settings != 0) {
...@@ -648,10 +648,27 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -648,10 +648,27 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
args.putInt("enc_id", high_id); args.putInt("enc_id", high_id);
} }
ChatActivity fragment = new ChatActivity(args); ChatActivity fragment = new ChatActivity(args);
actionBarLayout.presentFragment(fragment, true);
if (videoPath != null) { if (videoPath != null) {
if(android.os.Build.VERSION.SDK_INT >= 16) {
if (AndroidUtilities.isTablet()) {
actionBarLayout.presentFragment(fragment, false, true, true);
}
Bundle args2 = new Bundle();
args2.putString("videoPath", videoPath);
VideoEditorActivity fragment2 = new VideoEditorActivity(args2);
fragment2.setDelegate(fragment);
presentFragment(fragment2, true, true);
if (!AndroidUtilities.isTablet()) {
actionBarLayout.addFragmentToStack(fragment, actionBarLayout.fragmentsStack.size() - 1);
}
} else {
actionBarLayout.presentFragment(fragment, true);
fragment.processSendingVideo(videoPath, 0, 0, 0, 0, null); fragment.processSendingVideo(videoPath, 0, 0, 0, 0, null);
} }
} else {
actionBarLayout.presentFragment(fragment, true);
if (sendingText != null) { if (sendingText != null) {
fragment.processSendingText(sendingText); fragment.processSendingText(sendingText);
} }
...@@ -666,6 +683,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -666,6 +683,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
SendMessagesHelper.getInstance().sendMessage(user, dialog_id); SendMessagesHelper.getInstance().sendMessage(user, dialog_id);
} }
} }
}
photoPathsArray = null; photoPathsArray = null;
videoPath = null; videoPath = null;
...@@ -1027,7 +1045,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -1027,7 +1045,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0)); layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
a--; a--;
} }
layersActionBarLayout.closeLastFragment(true); layersActionBarLayout.closeLastFragment(!forceWithoutAnimation);
} }
return false; return false;
} else if (tabletFullSize && layout != actionBarLayout) { } else if (tabletFullSize && layout != actionBarLayout) {
...@@ -1037,7 +1055,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -1037,7 +1055,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0)); layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
a--; a--;
} }
layersActionBarLayout.closeLastFragment(true); layersActionBarLayout.closeLastFragment(!forceWithoutAnimation);
} }
return false; return false;
} else { } else {
...@@ -1046,7 +1064,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa ...@@ -1046,7 +1064,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0)); layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
a--; a--;
} }
layersActionBarLayout.closeLastFragment(true); layersActionBarLayout.closeLastFragment(!forceWithoutAnimation);
}
if (actionBarLayout.fragmentsStack.size() > 1) {
actionBarLayout.presentFragment(fragment, actionBarLayout.fragmentsStack.size() > 1, forceWithoutAnimation, false);
return false;
} }
} }
} else if (layout != layersActionBarLayout) { } else if (layout != layersActionBarLayout) {
......
...@@ -366,6 +366,9 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter ...@@ -366,6 +366,9 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
MessagesController.getInstance().deleteUserFromChat((int) -selectedDialog, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null); MessagesController.getInstance().deleteUserFromChat((int) -selectedDialog, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), null);
MessagesController.getInstance().deleteDialog(selectedDialog, 0, false); MessagesController.getInstance().deleteDialog(selectedDialog, 0, false);
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats, selectedDialog);
}
} }
}); });
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
...@@ -387,6 +390,9 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter ...@@ -387,6 +390,9 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
MessagesController.getInstance().deleteDialog(selectedDialog, 0, false); MessagesController.getInstance().deleteDialog(selectedDialog, 0, false);
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats, selectedDialog);
}
} }
}); });
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
...@@ -486,7 +492,15 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter ...@@ -486,7 +492,15 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
updateVisibleRows(0); updateVisibleRows(0);
} else if (id == NotificationCenter.openedChatChanged) { } else if (id == NotificationCenter.openedChatChanged) {
if (!serverOnly && AndroidUtilities.isTablet()) { if (!serverOnly && AndroidUtilities.isTablet()) {
openedDialogId = (Long)args[0]; boolean close = (Boolean)args[1];
long dialog_id = (Long)args[0];
if (close) {
if (dialog_id == openedDialogId) {
openedDialogId = 0;
}
} else {
openedDialogId = dialog_id;
}
updateVisibleRows(0); updateVisibleRows(0);
} }
} }
......
...@@ -509,10 +509,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -509,10 +509,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (id == -1) { if (id == -1) {
closePhoto(true); closePhoto(true);
} else if (id == gallery_menu_save) { } else if (id == gallery_menu_save) {
if (currentFileName == null) { File f = null;
return; if (currentMessageObject != null) {
f = FileLoader.getPathToMessage(currentMessageObject.messageOwner);
} else if (currentFileLocation != null) {
f = FileLoader.getPathToAttach(currentFileLocation);
}
if (f != null && f.exists()) {
MediaController.saveFile(f.toString(), parentActivity, currentFileName.endsWith("mp4") ? 1 : 0, null);
} }
MediaController.saveFile(currentFileName, null, parentActivity, currentFileName.endsWith("mp4") ? 1 : 0, null);
} else if (id == gallery_menu_showall) { } else if (id == gallery_menu_showall) {
if (opennedFromMedia) { if (opennedFromMedia) {
closePhoto(true); closePhoto(true);
...@@ -945,7 +951,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -945,7 +951,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) {
return message.messageOwner.action.newUserPhoto.photo_big; return message.messageOwner.action.newUserPhoto.photo_big;
} else { } else {
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.action.photo.sizes, 800, 800); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.action.photo.sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (sizeFull != null) { if (sizeFull != null) {
size[0] = sizeFull.size; size[0] = sizeFull.size;
if (size[0] == 0) { if (size[0] == 0) {
...@@ -957,7 +963,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -957,7 +963,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} }
} }
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && message.messageOwner.media.photo != null) { } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && message.messageOwner.media.photo != null) {
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.media.photo.sizes, 800, 800); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.media.photo.sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (sizeFull != null) { if (sizeFull != null) {
size[0] = sizeFull.size; size[0] = sizeFull.size;
if (size[0] == 0) { if (size[0] == 0) {
...@@ -1008,7 +1014,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -1008,7 +1014,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
location.secret = sizeFull.secret; location.secret = sizeFull.secret;
return location; return location;
} else { } else {
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.action.photo.sizes, 800, 800); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.action.photo.sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (sizeFull != null) { if (sizeFull != null) {
TLRPC.TL_inputFileLocation location = new TLRPC.TL_inputFileLocation(); TLRPC.TL_inputFileLocation location = new TLRPC.TL_inputFileLocation();
location.local_id = sizeFull.location.local_id; location.local_id = sizeFull.location.local_id;
...@@ -1019,7 +1025,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -1019,7 +1025,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} }
} }
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.media.photo.sizes, 800, 800); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.messageOwner.media.photo.sizes, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
if (sizeFull != null) { if (sizeFull != null) {
TLRPC.TL_inputFileLocation location = new TLRPC.TL_inputFileLocation(); TLRPC.TL_inputFileLocation location = new TLRPC.TL_inputFileLocation();
location.local_id = sizeFull.location.local_id; location.local_id = sizeFull.location.local_id;
...@@ -1370,7 +1376,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -1370,7 +1376,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (currentThumb != null && imageReceiver == centerImage) { if (currentThumb != null && imageReceiver == centerImage) {
placeHolder = currentThumb; placeHolder = currentThumb;
} }
int size = (int)(800 / AndroidUtilities.density); int size = (int)(AndroidUtilities.getPhotoSize() / AndroidUtilities.density);
imageReceiver.setImage(photoEntry.path, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(null, placeHolder) : null); imageReceiver.setImage(photoEntry.path, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(null, placeHolder) : null);
} else { } else {
imageReceiver.setImageBitmap((Bitmap) null); imageReceiver.setImageBitmap((Bitmap) null);
...@@ -1405,6 +1411,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -1405,6 +1411,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (currentThumb != null && imageReceiver == centerImage) { if (currentThumb != null && imageReceiver == centerImage) {
placeHolder = currentThumb; placeHolder = currentThumb;
} }
if (size[0] == 0) {
size[0] = -1;
}
imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, size[0]); imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, size[0]);
} }
} else { } else {
...@@ -2306,7 +2315,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ...@@ -2306,7 +2315,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} }
if (loadFile) { if (loadFile) {
if (!FileLoader.getInstance().isLoadingFile(currentFileName)) { if (!FileLoader.getInstance().isLoadingFile(currentFileName)) {
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video); FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video, true);
} else { } else {
FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.video); FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.video);
} }
......
...@@ -445,7 +445,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC ...@@ -445,7 +445,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
TextView messageText = (TextView)view.findViewById(R.id.message_text); TextView messageText = (TextView)view.findViewById(R.id.message_text);
BackupImageView imageView = (BackupImageView) view.findViewById(R.id.message_image); BackupImageView imageView = (BackupImageView) view.findViewById(R.id.message_image);
imageView.imageReceiver.setAspectFit(true); imageView.imageReceiver.setAspectFit(true);
PhotoObject currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, 800, 800); PhotoObject currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize());
boolean photoSet = false; boolean photoSet = false;
if (currentPhotoObject != null) { if (currentPhotoObject != null) {
boolean photoExist = true; boolean photoExist = true;
......
...@@ -568,11 +568,19 @@ public class ActionBarLayout extends FrameLayout { ...@@ -568,11 +568,19 @@ public class ActionBarLayout extends FrameLayout {
} }
public boolean addFragmentToStack(BaseFragment fragment) { public boolean addFragmentToStack(BaseFragment fragment) {
return addFragmentToStack(fragment, -1);
}
public boolean addFragmentToStack(BaseFragment fragment, int position) {
if (delegate != null && !delegate.needAddFragmentToStack(fragment, this) || !fragment.onFragmentCreate()) { if (delegate != null && !delegate.needAddFragmentToStack(fragment, this) || !fragment.onFragmentCreate()) {
return false; return false;
} }
fragment.setParentLayout(this); fragment.setParentLayout(this);
if (position == -1) {
fragmentsStack.add(fragment); fragmentsStack.add(fragment);
} else {
fragmentsStack.add(position, fragment);
}
return true; return true;
} }
......
...@@ -45,8 +45,6 @@ import org.telegram.messenger.R; ...@@ -45,8 +45,6 @@ import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.ui.ApplicationLoader; import org.telegram.ui.ApplicationLoader;
import java.lang.reflect.Method;
public class ChatActivityEnterView implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate { public class ChatActivityEnterView implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate {
public static interface ChatActivityEnterViewDelegate { public static interface ChatActivityEnterViewDelegate {
......
...@@ -39,6 +39,9 @@ public class TypingDotsDrawable extends Drawable { ...@@ -39,6 +39,9 @@ public class TypingDotsDrawable extends Drawable {
long newTime = System.currentTimeMillis(); long newTime = System.currentTimeMillis();
long dt = newTime - lastUpdateTime; long dt = newTime - lastUpdateTime;
lastUpdateTime = newTime; lastUpdateTime = newTime;
if (dt > 50) {
dt = 50;
}
for (int a = 0; a < 3; a++) { for (int a = 0; a < 3; a++) {
elapsedTimes[a] += dt; elapsedTimes[a] += dt;
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
<org.telegram.ui.Views.FrameLayoutFixed <org.telegram.ui.Views.FrameLayoutFixed
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:paddingBottom="48dp"> android:paddingBottom="48dp"
android:id="@+id/empty_view">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
...@@ -20,7 +21,6 @@ ...@@ -20,7 +21,6 @@
android:paddingRight="7dp" android:paddingRight="7dp"
android:textSize="14dp" android:textSize="14dp"
android:id="@+id/searchEmptyView" android:id="@+id/searchEmptyView"
android:visibility="gone"
android:layout_gravity="center"/> android:layout_gravity="center"/>
<include <include
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:id="@+id/info_container" android:id="@+id/info_container"
android:orientation="vertical"> android:orientation="vertical">
...@@ -65,7 +67,6 @@ ...@@ -65,7 +67,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="#f0f0f0" android:textColor="#f0f0f0"
android:textSize="15dp" android:textSize="15dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="13dp" android:layout_marginLeft="13dp"
android:id="@+id/original_title"/> android:id="@+id/original_title"/>
...@@ -92,9 +93,17 @@ ...@@ -92,9 +93,17 @@
android:textColor="#bebebe" android:textColor="#bebebe"
android:textSize="15dp" android:textSize="15dp"
android:layout_marginLeft="13dp" android:layout_marginLeft="13dp"
android:layout_marginBottom="8dp"
android:id="@+id/edited_size"/> android:id="@+id/edited_size"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="6dp"
android:textColor="#f0f0f0"
android:textSize="15dp"
android:id="@+id/compress_video"/>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="OriginalVideo">الفيديو الأصلي</string> <string name="OriginalVideo">الفيديو الأصلي</string>
<string name="EditedVideo">تم تحرير الفيديو</string> <string name="EditedVideo">تم تحرير الفيديو</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sending video...</string>
<string name="CompressVideo">Compress Video</string>
<!--button titles--> <!--button titles-->
<string name="Next">التالي</string> <string name="Next">التالي</string>
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<!--signin view--> <!--signin view-->
<string name="YourPhone">Dein Telefon</string> <string name="YourPhone">Dein Telefon</string>
<string name="StartText">Bitte bestätige deine Landesvorwahl und deine Telefonnummer.</string> <string name="StartText">Bitte Landeskennzahl und\nTelefonnummer bestätigen.</string>
<string name="ChooseCountry">Wähle ein Land</string> <string name="ChooseCountry">Wähle ein Land</string>
<string name="WrongCountry">Falsche Landesvorwahl</string> <string name="WrongCountry">Falsche Landesvorwahl</string>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<string name="Yesterday">gestern</string> <string name="Yesterday">gestern</string>
<string name="NoResult">Keine Ergebnisse</string> <string name="NoResult">Keine Ergebnisse</string>
<string name="NoChats">Noch keine Chats…</string> <string name="NoChats">Noch keine Chats…</string>
<string name="NoChatsHelp">Beginne Telegram zu nutzen, indem du\neine neue Nachricht erstellst (rechte obere Ecke)\noder deine Kontakte aufrufst.</string> <string name="NoChatsHelp">Tippe rechts oben für deine erste\nChatnachricht, oder auf den Menüknopf\num die restlichen Optionen zu öffnen.</string>
<string name="WaitingForNetwork">Warte auf Netzwerk...</string> <string name="WaitingForNetwork">Warte auf Netzwerk...</string>
<string name="Connecting">Verbinde…</string> <string name="Connecting">Verbinde…</string>
<string name="Updating">Aktualisiere…</string> <string name="Updating">Aktualisiere…</string>
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
<string name="ShortMessageLifetime1h">1 Std.</string> <string name="ShortMessageLifetime1h">1 Std.</string>
<string name="ShortMessageLifetime1d">1 Tag</string> <string name="ShortMessageLifetime1d">1 Tag</string>
<string name="ShortMessageLifetime1w">1 Woche</string> <string name="ShortMessageLifetime1w">1 Woche</string>
<string name="EncryptionKeyDescription">Dieses Bild ist eine Visualisierung des geheimen Schlüssels für den geheimen Chat mit <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.<![CDATA[<br><br>]]>Wenn dieses Bild auf <![CDATA[<b>]]>%2$s\s<![CDATA[</b>]]> Telefon genau so aussieht, ist euer Chat zu 200%% sicher.<![CDATA[<br><br>]]>Erfahre mehr über die Sicherheit auf telegram.org</string> <string name="EncryptionKeyDescription">Das ist eine Darstellung des Schlüssels für den Geheimen Chat mit <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.<![CDATA[<br><br>]]>Wenn dieses Bild auf <![CDATA[<b>]]>%2$s\s<![CDATA[</b>]]>s Telefon genau so aussieht, ist euer Chat zu 200%% sicher.<![CDATA[<br><br>]]>Erfahre mehr auf telegram.org</string>
<!--settings view--> <!--settings view-->
<string name="ResetNotificationsText">Alle Einstellungen für Mitteilungen zurücksetzen</string> <string name="ResetNotificationsText">Alle Einstellungen für Mitteilungen zurücksetzen</string>
...@@ -317,7 +317,8 @@ ...@@ -317,7 +317,8 @@
<string name="EditVideo">Video bearbeiten</string> <string name="EditVideo">Video bearbeiten</string>
<string name="OriginalVideo">Originalvideo</string> <string name="OriginalVideo">Originalvideo</string>
<string name="EditedVideo">Bearbeitetes Video</string> <string name="EditedVideo">Bearbeitetes Video</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sende Video...</string>
<string name="CompressVideo">Video komprimieren</string>
<!--button titles--> <!--button titles-->
<string name="Next">Weiter</string> <string name="Next">Weiter</string>
...@@ -405,12 +406,12 @@ ...@@ -405,12 +406,12 @@
<string name="Page5Title">Leistungsstark</string> <string name="Page5Title">Leistungsstark</string>
<string name="Page6Title">Cloud-Basiert</string> <string name="Page6Title">Cloud-Basiert</string>
<string name="Page7Title">Vertraulich</string> <string name="Page7Title">Vertraulich</string>
<string name="Page1Message">Willkommen im Zeitalter der sicheren und schnellen Kommunikation.</string> <string name="Page1Message">Die <![CDATA[<b>schnellste</b>]]> Messaging App der Welt. <![CDATA[<b>Kostenlos</b>]]> und <![CDATA[<b>sicher</b>]]>.</string>
<string name="Page2Message"><![CDATA[<b>Telegram</b>]]> stellt Nachrichten schneller zu als andere Anwendungen</string> <string name="Page2Message"><![CDATA[<b>Telegram</b>]]> stellt Nachrichten schneller zu als alle andere Anwendungen</string>
<string name="Page3Message"><![CDATA[<b>Telegram</b>]]> ist für immer kostenlos. Keine Werbung. Keine Abo-Gebühr.</string> <string name="Page3Message"><![CDATA[<b>Telegram</b>]]> ist für immer kostenlos. Keine Werbung. <![CDATA[<br/>]]>Keine Abo-Gebühr.</string>
<string name="Page4Message"><![CDATA[<b>Telegram</b>]]> schützt deine Nachrichten vor Hacker-Angriffen</string> <string name="Page4Message"><![CDATA[<b>Telegram</b>]]> schützt deine Nachrichten vor Hacker-Angriffen</string>
<string name="Page5Message"><![CDATA[<b>Telegram</b>]]> unterstützt unbegrenzt große Chats und Mediendateien</string> <string name="Page5Message"><![CDATA[<b>Telegram</b>]]> unterstützt unbegrenzt große Chats und Mediendateien</string>
<string name="Page6Message"><![CDATA[<b>Telegram</b>]]> lässt sich von verschiedenen Geräten gleichzeitig nutzen</string> <string name="Page6Message"><![CDATA[<b>Telegram</b>]]> kannst du vom Handy, Tablet oder auch Computer syncronisiert benutzen</string>
<string name="Page7Message"><![CDATA[<b>Telegram</b>]]>-Nachrichten sind stark verschlüsselt und können sich selbst zerstören</string> <string name="Page7Message"><![CDATA[<b>Telegram</b>]]>-Nachrichten sind stark verschlüsselt und können sich selbst zerstören</string>
<string name="StartMessaging">Jetzt beginnen</string> <string name="StartMessaging">Jetzt beginnen</string>
......
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="OriginalVideo">Video originale</string> <string name="OriginalVideo">Video originale</string>
<string name="EditedVideo">Video modificato</string> <string name="EditedVideo">Video modificato</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sending video...</string>
<string name="CompressVideo">Compress Video</string>
<!--button titles--> <!--button titles-->
<string name="Next">Avanti</string> <string name="Next">Avanti</string>
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<string name="Yesterday">gisteren</string> <string name="Yesterday">gisteren</string>
<string name="NoResult">Geen resultaten</string> <string name="NoResult">Geen resultaten</string>
<string name="NoChats">Nog geen gesprekken…</string> <string name="NoChats">Nog geen gesprekken…</string>
<string name="NoChatsHelp">Tik op de opstelknop rechtsbovenin\nom een gesprek te beginnen\nof ga naar de contactenlijst.</string> <string name="NoChatsHelp">Begin een gesprek door op de\nopstellen-knop rechtsboven te drukken\nof druk op de menuknop voor meer opties.</string>
<string name="WaitingForNetwork">Wachten op netwerk…</string> <string name="WaitingForNetwork">Wachten op netwerk…</string>
<string name="Connecting">Verbinden…</string> <string name="Connecting">Verbinden…</string>
<string name="Updating">Bijwerken…</string> <string name="Updating">Bijwerken…</string>
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
<string name="EncryptedPlaceholderTitleOutgoing">Je hebt %s uitgenodigd voor een geheime chat.</string> <string name="EncryptedPlaceholderTitleOutgoing">Je hebt %s uitgenodigd voor een geheime chat.</string>
<string name="EncryptedDescriptionTitle">Geheime chat functies:</string> <string name="EncryptedDescriptionTitle">Geheime chat functies:</string>
<string name="EncryptedDescription1">End-to-end encryptie</string> <string name="EncryptedDescription1">End-to-end encryptie</string>
<string name="EncryptedDescription2">Ontraceerbaar via onze servers</string> <string name="EncryptedDescription2">Geen serveropslag</string>
<string name="EncryptedDescription3">Zelfvernietigingstimers</string> <string name="EncryptedDescription3">Zelfvernietigingstimers</string>
<string name="EncryptedDescription4">Doorstuurbescherming</string> <string name="EncryptedDescription4">Doorstuurbescherming</string>
<string name="YouWereKicked">Je bent verwijderd uit deze groep</string> <string name="YouWereKicked">Je bent verwijderd uit deze groep</string>
...@@ -171,8 +171,8 @@ ...@@ -171,8 +171,8 @@
<string name="OtherAt">om</string> <string name="OtherAt">om</string>
<string name="Online">online</string> <string name="Online">online</string>
<string name="Offline">offline</string> <string name="Offline">offline</string>
<string name="LastSeen">laatst gez.:</string> <string name="LastSeen">gezien</string>
<string name="LastSeenDate">laatst gez.:</string> <string name="LastSeenDate">gezien</string>
<string name="InviteFriends">Vrienden uitnodigen</string> <string name="InviteFriends">Vrienden uitnodigen</string>
<!--group create view--> <!--group create view-->
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
<string name="ShortMessageLifetime1h">1u</string> <string name="ShortMessageLifetime1h">1u</string>
<string name="ShortMessageLifetime1d">1d</string> <string name="ShortMessageLifetime1d">1d</string>
<string name="ShortMessageLifetime1w">1w</string> <string name="ShortMessageLifetime1w">1w</string>
<string name="EncryptionKeyDescription">Dit is een weergave van de encryptiesleutel voor deze geheime chat met <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.<![CDATA[<br><br>]]>Als deze afbeelding er bij <![CDATA[<b>]]>%2$s<![CDATA[</b>]]> hetzelfde uitziet, is jullie gesprek 200%% beveiligd.<![CDATA[<br><br>]]>Lees meer op telegram.org.</string> <string name="EncryptionKeyDescription">Dit is een weergave van de encryptiesleutel voor deze geheime chat met <![CDATA[<b>]]>%1$s<![CDATA[</b>]]>.\n\nAls deze afbeelding er bij <![CDATA[<b>]]>%2$s<![CDATA[</b>]]> hetzelfde uitziet, is jullie gesprek 200%% beveiligd.\n\nLees meer op telegram.org.</string>
<!--settings view--> <!--settings view-->
<string name="ResetNotificationsText">Alle meldingsinstellingen herstellen</string> <string name="ResetNotificationsText">Alle meldingsinstellingen herstellen</string>
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
<string name="InAppPreview">Voorvertoningen</string> <string name="InAppPreview">Voorvertoningen</string>
<string name="Reset">RESETTEN</string> <string name="Reset">RESETTEN</string>
<string name="ResetAllNotifications">Alle meldingen resetten</string> <string name="ResetAllNotifications">Alle meldingen resetten</string>
<string name="UndoAllCustom">Alle aangepaste meldingsinstellingen ongedaan maken voor alle contacten en groepen.</string> <string name="UndoAllCustom">Aangepaste meldingsinstellingen wissen voor contacten en groepen.</string>
<string name="NotificationsAndSounds">Meldingen en geluiden</string> <string name="NotificationsAndSounds">Meldingen en geluiden</string>
<string name="BlockedUsers">Geblokkeerde gebruikers</string> <string name="BlockedUsers">Geblokkeerde gebruikers</string>
<string name="SaveIncomingPhotos">Inkomende foto\'s opslaan</string> <string name="SaveIncomingPhotos">Inkomende foto\'s opslaan</string>
...@@ -259,7 +259,7 @@ ...@@ -259,7 +259,7 @@
<string name="ContactJoined">Contact lid van Telegram</string> <string name="ContactJoined">Contact lid van Telegram</string>
<string name="Pebble">PEBBLE</string> <string name="Pebble">PEBBLE</string>
<string name="Language">Taal</string> <string name="Language">Taal</string>
<string name="AskAQuestionInfo">Houd er rekening mee dat de ondersteuning van Telegram door vrijwilligers wordt gedaan. We doen ons best om zo snel mogelijk te antwoorden, maar het kan even even duren.<![CDATA[<br><br>]]>Bekijk ook de <![CDATA[<a href=\"http://telegram.org/faq#general\">veelgestelde vragen</a>]]>: hier staan de antwoorden op de meeste vragen en belangrijke tips voor <![CDATA[<a href=\"http://telegram.org/faq#troubleshooting\">het oplossen van problemen</a>]]>.</string> <string name="AskAQuestionInfo">Houd er rekening mee dat de ondersteuning van Telegram door vrijwilligers wordt gedaan. We doen ons best om zo snel mogelijk te antwoorden, maar het kan even even duren.\n\nBekijk ook de <![CDATA[<a href=\"http://telegram.org/faq#general\">veelgestelde vragen</a>]]>: hier staan de antwoorden op de meeste vragen en belangrijke tips voor <![CDATA[<a href=\"http://telegram.org/faq#troubleshooting\">het oplossen van problemen</a>]]>.</string>
<string name="AskButton">Vraag een vrijwilliger</string> <string name="AskButton">Vraag een vrijwilliger</string>
<string name="TelegramFaq">Veelgestelde vragen</string> <string name="TelegramFaq">Veelgestelde vragen</string>
<string name="TelegramFaqUrl">https://telegram.org/faq</string> <string name="TelegramFaqUrl">https://telegram.org/faq</string>
...@@ -317,7 +317,8 @@ ...@@ -317,7 +317,8 @@
<string name="EditVideo">Video bewerken</string> <string name="EditVideo">Video bewerken</string>
<string name="OriginalVideo">Originele video</string> <string name="OriginalVideo">Originele video</string>
<string name="EditedVideo">Bewerkte video</string> <string name="EditedVideo">Bewerkte video</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Video versturen...</string>
<string name="CompressVideo">Video comprimeren</string>
<!--button titles--> <!--button titles-->
<string name="Next">Volgende</string> <string name="Next">Volgende</string>
...@@ -387,7 +388,7 @@ ...@@ -387,7 +388,7 @@
<string name="DeleteChatQuestion">Dit gesprek verwijderen?</string> <string name="DeleteChatQuestion">Dit gesprek verwijderen?</string>
<string name="SendMessagesTo">Berichten naar %1$s verzenden?</string> <string name="SendMessagesTo">Berichten naar %1$s verzenden?</string>
<string name="AreYouSureLogout">Weet je zeker dat je wilt uitloggen?</string> <string name="AreYouSureLogout">Weet je zeker dat je wilt uitloggen?</string>
<string name="AreYouSureSessions">Weet je zeker dat je alle andere sessies wilt beëindigen?</string> <string name="AreYouSureSessions">Alle apparaten behalve het huidige apparaat uitloggen?</string>
<string name="AreYouSureDeleteAndExit">Weet je zeker dat je alles wilt verwijderen en de groep wilt verlaten?</string> <string name="AreYouSureDeleteAndExit">Weet je zeker dat je alles wilt verwijderen en de groep wilt verlaten?</string>
<string name="AreYouSureDeleteThisChat">Weet je zeker dat je dit gesprek wilt verwijderen?</string> <string name="AreYouSureDeleteThisChat">Weet je zeker dat je dit gesprek wilt verwijderen?</string>
<string name="AreYouSureShareMyContactInfo">Weet je zeker dat je je contactinformatie wilt delen?</string> <string name="AreYouSureShareMyContactInfo">Weet je zeker dat je je contactinformatie wilt delen?</string>
...@@ -405,13 +406,13 @@ ...@@ -405,13 +406,13 @@
<string name="Page5Title">Krachtig</string> <string name="Page5Title">Krachtig</string>
<string name="Page6Title">In de cloud</string> <string name="Page6Title">In de cloud</string>
<string name="Page7Title">Privé</string> <string name="Page7Title">Privé</string>
<string name="Page1Message">\'s Werelds <![CDATA[<b>snelste</b>]]> berichtendienst.<![CDATA[<br/>]]>Het is <![CDATA[<b>veilig</b>]]> en <![CDATA[<b>gratis</b>]]>.</string> <string name="Page1Message">\'s Werelds <![CDATA[<b>snelste</b>]]> berichtendienst.\nHet is <![CDATA[<b>veilig</b>]]> en <![CDATA[<b>gratis</b>]]>.</string>
<string name="Page2Message"><![CDATA[<b>Telegram</b>]]> bezorgt berichten<![CDATA[<br/>]]>sneller dan elke andere applicatie.</string> <string name="Page2Message"><![CDATA[<b>Telegram</b>]]> bezorgt berichten\nsneller dan elke andere applicatie.</string>
<string name="Page3Message"><![CDATA[<b>Telegram</b>]]> is altijd gratis. <![CDATA[<br/>]]>Geen advertenties.<![CDATA[<br/>]]>Geen abonnementskosten.</string> <string name="Page3Message"><![CDATA[<b>Telegram</b>]]> is altijd gratis. \nGeen advertenties.\nGeen abonnementskosten.</string>
<string name="Page4Message"><![CDATA[<b>Telegram</b>]]> beveiligt je berichten<![CDATA[<br/>]]>tegen aanvallen van hackers.</string> <string name="Page4Message"><![CDATA[<b>Telegram</b>]]> beveiligt je berichten\ntegen aanvallen van hackers.</string>
<string name="Page5Message"><![CDATA[<b>Telegram</b>]]> beperkt je niet<![CDATA[<br/>]]>in de grootte van je media of gesprekken.</string> <string name="Page5Message"><![CDATA[<b>Telegram</b>]]> beperkt je niet\nin de grootte van je media of gesprekken.</string>
<string name="Page6Message"><![CDATA[<b>Telegram</b>]]> biedt toegang tot je berichten<![CDATA[<br/>]]>vanaf meerdere apparaten.</string> <string name="Page6Message"><![CDATA[<b>Telegram</b>]]> biedt toegang tot je berichten\nvanaf meerdere apparaten.</string>
<string name="Page7Message"><![CDATA[<b>Telegram</b>]]> berichten zijn sterk versleuteld<![CDATA[<br/>]]>en kunnen zichzelf vernietigen</string> <string name="Page7Message"><![CDATA[<b>Telegram</b>]]> berichten zijn sterk versleuteld\nen kunnen zichzelf vernietigen.</string>
<string name="StartMessaging">Begin met chatten</string> <string name="StartMessaging">Begin met chatten</string>
<!--plurals--> <!--plurals-->
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<string name="Yesterday">ontem</string> <string name="Yesterday">ontem</string>
<string name="NoResult">Nenhum resultado</string> <string name="NoResult">Nenhum resultado</string>
<string name="NoChats">Ainda não há conversas...</string> <string name="NoChats">Ainda não há conversas...</string>
<string name="NoChatsHelp">Comece a conversar pressionando o\nbotão \'Nova Mensagem\' no canto superior direito\nou vá para a seção \'Contatos\'</string> <string name="NoChatsHelp">Comece a conversar pressionando o\nbotão \'Nova Mensagem\' no canto superior direito\nou vá para a seção \'Contatos\'.</string>
<string name="WaitingForNetwork">Aguardando rede...</string> <string name="WaitingForNetwork">Aguardando rede...</string>
<string name="Connecting">Conectando...</string> <string name="Connecting">Conectando...</string>
<string name="Updating">Atualizando...</string> <string name="Updating">Atualizando...</string>
...@@ -166,13 +166,13 @@ ...@@ -166,13 +166,13 @@
<string name="SelectContact">Selecionar Contato</string> <string name="SelectContact">Selecionar Contato</string>
<string name="NoContacts">Ainda não há contatos</string> <string name="NoContacts">Ainda não há contatos</string>
<string name="InviteText">Ei, vamos mudar para o Telegram: http://telegram.org/dl2</string> <string name="InviteText">Ei, vamos mudar para o Telegram: http://telegram.org/dl2</string>
<string name="TodayAt">hoje à(s)</string> <string name="TodayAt">hoje às</string>
<string name="YesterdayAt">ontem à(s)</string> <string name="YesterdayAt">ontem às</string>
<string name="OtherAt">em</string> <string name="OtherAt">às</string>
<string name="Online">online</string> <string name="Online">online</string>
<string name="Offline">offline</string> <string name="Offline">offline</string>
<string name="LastSeen">visto pela última vez</string> <string name="LastSeen">visto por último</string>
<string name="LastSeenDate">visto pela última vez</string> <string name="LastSeenDate">visto por último</string>
<string name="InviteFriends">Convidar Amigos</string> <string name="InviteFriends">Convidar Amigos</string>
<!--group create view--> <!--group create view-->
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="OriginalVideo">Vídeo Original</string> <string name="OriginalVideo">Vídeo Original</string>
<string name="EditedVideo">Vídeo Editado</string> <string name="EditedVideo">Vídeo Editado</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sending video...</string>
<string name="CompressVideo">Compress video</string>
<!--button titles--> <!--button titles-->
<string name="Next">Próximo</string> <string name="Next">Próximo</string>
...@@ -405,7 +406,7 @@ ...@@ -405,7 +406,7 @@
<string name="Page5Title">Poderoso</string> <string name="Page5Title">Poderoso</string>
<string name="Page6Title">Baseado na nuvem</string> <string name="Page6Title">Baseado na nuvem</string>
<string name="Page7Title">Privado</string> <string name="Page7Title">Privado</string>
<string name="Page1Message">Bem-vindo à era das mensagens<![CDATA[<br/>]]> rápidas e seguras</string> <string name="Page1Message">O Mais <![CDATA[<b>rápido</b>]]> aplicativo de mensagens\ndo mundo. É <![CDATA[<b>grátis</b>]]> e <![CDATA[<b>seguro</b>]]>.</string>
<string name="Page2Message"><![CDATA[<b>Telegram</b>]]> envia mensagens mais rapidamente do que qualquer outro aplicativo</string> <string name="Page2Message"><![CDATA[<b>Telegram</b>]]> envia mensagens mais rapidamente do que qualquer outro aplicativo</string>
<string name="Page3Message"><![CDATA[<b>Telegram</b>]]> será gratuito para sempre. Sem propagandas. Sem mensalidades</string> <string name="Page3Message"><![CDATA[<b>Telegram</b>]]> será gratuito para sempre. Sem propagandas. Sem mensalidades</string>
<string name="Page4Message"><![CDATA[<b>Telegram</b>]]> mantém suas mensagens seguras contra ataques de hackers</string> <string name="Page4Message"><![CDATA[<b>Telegram</b>]]> mantém suas mensagens seguras contra ataques de hackers</string>
......
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="OriginalVideo">Original Video</string> <string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string> <string name="EditedVideo">Edited Video</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sending video...</string>
<string name="CompressVideo">Compress Video</string>
<!--button titles--> <!--button titles-->
<string name="Next">Seguinte</string> <string name="Next">Seguinte</string>
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<string name="Yesterday">yesterday</string> <string name="Yesterday">yesterday</string>
<string name="NoResult">No results</string> <string name="NoResult">No results</string>
<string name="NoChats">No chats yet...</string> <string name="NoChats">No chats yet...</string>
<string name="NoChatsHelp">Start messaging by pressing the\ncompose button in the top right corner\nor go to the Contacts section.</string> <string name="NoChatsHelp">Start messaging by pressing the\ncompose button in the top right corner\nor tap the menu button for more options.</string>
<string name="WaitingForNetwork">Waiting for network...</string> <string name="WaitingForNetwork">Waiting for network...</string>
<string name="Connecting">Connecting...</string> <string name="Connecting">Connecting...</string>
<string name="Updating">Updating...</string> <string name="Updating">Updating...</string>
...@@ -259,7 +259,7 @@ ...@@ -259,7 +259,7 @@
<string name="ContactJoined">Contact joined Telegram</string> <string name="ContactJoined">Contact joined Telegram</string>
<string name="Pebble">PEBBLE</string> <string name="Pebble">PEBBLE</string>
<string name="Language">Language</string> <string name="Language">Language</string>
<string name="AskAQuestionInfo">Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.<![CDATA[<br><br>]]>Please take a look at the <![CDATA[<a href="http://telegram.org/faq#general">Telegram FAQ</a>]]>: it has answers to most questions and important tips for <![CDATA[<a href="http://telegram.org/faq#troubleshooting">troubleshooting</a>]]>.</string> <string name="AskAQuestionInfo">Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.<![CDATA[<br><br>]]>Please take a look at the <![CDATA[<a href=\"http://telegram.org/faq#general\">Telegram FAQ</a>]]>: it has answers to most questions and important tips for <![CDATA[<a href=\"http://telegram.org/faq#troubleshooting\">troubleshooting</a>]]>.</string>
<string name="AskButton">Ask a volunteer</string> <string name="AskButton">Ask a volunteer</string>
<string name="TelegramFaq">Telegram FAQ</string> <string name="TelegramFaq">Telegram FAQ</string>
<string name="TelegramFaqUrl">https://telegram.org/faq</string> <string name="TelegramFaqUrl">https://telegram.org/faq</string>
...@@ -277,8 +277,8 @@ ...@@ -277,8 +277,8 @@
<string name="LedColor">LED Color</string> <string name="LedColor">LED Color</string>
<string name="PopupNotification">Popup Notifications</string> <string name="PopupNotification">Popup Notifications</string>
<string name="NoPopup">No popup</string> <string name="NoPopup">No popup</string>
<string name="OnlyWhenScreenOn">Only when screen "on"</string> <string name="OnlyWhenScreenOn">Only when screen \"on\"</string>
<string name="OnlyWhenScreenOff">Only when screen "off"</string> <string name="OnlyWhenScreenOff">Only when screen \"off\"</string>
<string name="AlwaysShowPopup">Always show popup</string> <string name="AlwaysShowPopup">Always show popup</string>
<string name="BadgeNumber">Badge Counter</string> <string name="BadgeNumber">Badge Counter</string>
<string name="Short">Short</string> <string name="Short">Short</string>
...@@ -318,6 +318,7 @@ ...@@ -318,6 +318,7 @@
<string name="OriginalVideo">Original Video</string> <string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string> <string name="EditedVideo">Edited Video</string>
<string name="SendingVideo">Sending video...</string> <string name="SendingVideo">Sending video...</string>
<string name="CompressVideo">Compress Video</string>
<!--button titles--> <!--button titles-->
<string name="Next">Next</string> <string name="Next">Next</string>
...@@ -405,7 +406,7 @@ ...@@ -405,7 +406,7 @@
<string name="Page5Title">Powerful</string> <string name="Page5Title">Powerful</string>
<string name="Page6Title">Cloud-Based</string> <string name="Page6Title">Cloud-Based</string>
<string name="Page7Title">Private</string> <string name="Page7Title">Private</string>
<string name="Page1Message">The world\'s fastets messaging app.\nIt is free and secure.</string> <string name="Page1Message">The world\'s <![CDATA[<b>fastest</b>]]> messaging app.\nIt is <![CDATA[<b>free</b>]]> and <![CDATA[<b>secure</b>]]>.</string>
<string name="Page2Message"><![CDATA[<b>Telegram</b>]]> delivers messages faster than<![CDATA[<br/>]]>any other application</string> <string name="Page2Message"><![CDATA[<b>Telegram</b>]]> delivers messages faster than<![CDATA[<br/>]]>any other application</string>
<string name="Page3Message"><![CDATA[<b>Telegram</b>]]> is free forever. No ads.<![CDATA[<br/>]]>No subscription fees</string> <string name="Page3Message"><![CDATA[<b>Telegram</b>]]> is free forever. No ads.<![CDATA[<br/>]]>No subscription fees</string>
<string name="Page4Message"><![CDATA[<b>Telegram</b>]]> keeps your messages safe<![CDATA[<br/>]]>from hacker attacks</string> <string name="Page4Message"><![CDATA[<b>Telegram</b>]]> keeps your messages safe<![CDATA[<br/>]]>from hacker attacks</string>
......
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