diff --git a/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.java index e880e2b9c0055c86691f58d60cb94ff748d39f4f..cceebcd308e4e9f85fee38196fc10feb51f937a3 100644 --- a/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.java +++ b/ring-android/app/src/main/java/cx/ring/adapters/ConversationAdapter.java @@ -31,6 +31,7 @@ import android.graphics.SurfaceTexture; import android.graphics.drawable.Drawable; import android.media.MediaPlayer; import android.net.Uri; +import android.os.Build; import android.text.format.DateUtils; import android.text.format.Formatter; import android.util.Log; @@ -588,6 +589,10 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo if (file.getStatus() == InteractionStatus.TRANSFER_FINISHED) { viewHolder.mMsgDetailTxt.setText(String.format("%s - %s", timeString, Formatter.formatFileSize(viewHolder.itemView.getContext(), file.getTotalSize()))); + } else if (file.getStatus() == InteractionStatus.TRANSFER_ONGOING) { + viewHolder.mMsgDetailTxt.setText(String.format("%s / %s - %s", + Formatter.formatFileSize(viewHolder.itemView.getContext(), file.getBytesProgress()), Formatter.formatFileSize(viewHolder.itemView.getContext(), file.getTotalSize()), + ResourceMapper.getReadableFileTransferStatus(conversationFragment.getActivity(), file.getStatus()))); } else { viewHolder.mMsgDetailTxt.setText(String.format("%s - %s - %s", timeString, Formatter.formatFileSize(viewHolder.itemView.getContext(), file.getTotalSize()), @@ -648,13 +653,19 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo longPressView.setOnCreateContextMenuListener((menu, v, menuInfo) -> { menu.setHeaderTitle(file.getDisplayName()); - conversationFragment.onCreateContextMenu(menu, v, menuInfo); - MenuInflater inflater = conversationFragment.getActivity().getMenuInflater(); - inflater.inflate(R.menu.conversation_item_actions_file, menu); - if (!file.isComplete()) { + new MenuInflater(v.getContext()).inflate(R.menu.conversation_item_actions_file, menu); + if (file.getStatus() == InteractionStatus.TRANSFER_ONGOING) { + menu.findItem(R.id.conv_action_delete).setTitle(android.R.string.cancel); menu.removeItem(R.id.conv_action_download); menu.removeItem(R.id.conv_action_share); + menu.removeItem(R.id.conv_action_open); + } else { + if (!file.isComplete()) { + menu.removeItem(R.id.conv_action_download); + menu.removeItem(R.id.conv_action_share); + } } + conversationFragment.onCreateContextMenu(menu, v, menuInfo); }); longPressView.setOnLongClickListener(v -> { if (type == TransferMsgType.AUDIO || type == TransferMsgType.FILE) { @@ -706,6 +717,17 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationViewHo }); } else { viewHolder.mAnswerLayout.setVisibility(View.GONE); + if (file.getStatus() == InteractionStatus.TRANSFER_ONGOING) { + viewHolder.progress.setMax((int) (file.getTotalSize() / 1024)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + viewHolder.progress.setProgress((int) (file.getBytesProgress() / 1024), true); + } else { + viewHolder.progress.setProgress((int) (file.getBytesProgress() / 1024)); + } + viewHolder.progress.show(); + } else { + viewHolder.progress.hide(); + } } } } diff --git a/ring-android/app/src/main/java/cx/ring/views/ConversationViewHolder.java b/ring-android/app/src/main/java/cx/ring/views/ConversationViewHolder.java index de764a619a60dc111067e07b9a3a56a8f8f54b2f..a43ec078c7c4dad5e3a4f44c2480dce215a0b08d 100644 --- a/ring-android/app/src/main/java/cx/ring/views/ConversationViewHolder.java +++ b/ring-android/app/src/main/java/cx/ring/views/ConversationViewHolder.java @@ -20,6 +20,7 @@ */ package cx.ring.views; +import androidx.core.widget.ContentLoadingProgressBar; import androidx.recyclerview.widget.RecyclerView; import android.animation.ValueAnimator; @@ -30,7 +31,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ProgressBar; import android.widget.TextView; import cx.ring.R; @@ -54,7 +54,7 @@ public class ConversationViewHolder extends RecyclerView.ViewHolder { public ViewGroup mAnswerLayout; public View btnAccept; public View btnRefuse; - public ProgressBar progress; + public ContentLoadingProgressBar progress; public MediaPlayer player; public TextureView video; public Surface surface = null; diff --git a/ring-android/app/src/main/res/layout/item_conv_file_me.xml b/ring-android/app/src/main/res/layout/item_conv_file_me.xml index e31c3434ce9aa8e58c2c74749b22dceb632a5ed5..1bcd36c30605e9532a12a094365ead6bb01390ea 100644 --- a/ring-android/app/src/main/res/layout/item_conv_file_me.xml +++ b/ring-android/app/src/main/res/layout/item_conv_file_me.xml @@ -92,6 +92,15 @@ android:textSize="16sp" tools:text="long_file_name_gtest_long_file_name_gtest.jpg" /> + <androidx.core.widget.ContentLoadingProgressBar + android:id="@+id/progress" + style="@style/Widget.AppCompat.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:indeterminate="false" + android:visibility="gone" + tools:visibility="visible" /> + <TextView android:id="@+id/file_details_txt" android:layout_width="wrap_content" @@ -104,15 +113,6 @@ android:textSize="12sp" tools:text="1 mo - 12 mars" /> - <ProgressBar - android:id="@+id/progress" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:indeterminate="false" - android:paddingBottom="8dp" - android:visibility="gone" - tools:visibility="gone" /> - <LinearLayout android:id="@+id/llAnswer" android:layout_width="match_parent" diff --git a/ring-android/app/src/main/res/layout/item_conv_file_me_tv.xml b/ring-android/app/src/main/res/layout/item_conv_file_me_tv.xml index bd9278b8d480e593b4a4599eac26926a59987926..a765d3b6f10449a394822ecfe3b1a7bf569a3453 100644 --- a/ring-android/app/src/main/res/layout/item_conv_file_me_tv.xml +++ b/ring-android/app/src/main/res/layout/item_conv_file_me_tv.xml @@ -91,6 +91,15 @@ android:textSize="16sp" tools:text="long_file_name_gtest_long_file_name_gtest.jpg" /> + <androidx.core.widget.ContentLoadingProgressBar + android:id="@+id/progress" + style="@style/Widget.AppCompat.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:indeterminate="false" + android:visibility="gone" + tools:visibility="gone" /> + <TextView android:id="@+id/file_details_txt" android:layout_width="wrap_content" @@ -103,15 +112,6 @@ android:textSize="12sp" tools:text="1 mo - 12 mars" /> - <ProgressBar - android:id="@+id/progress" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:indeterminate="false" - android:paddingBottom="8dp" - android:visibility="gone" - tools:visibility="gone" /> - <LinearLayout android:id="@+id/llAnswer" android:layout_width="match_parent" diff --git a/ring-android/app/src/main/res/layout/item_conv_file_peer.xml b/ring-android/app/src/main/res/layout/item_conv_file_peer.xml index 60ebb46ab09d19c969cf71562863c4e87e781a03..42cfad350edcf9492247436f4e155b01ffcaa1cc 100644 --- a/ring-android/app/src/main/res/layout/item_conv_file_peer.xml +++ b/ring-android/app/src/main/res/layout/item_conv_file_peer.xml @@ -17,51 +17,50 @@ ~ along with this program; if not, write to the Free Software ~ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/file_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingBottom="8dp" android:clickable="true" android:descendantFocusability="blocksDescendants" android:focusable="true" + android:gravity="center" android:orientation="vertical" - android:gravity="center"> + android:paddingBottom="8dp"> <TextView android:id="@+id/msg_details_txt_perm" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="gone" android:textColor="@color/textColorSecondary" android:textSize="@dimen/conversation_timestamp_textsize" + android:visibility="gone" tools:text="@string/time_just_now" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="8dp" android:paddingStart="@dimen/padding_medium" + android:paddingTop="8dp" android:paddingEnd="@dimen/padding_large"> <ImageView android:id="@+id/photo" android:layout_width="@dimen/conversation_avatar_size" android:layout_height="@dimen/conversation_avatar_size" - android:background="@null" android:layout_alignBottom="@id/fileInfoLayout" - android:scaleType="centerCrop"/> + android:background="@null" + android:scaleType="centerCrop" /> <LinearLayout android:id="@+id/fileInfoLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_toEndOf="@+id/photo" android:layout_marginStart="@dimen/padding_medium" android:layout_marginEnd="20dp" + android:layout_toEndOf="@+id/photo" android:background="@drawable/textmsg_call_background" android:orientation="horizontal"> @@ -98,6 +97,17 @@ android:textSize="16sp" tools:text="long_file_name_gtest.jpg" /> + <androidx.core.widget.ContentLoadingProgressBar + android:id="@+id/progress" + style="@style/Widget.AppCompat.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:indeterminate="false" + android:visibility="gone" + tools:max="100" + tools:progress="40" + tools:visibility="visible" /> + <TextView android:id="@+id/file_details_txt" android:layout_width="wrap_content" @@ -110,15 +120,6 @@ android:textSize="12sp" tools:text="1 mo - 12 mars" /> - <ProgressBar - android:id="@+id/progress" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:indeterminate="false" - android:paddingBottom="8dp" - android:visibility="gone" - tools:visibility="gone" /> - <LinearLayout android:id="@+id/llAnswer" android:layout_width="match_parent" @@ -126,7 +127,7 @@ android:minWidth="350dp" android:orientation="horizontal" android:visibility="gone" - tools:visibility="visible"> + tools:visibility="gone"> <com.google.android.material.button.MaterialButton android:id="@+id/btnRefuse" diff --git a/ring-android/app/src/main/res/layout/item_conv_file_peer_tv.xml b/ring-android/app/src/main/res/layout/item_conv_file_peer_tv.xml index aa2a4c1c1d9ff6a8afbee2fc309e91275aa2b29f..ab8876d141dc958c1b0d129c718c293ebead7c78 100644 --- a/ring-android/app/src/main/res/layout/item_conv_file_peer_tv.xml +++ b/ring-android/app/src/main/res/layout/item_conv_file_peer_tv.xml @@ -97,6 +97,15 @@ android:textSize="16sp" tools:text="long_file_name_gtest.jpg" /> + <androidx.core.widget.ContentLoadingProgressBar + android:id="@+id/progress" + style="@style/Widget.AppCompat.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:indeterminate="false" + android:visibility="gone" + tools:visibility="gone" /> + <TextView android:id="@+id/file_details_txt" android:layout_width="wrap_content" @@ -109,15 +118,6 @@ android:textSize="12sp" tools:text="1 mo - 12 mars" /> - <ProgressBar - android:id="@+id/progress" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:indeterminate="false" - android:paddingBottom="8dp" - android:visibility="gone" - tools:visibility="gone" /> - <LinearLayout android:id="@+id/llAnswer" android:layout_width="match_parent" diff --git a/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java b/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java index e603c789842be6428fcb934a3451b5a1826ec7be..bdcb9c405a94a49e0d650b8f860807a98c1e7ba7 100644 --- a/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java +++ b/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java @@ -290,13 +290,17 @@ public class ConversationFacade { public void deleteConversationItem(Interaction element) { if (element.getType() == InteractionType.DATA_TRANSFER) { DataTransfer transfer = (DataTransfer) element; - File file = mDeviceRuntimeService.getConversationPath(transfer.getPeerId(), transfer.getStoragePath()); - mDisposableBag.add(Completable.mergeArrayDelayError( - mHistoryService.deleteInteraction(element.getId(), element.getAccount()), - Completable.fromAction(file::delete).subscribeOn(Schedulers.io())) - .andThen(startConversation(transfer.getAccount(), new Uri(transfer.getConversation().getParticipant()))) - .subscribe(c -> c.removeInteraction(transfer), - e -> Log.e(TAG, "Can't delete file transfer", e))); + if (transfer.getStatus() == InteractionStatus.TRANSFER_ONGOING) { + mAccountService.cancelDataTransfer(transfer.getDaemonId()); + } else { + File file = mDeviceRuntimeService.getConversationPath(transfer.getPeerId(), transfer.getStoragePath()); + mDisposableBag.add(Completable.mergeArrayDelayError( + mHistoryService.deleteInteraction(element.getId(), element.getAccount()), + Completable.fromAction(file::delete).subscribeOn(Schedulers.io())) + .andThen(startConversation(transfer.getAccount(), new Uri(transfer.getConversation().getParticipant()))) + .subscribe(c -> c.removeInteraction(transfer), + e -> Log.e(TAG, "Can't delete file transfer", e))); + } } else { // handling is the same for calls and texts mDisposableBag.add(Completable.mergeArrayDelayError(mHistoryService.deleteInteraction(element.getId(), element.getAccount()).subscribeOn(Schedulers.io())) diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java index cac1bd493d26e21019c8543a8254417b6c47caea..27664c503a1069b04ee6524a1927226f6d5c1210 100644 --- a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java +++ b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java @@ -34,9 +34,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; -import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; @@ -114,7 +114,6 @@ public class AccountService { private final HashMap<Long, DataTransfer> mDataTransfers = new HashMap<>(); private DataTransfer mStartingTransfer = null; - private Timer mTransferRefreshTimer = null; private final BehaviorSubject<List<Account>> accountsSubject = BehaviorSubject.create(); private final Subject<Account> accountSubject = PublishSubject.create(); @@ -1518,8 +1517,9 @@ public class AccountService { mExecutor.execute(() -> Ringservice.cancelDataTransfer(dataTransferId)); } - private class DataTransferRefreshTask extends TimerTask { + private class DataTransferRefreshTask implements Runnable { private final DataTransfer mToUpdate; + public ScheduledFuture<?> scheduledTask; DataTransferRefreshTask(DataTransfer t) { mToUpdate = t; @@ -1527,13 +1527,12 @@ public class AccountService { @Override public void run() { - Interaction.InteractionStatus transferStatus; synchronized (mToUpdate) { - transferStatus = mToUpdate.getStatus(); - if (transferStatus == Interaction.InteractionStatus.TRANSFER_ONGOING) { + if (mToUpdate.getStatus() == Interaction.InteractionStatus.TRANSFER_ONGOING) { dataTransferEvent(mToUpdate.getDaemonId(), 5); } else { - cancel(); + scheduledTask.cancel(false); + scheduledTask = null; } } } @@ -1568,12 +1567,10 @@ public class AccountService { InteractionStatus oldState = transfer.getStatus(); if (oldState != transferStatus) { if (transferStatus == Interaction.InteractionStatus.TRANSFER_ONGOING) { - if (mTransferRefreshTimer == null) - mTransferRefreshTimer = new Timer(); - mTransferRefreshTimer.scheduleAtFixedRate( - new DataTransferRefreshTask(transfer), + DataTransferRefreshTask task = new DataTransferRefreshTask(transfer); + task.scheduledTask = mExecutor.scheduleAtFixedRate(task, DATA_TRANSFER_REFRESH_PERIOD, - DATA_TRANSFER_REFRESH_PERIOD); + DATA_TRANSFER_REFRESH_PERIOD, TimeUnit.MILLISECONDS); } else if (transferStatus.isError()) { if (!transfer.isOutgoing()) { File tmpPath = mDeviceRuntimeService.getTemporaryPath(transfer.getPeerId(), transfer.getStoragePath());