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

Bug fixes

This commit is contained in:
DrKLO 2014-07-20 03:31:49 +04:00
parent d24578fe6b
commit 1c2010a428
45 changed files with 1255 additions and 78 deletions

View File

@ -83,7 +83,7 @@ android {
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 281
versionName "1.6.0"
versionCode 286
versionName "1.6.1"
}
}

View File

@ -174,15 +174,23 @@ public class AndroidUtilities {
public static File getCacheDir() {
if (externalCacheNotAvailableState == 1 || externalCacheNotAvailableState == 0 && Environment.getExternalStorageState().startsWith(Environment.MEDIA_MOUNTED)) {
externalCacheNotAvailableState = 1;
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
if (file != null) {
return file;
try {
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
if (file != null) {
return file;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
externalCacheNotAvailableState = 2;
File file = ApplicationLoader.applicationContext.getCacheDir();
if (file != null) {
return file;
try {
File file = ApplicationLoader.applicationContext.getCacheDir();
if (file != null) {
return file;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return new File("");
}

View File

@ -354,30 +354,45 @@ public class NotificationsController {
.setContentIntent(contentIntent);
String lastMessage = null;
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle(name);
int count = Math.min(10, pushMessages.size());
for (int i = 0; i < count; i++) {
String message = getStringForMessage(pushMessages.get(i));
if (pushMessages.size() == 1) {
String message = lastMessage = getStringForMessage(pushMessages.get(0));
if (message == null) {
continue;
return;
}
if (i == 0) {
lastMessage = message;
}
if (pushDialogs.size() == 1) {
if (replace) {
if (chat != null) {
message = message.replace(" @ " + name, "");
} else {
message = message.replace(name + ": ", "").replace(name + " ", "");
}
if (replace) {
if (chat != null) {
message = message.replace(" @ " + name, "");
} else {
message = message.replace(name + ": ", "").replace(name + " ", "");
}
}
inboxStyle.addLine(message);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
} else {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle(name);
int count = Math.min(10, pushMessages.size());
for (int i = 0; i < count; i++) {
String message = getStringForMessage(pushMessages.get(i));
if (message == null) {
continue;
}
if (i == 0) {
lastMessage = message;
}
if (pushDialogs.size() == 1) {
if (replace) {
if (chat != null) {
message = message.replace(" @ " + name, "");
} else {
message = message.replace(name + ": ", "").replace(name + " ", "");
}
}
}
inboxStyle.addLine(message);
}
inboxStyle.setSummaryText(detailText);
mBuilder.setStyle(inboxStyle);
}
inboxStyle.setSummaryText(detailText);
mBuilder.setStyle(inboxStyle);
if (photoPath != null) {
Bitmap img = FileLoader.getInstance().getImageFromMemory(photoPath, null, null, "50_50", false);
@ -547,38 +562,47 @@ public class NotificationsController {
public void processDialogsUpdateRead(final HashMap<Long, Integer> dialogsToUpdate, boolean replace) {
int old_unread_count = total_unread_count;
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
for (HashMap.Entry<Long, Integer> entry : dialogsToUpdate.entrySet()) {
Long dialog_id = entry.getKey();
long dialog_id = entry.getKey();
int notify_override = preferences.getInt("notify2_" + dialog_id, 0);
boolean isChat = (int)dialog_id < 0;
Integer currentCount = pushDialogs.get(dialog_id);
Integer newCount = entry.getValue();
if (replace) {
if (currentCount != null) {
total_unread_count -= currentCount;
}
if (newCount == 0) {
pushDialogs.remove(dialog_id);
if (!(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || isChat && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0)) {
Integer newCount = entry.getValue();
if (replace) {
if (currentCount != null) {
total_unread_count -= currentCount;
}
if (newCount == 0) {
pushDialogs.remove(dialog_id);
} else {
total_unread_count += newCount;
pushDialogs.put(dialog_id, newCount);
}
} else {
if (currentCount == null) {
currentCount = 0;
}
currentCount += newCount;
total_unread_count += newCount;
pushDialogs.put(dialog_id, newCount);
pushDialogs.put(dialog_id, currentCount);
}
} else {
if (currentCount == null) {
currentCount = 0;
}
currentCount += newCount;
total_unread_count += newCount;
pushDialogs.put(dialog_id, currentCount);
}
}
if (old_unread_count != total_unread_count) {
showOrUpdateNotification(notifyCheck);
notifyCheck = false;
}
setBadge(ApplicationLoader.applicationContext, total_unread_count);
if (preferences.getBoolean("badgeNumber", true)) {
setBadge(ApplicationLoader.applicationContext, total_unread_count);
}
}
public void processLoadedUnreadMessages(HashMap<Long, Integer> dialogs) {
pushDialogs.clear();
total_unread_count = 0;
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
String dialogsToLoad = "";
for (HashMap.Entry<Long, Integer> entry : dialogs.entrySet()) {
@ -594,7 +618,20 @@ public class NotificationsController {
dialogsToLoad += "" + dialog_id;
}
}
setBadge(ApplicationLoader.applicationContext, total_unread_count);
if (total_unread_count == 0) {
pushMessages.clear();
pushMessagesDict.clear();
popupMessages.clear();
showOrUpdateNotification(false);
NotificationCenter.getInstance().postNotificationName(pushMessagesUpdated);
}
if (preferences.getBoolean("badgeNumber", true)) {
setBadge(ApplicationLoader.applicationContext, total_unread_count);
}
}
public void setBadgeEnabled(boolean enabled) {
setBadge(ApplicationLoader.applicationContext, enabled ? total_unread_count : 0);
}
private void setBadge(Context context, int count) {

View File

@ -101,15 +101,18 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
public void run() {
Utilities.stageQueue.handler.removeCallbacks(stageRunnable);
if (datacenters != null) {
Datacenter datacenter = datacenterWithId(currentDatacenterId);
if (sendingPushPing && lastPushPingTime < System.currentTimeMillis() - 30000 || Math.abs(lastPushPingTime - System.currentTimeMillis()) > 60000 * 3 + 10000) {
lastPushPingTime = 0;
sendingPushPing = false;
if (datacenter != null && datacenter.pushConnection != null) {
datacenter.pushConnection.suspendConnection(true);
}
FileLog.e("tmessages", "push ping timeout");
}
if (lastPushPingTime < System.currentTimeMillis() - 60000 * 3) {
FileLog.e("tmessages", "time for push ping");
lastPushPingTime = System.currentTimeMillis();
Datacenter datacenter = datacenterWithId(currentDatacenterId);
if (datacenter != null) {
generatePing(datacenter, true);
}
@ -448,7 +451,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
datacenter = new Datacenter();
datacenter.datacenterId = 4;
datacenter.addAddressAndPort("31.210.235.12", 443);
datacenter.addAddressAndPort("149.154.167.90", 443);
datacenters.put(datacenter.datacenterId, datacenter);
datacenter = new Datacenter();
@ -2374,7 +2377,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
FileLog.e("tmessages", "no network available");
}
} catch (Exception e) {
FileLog.e("tmessages", "NETWORK STATE GET ERROR");
FileLog.e("tmessages", "NETWORK STATE GET ERROR", e);
}
}
final int stateCopy = connectionState;

View File

@ -674,7 +674,7 @@ public class FileLoadOperation {
}
}
if (downloadedBytes % downloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) {
if (totalBytesCount != downloadedBytes && downloadedBytes % downloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) {
startDownloadRequest();
} else {
onFinishLoadingFile();

View File

@ -174,17 +174,13 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
}
ByteBufferDesc sendMessageData(TLObject message, long messageId) {
ByteBufferDesc innerOs = BuffersStorage.getInstance().getFreeBuffer(message.getObjectSize());
message.serializeToStream(innerOs);
message.freeResources();
ByteBufferDesc messageOs = BuffersStorage.getInstance().getFreeBuffer(8 + 8 + 4 + innerOs.length());
int messageLength = message.getObjectSize();
ByteBufferDesc messageOs = BuffersStorage.getInstance().getFreeBuffer(8 + 8 + 4 + messageLength);
messageOs.writeInt64(0);
messageOs.writeInt64(messageId);
messageOs.writeInt32(innerOs.length());
innerOs.position(0);
messageOs.writeRaw(innerOs);
BuffersStorage.getInstance().reuseFreeBuffer(innerOs);
messageOs.writeInt32(messageLength);
message.serializeToStream(messageOs);
message.freeResources();
datacenter.connection.sendData(messageOs, false, false);
return messageOs;

View File

@ -30,6 +30,7 @@ import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ContactsController;
import org.telegram.android.NotificationsService;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ConnectionsManager;
@ -128,6 +129,8 @@ public class ApplicationLoader extends Application {
ApplicationLoader app = (ApplicationLoader)ApplicationLoader.applicationContext;
app.initPlayServices();
FileLog.e("tmessages", "app initied");
ContactsController.getInstance().checkAppAccount();
}
@Override

View File

@ -307,7 +307,7 @@ public class ChatOrUserCell extends BaseCell {
nameString = nameString2.replace("\n", " ");
}
if (nameString.length() == 0) {
if (user.phone != null && user.phone.length() != 0) {
if (user != null && user.phone != null && user.phone.length() != 0) {
nameString = PhoneFormat.getInstance().format("+" + user.phone);
} else {
nameString = LocaleController.getString("HiddenName", R.string.HiddenName);

View File

@ -89,7 +89,8 @@ import java.util.HashMap;
import java.util.concurrent.Semaphore;
public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate,
DocumentSelectActivity.DocumentSelectActivityDelegate, PhotoViewer.PhotoViewerProvider, PhotoPickerActivity.PhotoPickerActivityDelegate {
DocumentSelectActivity.DocumentSelectActivityDelegate, PhotoViewer.PhotoViewerProvider, PhotoPickerActivity.PhotoPickerActivityDelegate,
VideoEditorActivity.VideoEditorActivityDelegate {
private ChatActivityEnterView chatActivityEnterView;
private View timeItem;
@ -1318,7 +1319,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
currentPicturePath = null;
}
processSendingVideo(videoPath);
/*if(android.os.Build.VERSION.SDK_INT >= 10) {
Bundle args = new Bundle();
args.putString("videoPath", videoPath);
VideoEditorActivity fragment = new VideoEditorActivity(args);
fragment.setDelegate(this);
presentFragment(fragment);
} else {*/
processSendingVideo(videoPath);
//}
} else if (requestCode == 21) {
if (data == null || data.getData() == null) {
showAttachmentError();
@ -1339,6 +1348,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public void didFinishedVideoConverting(String videoPath) {
processSendingVideo(videoPath);
}
private void showAttachmentError() {
if (getParentActivity() == null) {
return;

View File

@ -133,6 +133,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
}
avatarImageView = (BackupImageView)fragmentView.findViewById(R.id.location_avatar_view);
if (avatarImageView != null) {
avatarImageView.processDetach = false;
}
nameTextView = (TextView)fragmentView.findViewById(R.id.location_name_label);
distanceTextView = (TextView)fragmentView.findViewById(R.id.location_distance_label);
View bottomView = fragmentView.findViewById(R.id.location_bottom_view);

View File

@ -506,12 +506,12 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
builder.setMessage(LocaleController.formatStringSimple(selectAlertString, Utilities.formatName(user.first_name, user.last_name)));
}
CheckBox checkBox = null;
if (delegate instanceof ChatActivity) {
/*if (delegate instanceof ChatActivity) {
checkBox = new CheckBox(getParentActivity());
checkBox.setText(LocaleController.getString("ForwardFromMyName", R.string.ForwardFromMyName));
checkBox.setChecked(false);
builder.setView(checkBox);
}
}*/
final CheckBox checkBoxFinal = checkBox;
builder.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
@Override

View File

@ -150,6 +150,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
NotificationCenter.getInstance().addObserver(this, MessagesController.updateInterfaces);
NotificationCenter.getInstance().addObserver(this, MediaController.audioProgressDidChanged);
NotificationCenter.getInstance().addObserver(this, MediaController.audioDidReset);
NotificationCenter.getInstance().addObserver(this, MessagesController.contactsDidLoaded);
NotificationCenter.getInstance().addObserver(this, 999);
chatActivityEnterView = new ChatActivityEnterView();
@ -940,6 +941,8 @@ public class PopupNotificationActivity extends Activity implements NotificationC
view.invalidate();
}
}
} else if (id == MessagesController.contactsDidLoaded) {
updateSubtitle();
}
}
@ -962,6 +965,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
NotificationCenter.getInstance().removeObserver(this, MessagesController.updateInterfaces);
NotificationCenter.getInstance().removeObserver(this, MediaController.audioProgressDidChanged);
NotificationCenter.getInstance().removeObserver(this, MediaController.audioDidReset);
NotificationCenter.getInstance().removeObserver(this, MessagesController.contactsDidLoaded);
NotificationCenter.getInstance().removeObserver(this, 999);
if (chatActivityEnterView != null) {
chatActivityEnterView.onDestroy();

View File

@ -293,7 +293,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
} else if (i == notificationRow) {
presentFragment(new SettingsNotificationsActivity());
} else if (i == blockedRow) {
presentFragment(new SettingsBlockedUsers());
presentFragment(new SettingsBlockedUsersActivity());
} else if (i == backgroundRow) {
presentFragment(new SettingsWallpapersActivity());
} else if (i == askQuestionRow) {

View File

@ -38,7 +38,7 @@ import org.telegram.ui.Views.ActionBar.BaseFragment;
import java.util.ArrayList;
import java.util.HashMap;
public class SettingsBlockedUsers extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ContactsActivity.ContactsActivityDelegate {
public class SettingsBlockedUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ContactsActivity.ContactsActivityDelegate {
private ListView listView;
private ListAdapter listViewAdapter;
private boolean loading;
@ -82,7 +82,7 @@ public class SettingsBlockedUsers extends BaseFragment implements NotificationCe
args.putBoolean("usersAsSections", true);
args.putBoolean("returnAsResult", true);
ContactsActivity fragment = new ContactsActivity(args);
fragment.setDelegate(SettingsBlockedUsers.this);
fragment.setDelegate(SettingsBlockedUsersActivity.this);
presentFragment(fragment);
}
}

View File

@ -28,6 +28,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.telegram.android.LocaleController;
import org.telegram.android.NotificationsController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC;
@ -67,7 +68,8 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
private int inappPreviewRow;
private int eventsSectionRow;
private int contactJoinedRow;
private int pebbleSectionRow;
private int otherSectionRow;
private int badgeNumberRow;
private int pebbleAlertRow;
private int resetSectionRow;
private int resetNotificationsRow;
@ -96,7 +98,8 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
inappPreviewRow = rowCount++;
eventsSectionRow = rowCount++;
contactJoinedRow = rowCount++;
pebbleSectionRow = rowCount++;
otherSectionRow = rowCount++;
badgeNumberRow = rowCount++;
pebbleAlertRow = rowCount++;
resetSectionRow = rowCount++;
resetNotificationsRow = rowCount++;
@ -279,6 +282,14 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
editor.putBoolean("EnablePebbleNotifications", !enabled);
editor.commit();
listView.invalidateViews();
} else if (i == badgeNumberRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
boolean enabled = preferences.getBoolean("badgeNumber", true);
editor.putBoolean("badgeNumber", !enabled);
editor.commit();
listView.invalidateViews();
NotificationsController.getInstance().setBadgeEnabled(!enabled);
} else if (i == notificationsServiceRow) {
final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
boolean enabled = preferences.getBoolean("pushService", true);
@ -480,7 +491,7 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
@Override
public boolean isEnabled(int i) {
return !(i == messageSectionRow || i == groupSectionRow || i == inappSectionRow || i == eventsSectionRow || i == pebbleSectionRow || i == resetSectionRow);
return !(i == messageSectionRow || i == groupSectionRow || i == inappSectionRow || i == eventsSectionRow || i == otherSectionRow || i == resetSectionRow);
}
@Override
@ -520,8 +531,8 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
textView.setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications));
} else if (i == eventsSectionRow) {
textView.setText(LocaleController.getString("Events", R.string.Events));
} else if (i == pebbleSectionRow) {
textView.setText(LocaleController.getString("Pebble", R.string.Pebble));
} else if (i == otherSectionRow) {
textView.setText(LocaleController.getString("PhoneOther", R.string.PhoneOther));
} else if (i == resetSectionRow) {
textView.setText(LocaleController.getString("Reset", R.string.Reset));
}
@ -581,12 +592,16 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
divider.setVisibility(View.INVISIBLE);
} else if (i == pebbleAlertRow) {
enabled = preferences.getBoolean("EnablePebbleNotifications", false);
textView.setText(LocaleController.getString("Alert", R.string.Alert));
textView.setText(LocaleController.getString("Pebble", R.string.Pebble));
divider.setVisibility(View.INVISIBLE);
} else if (i == notificationsServiceRow) {
enabled = preferences.getBoolean("pushService", true);
textView.setText(LocaleController.getString("NotificationsService", R.string.NotificationsService));
divider.setVisibility(View.INVISIBLE);
} else if (i == badgeNumberRow) {
enabled = preferences.getBoolean("badgeNumber", true);
textView.setText(LocaleController.getString("BadgeNumber", R.string.BadgeNumber));
divider.setVisibility(View.VISIBLE);
}
if (enabled) {
checkButton.setImageResource(R.drawable.btn_check_on);
@ -664,13 +679,13 @@ public class SettingsNotificationsActivity extends BaseFragment implements Notif
@Override
public int getItemViewType(int i) {
if (i == messageSectionRow || i == groupSectionRow || i == inappSectionRow || i == eventsSectionRow || i == pebbleSectionRow || i == resetSectionRow) {
if (i == messageSectionRow || i == groupSectionRow || i == inappSectionRow || i == eventsSectionRow || i == otherSectionRow || i == resetSectionRow) {
return 0;
} else if (i == messageAlertRow || i == messagePreviewRow || i == messageVibrateRow ||
i == groupAlertRow || i == groupPreviewRow || i == groupVibrateRow ||
i == inappSoundRow || i == inappVibrateRow || i == inappPreviewRow ||
i == contactJoinedRow ||
i == pebbleAlertRow || i == notificationsServiceRow) {
i == pebbleAlertRow || i == notificationsServiceRow || i == badgeNumberRow) {
return 1;
} else if (i == messageLedRow || i == groupLedRow) {
return 3;

View File

@ -0,0 +1,552 @@
/*
* This is the source code of Telegram for Android v. 1.7.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2014.
*/
package org.telegram.ui;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.coremedia.iso.boxes.Container;
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 org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
import org.telegram.ui.Views.ActionBar.BaseFragment;
import org.telegram.ui.Views.VideoSeekBarView;
import org.telegram.ui.Views.VideoTimelineView;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class VideoEditorActivity extends BaseFragment implements SurfaceHolder.Callback {
private MediaPlayer videoPlayer = null;
private SurfaceHolder surfaceHolder = null;
private VideoTimelineView videoTimelineView = null;
private View videoContainerView = null;
private TextView originalSizeTextView = null;
private TextView editedSizeTextView = null;
private View textContainerView = null;
private ImageView playButton = null;
private VideoSeekBarView videoSeekBarView = null;
private boolean initied = false;
private String videoPath = null;
private int videoWidth;
private int videoHeight;
private float lastProgress = 0;
private boolean needSeek = false;
private VideoEditorActivityDelegate delegate;
public interface VideoEditorActivityDelegate {
public abstract void didFinishedVideoConverting(String videoPath);
}
private Runnable progressRunnable = new Runnable() {
@Override
public void run() {
while (videoPlayer.isPlaying()) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (videoPlayer.isPlaying()) {
float startTime = videoTimelineView.getLeftProgress() * videoPlayer.getDuration();
float endTime = videoTimelineView.getRightProgress() * videoPlayer.getDuration();
if (startTime == endTime) {
startTime = endTime - 0.01f;
}
float progress = (videoPlayer.getCurrentPosition() - startTime) / (endTime - startTime);
if (progress > lastProgress) {
videoSeekBarView.setProgress(progress);
lastProgress = progress;
}
if (videoPlayer.getCurrentPosition() >= endTime) {
try {
videoPlayer.pause();
onPlayComplete();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
}
});
try {
Thread.sleep(50);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
};
public VideoEditorActivity(Bundle args) {
super(args);
videoPath = args.getString("videoPath");
}
@Override
public boolean onFragmentCreate() {
if (videoPath == null) {
return false;
}
videoPlayer = new MediaPlayer();
videoPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
onPlayComplete();
}
});
}
});
return super.onFragmentCreate();
}
@Override
public void onFragmentDestroy() {
if (videoTimelineView != null) {
videoTimelineView.destroy();
}
super.onFragmentDestroy();
}
@Override
public View createView(LayoutInflater inflater, ViewGroup container) {
if (fragmentView == null) {
actionBarLayer.setBackgroundColor(0xff333333);
actionBarLayer.setItemsBackground(R.drawable.bar_selector_white);
actionBarLayer.setDisplayHomeAsUpEnabled(true, R.drawable.photo_back);
actionBarLayer.setTitle(LocaleController.getString("EditVideo", R.string.EditVideo));
actionBarLayer.setActionBarMenuOnItemClick(new ActionBarLayer.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
} else if (id == 1) {
try {
startConvert();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
});
ActionBarMenu menu = actionBarLayer.createMenu();
View doneItem = menu.addItemResource(1, R.layout.group_create_done_layout);
TextView doneTextView = (TextView)doneItem.findViewById(R.id.done_button);
doneTextView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase());
fragmentView = inflater.inflate(R.layout.video_editor_layout, container, false);
originalSizeTextView = (TextView)fragmentView.findViewById(R.id.original_size);
editedSizeTextView = (TextView)fragmentView.findViewById(R.id.edited_size);
videoContainerView = fragmentView.findViewById(R.id.video_container);
textContainerView = fragmentView.findViewById(R.id.info_container);
videoTimelineView = (VideoTimelineView)fragmentView.findViewById(R.id.video_timeline_view);
videoTimelineView.setVideoPath(videoPath);
videoTimelineView.setDelegate(new VideoTimelineView.VideoTimelineViewDelegate() {
@Override
public void onLeftProgressChanged(float progress) {
try {
if (videoPlayer.isPlaying()) {
videoPlayer.pause();
playButton.setImageResource(R.drawable.video_play);
}
videoPlayer.setOnSeekCompleteListener(null);
videoPlayer.seekTo((int)(videoPlayer.getDuration() * progress));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
needSeek = true;
videoSeekBarView.setProgress(0);
updateVideoEditedInfo();
}
@Override
public void onRifhtProgressChanged(float progress) {
try {
if (videoPlayer.isPlaying()) {
videoPlayer.pause();
playButton.setImageResource(R.drawable.video_play);
}
videoPlayer.setOnSeekCompleteListener(null);
videoPlayer.seekTo((int)(videoPlayer.getDuration() * progress));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
needSeek = true;
videoSeekBarView.setProgress(0);
updateVideoEditedInfo();
}
});
videoSeekBarView = (VideoSeekBarView)fragmentView.findViewById(R.id.video_seekbar);
videoSeekBarView.delegate = new VideoSeekBarView.SeekBarDelegate() {
@Override
public void onSeekBarDrag(float progress) {
if (videoPlayer.isPlaying()) {
try {
float prog = videoTimelineView.getLeftProgress() + (videoTimelineView.getRightProgress() - videoTimelineView.getLeft()) * progress;
videoPlayer.seekTo((int)(videoPlayer.getDuration() * prog));
lastProgress = progress;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
} else {
lastProgress = progress;
needSeek = true;
}
}
};
playButton = (ImageView)fragmentView.findViewById(R.id.play_button);
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);
updateVideoOriginalInfo();
updateVideoEditedInfo();
} else {
ViewGroup parent = (ViewGroup)fragmentView.getParent();
if (parent != null) {
parent.removeView(fragmentView);
}
}
return fragmentView;
}
@Override
public void onResume() {
super.onResume();
fixLayout();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fixLayout();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
videoPlayer.setDisplay(holder);
try {
videoPlayer.setDataSource(videoPath);
videoPlayer.prepare();
videoWidth = videoPlayer.getVideoWidth();
videoHeight = videoPlayer.getVideoHeight();
fixVideoSize();
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoPlayer.getDuration()));
initied = true;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
updateVideoOriginalInfo();
updateVideoEditedInfo();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
videoPlayer.setDisplay(null);
}
private void onPlayComplete() {
playButton.setImageResource(R.drawable.video_play);
videoSeekBarView.setProgress(0);
try {
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoPlayer.getDuration()));
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
private void updateVideoOriginalInfo() {
if (!initied || 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;
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));
}
private void updateVideoEditedInfo() {
if (!initied || editedSizeTextView == null) {
return;
}
File file = new File(videoPath);
long size = file.length();
float videoWidth = videoPlayer.getVideoWidth();
float videoHeight = videoPlayer.getVideoHeight();
if (videoWidth > 640 || videoHeight > 640) {
float scale = videoWidth > videoHeight ? 640.0f / videoWidth : 640.0f / videoHeight;
videoWidth *= scale;
videoHeight *= scale;
size *= (scale * scale);
}
String videoDimension = String.format("%dx%d", (int)videoWidth, (int)videoHeight);
int minutes = videoPlayer.getDuration() / 1000 / 60;
int seconds = (int)Math.ceil(videoPlayer.getDuration() / 1000) - minutes * 60;
String videoTimeSize = String.format("%d:%02d, ~%s", minutes, seconds, Utilities.formatFileSize(size));
editedSizeTextView.setText(String.format("%s: %s, %s", LocaleController.getString("EditedVideo", R.string.EditedVideo), videoDimension, videoTimeSize));
}
private void fixVideoSize() {
if (videoWidth == 0 || videoHeight == 0 || fragmentView == null || getParentActivity() == null) {
return;
}
int viewHeight = 0;
if (!Utilities.isTablet(getParentActivity()) && 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 (getParentActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
width = AndroidUtilities.displaySize.x - AndroidUtilities.displaySize.x / 2 - AndroidUtilities.dp(24);
height = viewHeight - AndroidUtilities.dp(32);
} else {
width = AndroidUtilities.displaySize.x;
height = viewHeight - AndroidUtilities.dp(176);
}
float wr = (float)width / (float)videoWidth;
float hr = (float)height / (float)videoHeight;
float ar = (float)videoWidth / (float)videoHeight;
if (wr > hr) {
width = (int) (height * ar);
} else {
height = (int) (width / ar);
}
surfaceHolder.setFixedSize(width, height);
}
private void fixLayout() {
if (originalSizeTextView == null) {
return;
}
originalSizeTextView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
originalSizeTextView.getViewTreeObserver().removeOnPreDrawListener(this);
if (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.leftMargin = AndroidUtilities.dp(16);
videoContainerView.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.rightMargin = AndroidUtilities.dp(16);
layoutParams.topMargin = 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.width = FrameLayout.LayoutParams.MATCH_PARENT;
layoutParams.leftMargin = 0;
videoContainerView.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;
textContainerView.setLayoutParams(layoutParams);
}
fixVideoSize();
videoTimelineView.clearFrames();
return false;
}
});
}
private void play() {
if (videoPlayer.isPlaying()) {
videoPlayer.pause();
playButton.setImageResource(R.drawable.video_play);
} else {
try {
playButton.setImageDrawable(null);
lastProgress = 0;
if (needSeek) {
float prog = videoTimelineView.getLeftProgress() + (videoTimelineView.getRightProgress() - videoTimelineView.getLeft()) * videoSeekBarView.getProgress();
videoPlayer.seekTo((int)(videoPlayer.getDuration() * 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();
if (startTime == endTime) {
startTime = endTime - 0.01f;
}
lastProgress = (videoPlayer.getCurrentPosition() - startTime) / (endTime - startTime);
videoSeekBarView.setProgress(lastProgress);
}
});
videoPlayer.start();
new Thread(progressRunnable).start();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}
public void setDelegate(VideoEditorActivityDelegate delegate) {
this.delegate = delegate;
}
private void startConvert() throws Exception {
Movie movie = MovieCreator.build(videoPath);
List<Track> tracks = movie.getTracks();
movie.setTracks(new LinkedList<Track>());
double startTime = videoTimelineView.getLeftProgress() * videoPlayer.getDuration() / 1000.0;
double endTime = videoTimelineView.getRightProgress() * videoPlayer.getDuration() / 1000.0;
boolean timeCorrected = false;
for (Track track : tracks) {
if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
if (timeCorrected) {
throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
}
startTime = correctTimeToSyncSample(track, startTime, false);
endTime = correctTimeToSyncSample(track, endTime, true);
timeCorrected = true;
}
}
for (Track track : tracks) {
long currentSample = 0;
double currentTime = 0;
double lastTime = 0;
long startSample = -1;
long endSample = -1;
for (int i = 0; i < track.getSampleDurations().length; i++) {
long delta = track.getSampleDurations()[i];
if (currentTime > lastTime && currentTime <= startTime) {
startSample = currentSample;
}
if (currentTime > lastTime && currentTime <= endTime) {
endSample = currentSample;
}
lastTime = currentTime;
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
currentSample++;
}
movie.addTrack(new CroppedTrack(track, startSample, endSample));
}
long start1 = System.currentTimeMillis();
Container out = new DefaultMp4Builder().build(movie);
long start2 = System.currentTimeMillis();
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
UserConfig.lastLocalId--;
File cacheFile = new File(AndroidUtilities.getCacheDir(), fileName);
UserConfig.saveConfig(false);
FileOutputStream fos = new FileOutputStream(cacheFile);
FileChannel fc = fos.getChannel();
out.writeContainer(fc);
fc.close();
fos.close();
if (delegate != null) {
delegate.didFinishedVideoConverting(cacheFile.getAbsolutePath());
finishFragment();
}
}
private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
long currentSample = 0;
double currentTime = 0;
for (int i = 0; i < track.getSampleDurations().length; i++) {
long delta = track.getSampleDurations()[i];
if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
}
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
currentSample++;
}
double previous = 0;
for (double timeOfSyncSample : timeOfSyncSamples) {
if (timeOfSyncSample > cutHere) {
if (next) {
return timeOfSyncSample;
} else {
return previous;
}
}
previous = timeOfSyncSample;
}
return timeOfSyncSamples[timeOfSyncSamples.length - 1];
}
}

View File

@ -15,6 +15,8 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import org.telegram.messenger.FileLog;
public class ClippingImageView extends View {
private int clipBottom;
private int clipLeft;
@ -64,7 +66,11 @@ public class ClippingImageView extends View {
canvas.save();
canvas.clipRect(clipLeft / getScaleY(), clipTop / getScaleY(), getWidth() - clipRight / getScaleY(), getHeight() - clipBottom / getScaleY());
drawRect.set(0, 0, getWidth(), getHeight());
canvas.drawBitmap(this.bmp, null, drawRect, this.paint);
try {
canvas.drawBitmap(this.bmp, null, drawRect, this.paint);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
canvas.restore();
}
}

View File

@ -0,0 +1,133 @@
/*
* This is the source code of Telegram for Android v. 1.7.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2014.
*/
package org.telegram.ui.Views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import org.telegram.android.AndroidUtilities;
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;
private int thumbDX = 0;
private float progress = 0;
private boolean pressed = false;
public SeekBarDelegate delegate;
public abstract interface SeekBarDelegate {
public void onSeekBarDrag(float progress);
}
private void init(Context context) {
if (thumbDrawable1 == null) {
thumbDrawable1 = context.getResources().getDrawable(R.drawable.playback);
thumbDrawablePressed1 = context.getResources().getDrawable(R.drawable.playback_active);
innerPaint1.setColor(0x99999999);
thumbWidth = thumbDrawable1.getIntrinsicWidth();
thumbHeight = thumbDrawable1.getIntrinsicHeight();
}
}
public VideoSeekBarView(Context context) {
super(context);
init(context);
}
public VideoSeekBarView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public VideoSeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event == null) {
return false;
}
float x = event.getX();
float y = event.getY();
float thumbX = (int)((getMeasuredWidth() - thumbWidth) * progress);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int additionWidth = (getMeasuredHeight() - thumbWidth) / 2;
if (thumbX - additionWidth <= x && x <= thumbX + thumbWidth + additionWidth && y >= 0 && y <= getMeasuredHeight()) {
pressed = true;
thumbDX = (int)(x - thumbX);
getParent().requestDisallowInterceptTouchEvent(true);
invalidate();
return true;
}
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
if (pressed) {
if (event.getAction() == MotionEvent.ACTION_UP && delegate != null) {
delegate.onSeekBarDrag(thumbX / (float)(getMeasuredWidth() - thumbWidth));
}
pressed = false;
invalidate();
return true;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (pressed) {
thumbX = (int)(x - thumbDX);
if (thumbX < 0) {
thumbX = 0;
} else if (thumbX > getMeasuredWidth() - thumbWidth) {
thumbX = getMeasuredWidth() - thumbWidth;
}
progress = thumbX / (getMeasuredWidth() - thumbWidth);
invalidate();
return true;
}
}
return false;
}
public void setProgress(float progress) {
if (progress < 0) {
progress = 0;
} else if (progress > 1) {
progress = 1;
}
this.progress = progress;
invalidate();
}
public float getProgress() {
return progress;
}
@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);
}
}

View File

@ -0,0 +1,285 @@
/*
* 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.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.MediaMetadataRetriever;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog;
import java.util.ArrayList;
@TargetApi(10)
public class VideoTimelineView extends View {
private long videoLength = 0;
private float progressLeft = 0;
private float progressRight = 1;
private Paint paint;
private Paint paint2;
private boolean pressedLeft = false;
private boolean pressedRight = false;
private float pressDx = 0;
private MediaMetadataRetriever mediaMetadataRetriever = null;
private VideoTimelineViewDelegate delegate = null;
private ArrayList<Bitmap> frames = new ArrayList<Bitmap>();
private AsyncTask<Integer, Integer, Bitmap> currentTask = null;
private static final Integer sync = 1;
private long frameTimeOffset = 0;
private int frameWidth = 0;
private int frameHeight = 0;
private int framesToLoad = 0;
public abstract interface VideoTimelineViewDelegate {
public void onLeftProgressChanged(float progress);
public void onRifhtProgressChanged(float progress);
}
private void init() {
paint = new Paint();
paint.setColor(0xff66d1ee);
paint2 = new Paint();
paint2.setColor(0x2266d1ee);
}
public VideoTimelineView(Context context) {
super(context);
init();
}
public VideoTimelineView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public VideoTimelineView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public float getLeftProgress() {
return progressLeft;
}
public float getRightProgress() {
return progressRight;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event == null) {
return false;
}
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);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int additionWidth = AndroidUtilities.dp(12);
if (startX - additionWidth <= x && x <= startX + additionWidth && y >= 0 && y <= getMeasuredHeight()) {
pressedLeft = true;
pressDx = (int)(x - startX);
getParent().requestDisallowInterceptTouchEvent(true);
invalidate();
return true;
} else if (endX - additionWidth <= x && x <= endX + additionWidth && y >= 0 && y <= getMeasuredHeight()) {
pressedRight = true;
pressDx = (int)(x - endX);
getParent().requestDisallowInterceptTouchEvent(true);
invalidate();
return true;
}
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
if (pressedLeft) {
pressedLeft = false;
return true;
} else if (pressedRight) {
pressedRight = false;
return true;
}
} 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);
}
progressLeft = (float)(startX - AndroidUtilities.dp(3)) / (float)width;
if (delegate != null) {
delegate.onLeftProgressChanged(progressLeft);
}
invalidate();
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);
}
progressRight = (float)(endX - AndroidUtilities.dp(9)) / (float)width;
if (delegate != null) {
delegate.onRifhtProgressChanged(progressRight);
}
invalidate();
return true;
}
}
return false;
}
public void setVideoPath(String path) {
mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(path);
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
videoLength = Long.parseLong(duration);
}
public void setDelegate(VideoTimelineViewDelegate delegate) {
this.delegate = delegate;
}
private void reloadFrames(int frameNum) {
if (mediaMetadataRetriever == null) {
return;
}
if (frameNum == 0) {
frameHeight = getMeasuredHeight() - AndroidUtilities.dp(4);
framesToLoad = getMeasuredWidth() / frameHeight;
frameWidth = (int)Math.ceil((float)getMeasuredWidth() / (float)framesToLoad);
frameTimeOffset = videoLength / framesToLoad;
}
currentTask = new AsyncTask<Integer, Integer, Bitmap>() {
private int frameNum = 0;
@Override
protected Bitmap doInBackground(Integer... objects) {
frameNum = objects[0];
Bitmap bitmap = null;
if (isCancelled()) {
return null;
}
try {
bitmap = mediaMetadataRetriever.getFrameAtTime(frameTimeOffset * frameNum * 1000);
if (isCancelled()) {
return null;
}
if (bitmap != null) {
Bitmap result = Bitmap.createBitmap(frameWidth, frameHeight, bitmap.getConfig());
Canvas canvas = new Canvas(result);
float scaleX = (float) frameWidth / (float) bitmap.getWidth();
float scaleY = (float) frameHeight / (float) bitmap.getHeight();
float scale = scaleX > scaleY ? scaleX : scaleY;
int w = (int) (bitmap.getWidth() * scale);
int h = (int) (bitmap.getHeight() * scale);
Rect srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect destRect = new Rect((frameWidth - w) / 2, (frameHeight - h) / 2, w, h);
Paint paint = new Paint();
canvas.drawBitmap(bitmap, srcRect, destRect, null);
bitmap.recycle();
bitmap = result;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (!isCancelled()) {
frames.add(bitmap);
invalidate();
if (frameNum < framesToLoad) {
reloadFrames(frameNum + 1);
}
}
}
};
if (android.os.Build.VERSION.SDK_INT >= 11) {
currentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, frameNum, null, null);
} else {
currentTask.execute(frameNum, null, null);
}
}
public void destroy() {
synchronized (sync) {
try {
if (mediaMetadataRetriever != null) {
mediaMetadataRetriever.release();
mediaMetadataRetriever = null;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
for (Bitmap bitmap : frames) {
if (bitmap != null) {
bitmap.recycle();
}
}
frames.clear();
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
}
public void clearFrames() {
for (Bitmap bitmap : frames) {
if (bitmap != null) {
bitmap.recycle();
}
}
frames.clear();
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
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);
}
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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -1,13 +1,15 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp">
android:layout_height="40dp"
android:layout_gravity="top">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="27dp"
android:background="@drawable/newmsg_divider"
android:layout_marginTop="7dp">
android:layout_marginTop="7dp"
android:layout_gravity="top">
<ImageView
android:layout_width="wrap_content"

View File

@ -18,7 +18,6 @@
android:drawablePadding="8dp"
android:paddingRight="16dp"
android:paddingLeft="16dp"
android:background="@drawable/bar_selector"
android:minHeight="60dp"
android:textAllCaps="true"/>

View File

@ -0,0 +1,69 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff000000">
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginTop="16dp"
android:layout_marginBottom="160dp"
android:id="@+id/video_container"
android:layout_gravity="top">
<SurfaceView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:id="@+id/video_view"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
android:src="@drawable/video_play"
android:layout_gravity="center"
android:id="@+id/play_button"/>
<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"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="143dp"
android:layout_gravity="bottom"
android:id="@+id/info_container">
<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="#999999"
android:textSize="16dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="66dp"
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:id="@+id/edited_size"/>
</FrameLayout>
</FrameLayout>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">فقط عندما تكون الشاشة تعمل</string>
<string name="OnlyWhenScreenOff">فقط عندما تكون الشاشة مطفأة</string>
<string name="AlwaysShowPopup">دائمًا أظهر الإشعارات المنبثقة</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">لا توجد وسائط بعد</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">جميع الصور</string>
<string name="NoPhotos">لا توجد صور حتى الآن</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">التالي</string>
<string name="Back">رجوع</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Nur wenn Bildschirm „an“</string>
<string name="OnlyWhenScreenOff">Nur wenn Bildschirm „aus“</string>
<string name="AlwaysShowPopup">Popups immer anzeigen</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">Noch keine geteilten Medien vorhanden</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Alle Fotos</string>
<string name="NoPhotos">Noch keine Fotos</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Weiter</string>
<string name="Back">Zurück</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Sólo con pantalla encendida</string>
<string name="OnlyWhenScreenOff">Sólo con pantalla apagada</string>
<string name="AlwaysShowPopup">Siempre mostrar notificación emergente</string>
<string name="BadgeNumber">Globo de notificación</string>
<!--media view-->
<string name="NoMedia">No hay fotos ni vídeos compartidos aún</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Todas</string>
<string name="NoPhotos">No hay fotos aún</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Siguiente</string>
<string name="Back">Atrás</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Solo con schermo acceso</string>
<string name="OnlyWhenScreenOff">Solo con schermo spento</string>
<string name="AlwaysShowPopup">Mostra sempre i popup</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">Nessun media condiviso</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Tutte le foto</string>
<string name="NoPhotos">Ancora nessuna foto</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Avanti</string>
<string name="Back">Indietro</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Alleen wanneer scherm \"aan\" staat</string>
<string name="OnlyWhenScreenOff">Alleen wanneer scherm \"uit\" staat</string>
<string name="AlwaysShowPopup">Altijd popup tonen</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">Nog geen media gedeeld</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Alle foto\'s</string>
<string name="NoPhotos">Nog geen foto\'s</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Volgende</string>
<string name="Back">Vorige</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Somente com a tela ligada</string>
<string name="OnlyWhenScreenOff">Somente com a tela desligada</string>
<string name="AlwaysShowPopup">Sempre mostrar popup</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">Ainda não há mídia compartilhada</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Todas as Fotos</string>
<string name="NoPhotos">Ainda não há fotos</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Próximo</string>
<string name="Back">Voltar</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Only when screen "on"</string>
<string name="OnlyWhenScreenOff">Only when screen "off"</string>
<string name="AlwaysShowPopup">Always show popup</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">Ainda não há multimédia partilhado</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">Todas as fotos</string>
<string name="NoPhotos">Ainda não há fotos</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Seguinte</string>
<string name="Back">Anterior</string>

View File

@ -275,6 +275,7 @@
<string name="OnlyWhenScreenOn">Only when screen "on"</string>
<string name="OnlyWhenScreenOff">Only when screen "off"</string>
<string name="AlwaysShowPopup">Always show popup</string>
<string name="BadgeNumber">Badge Number</string>
<!--media view-->
<string name="NoMedia">No shared media yet</string>
@ -298,6 +299,11 @@
<string name="AllPhotos">All Photos</string>
<string name="NoPhotos">No photos yet</string>
<!--edit video view-->
<string name="EditVideo">Edit Video</string>
<string name="OriginalVideo">Original Video</string>
<string name="EditedVideo">Edited Video</string>
<!--button titles-->
<string name="Next">Next</string>
<string name="Back">Back</string>