diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ChooserFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ChooserFragment.java index 767f79b65..01c19a8de 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ChooserFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ChooserFragment.java @@ -60,8 +60,9 @@ public class ChooserFragment extends Fragment { public void onStart() { super.onStart(); requireActivity().setTitle(R.string.removable_drive_menu_title); - if (viewModel.getState().getValue() != null) { - // we can't come back here now to start another action + TransferDataState state = viewModel.getState().getValue(); + if (state instanceof TransferDataState.TaskAvailable) { + // we can't come back here now to start another task // as we only support one per ViewModel instance requireActivity().supportFinishAfterTransition(); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java index c0a41b699..6a71725a3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java @@ -87,7 +87,7 @@ public class ReceiveFragment extends Fragment { if (state instanceof TransferDataState.NoDataToSend) { throw new IllegalStateException(); } else if (state instanceof TransferDataState.Ready) { - button.setVisibility(VISIBLE); + button.setEnabled(true); } else if (state instanceof TransferDataState.TaskAvailable) { button.setEnabled(false); if (((TransferDataState.TaskAvailable) state).isOldTask) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java index eb450fd0c..a9878b4fd 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java @@ -5,37 +5,38 @@ import android.net.Uri; import org.briarproject.bramble.api.Consumer; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.TransactionManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.file.RemovableDriveManager; import org.briarproject.bramble.api.plugin.file.RemovableDriveTask; import org.briarproject.bramble.api.plugin.file.RemovableDriveTask.State; import org.briarproject.bramble.api.properties.TransportProperties; +import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.briar.android.viewmodel.DbViewModel; import org.briarproject.briar.android.viewmodel.LiveEvent; import org.briarproject.briar.android.viewmodel.MutableLiveEvent; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.logging.Logger; +import java.util.concurrent.Executor; import javax.annotation.Nullable; import javax.inject.Inject; import androidx.annotation.UiThread; -import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import static java.util.Locale.US; import static java.util.Objects.requireNonNull; -import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.PROP_URI; @UiThread @NotNullByDefault -class RemovableDriveViewModel extends AndroidViewModel { - - private static final Logger LOG = - getLogger(RemovableDriveViewModel.class.getName()); +class RemovableDriveViewModel extends DbViewModel { enum Action {SEND, RECEIVE} @@ -53,9 +54,14 @@ class RemovableDriveViewModel extends AndroidViewModel { private Consumer taskObserver = null; @Inject - RemovableDriveViewModel(Application app, + RemovableDriveViewModel( + Application app, + @DatabaseExecutor Executor dbExecutor, + LifecycleManager lifecycleManager, + TransactionManager db, + AndroidExecutor androidExecutor, RemovableDriveManager removableDriveManager) { - super(app); + super(app, dbExecutor, lifecycleManager, db, androidExecutor); this.manager = removableDriveManager; } @@ -82,9 +88,19 @@ class RemovableDriveViewModel extends AndroidViewModel { // check if there is already a send/write task task = manager.getCurrentWriterTask(); if (task == null) { - // TODO check if there is data to export now - // and only allow to continue if there is. - state.setValue(new TransferDataState.Ready()); + // check if there's even something to send + ContactId c = requireNonNull(contactId); + runOnDbThread(() -> { + try { + if (manager.isWriterTaskNeeded(c)) { + state.postValue(new TransferDataState.Ready()); + } else { + state.postValue(new TransferDataState.NoDataToSend()); + } + } catch (DbException e) { + handleException(e); + } + }); } else { // observe old task and start with initial state taskObserver = s -> observeTask(s, true); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java index 33ec15095..1cac6674f 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java @@ -25,7 +25,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModelProvider; -import static android.view.View.GONE; +import static android.os.Build.VERSION.SDK_INT; import static android.view.View.VISIBLE; import static android.widget.Toast.LENGTH_LONG; import static org.briarproject.briar.android.AppModule.getAndroidComponent; @@ -47,6 +47,7 @@ public class SendFragment extends Fragment { TextView introTextView; Button button; ProgressBar progressBar; + boolean hasShownOldTaskToast = false; @Override public void onAttach(Context context) { @@ -86,14 +87,16 @@ public class SendFragment extends Fragment { private void onStateChanged(TransferDataState state) { if (state instanceof TransferDataState.NoDataToSend) { introTextView.setText(R.string.removable_drive_send_no_data); - button.setVisibility(GONE); + button.setEnabled(false); } else if (state instanceof TransferDataState.Ready) { - button.setVisibility(VISIBLE); + button.setEnabled(true); } else if (state instanceof TransferDataState.TaskAvailable) { button.setEnabled(false); - if (((TransferDataState.TaskAvailable) state).isOldTask) { + if (!hasShownOldTaskToast && + ((TransferDataState.TaskAvailable) state).isOldTask) { Toast.makeText(requireContext(), R.string.removable_drive_ongoing, LENGTH_LONG).show(); + hasShownOldTaskToast = true; } RemovableDriveTask.State s = ((TransferDataState.TaskAvailable) state).state; @@ -102,7 +105,11 @@ public class SendFragment extends Fragment { // FIXME if we ever export more than 2 GB, this won't work progressBar.setMax((int) s.getTotal()); } - progressBar.setProgress((int) s.getDone()); + if (SDK_INT >= 24) { + progressBar.setProgress((int) s.getDone(), true); + } else { + progressBar.setProgress((int) s.getDone()); + } } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/DbViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/DbViewModel.java index 087e95f64..6e39b347c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/DbViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/DbViewModel.java @@ -23,7 +23,6 @@ import java.util.logging.Logger; import javax.annotation.concurrent.Immutable; import androidx.annotation.AnyThread; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.arch.core.util.Function; @@ -50,7 +49,7 @@ public abstract class DbViewModel extends AndroidViewModel { protected final AndroidExecutor androidExecutor; public DbViewModel( - @NonNull Application application, + Application application, @DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, TransactionManager db, diff --git a/briar-android/src/main/res/layout/fragment_transfer_data_receive.xml b/briar-android/src/main/res/layout/fragment_transfer_data_receive.xml index 0f8c283f9..6448b9d28 100644 --- a/briar-android/src/main/res/layout/fragment_transfer_data_receive.xml +++ b/briar-android/src/main/res/layout/fragment_transfer_data_receive.xml @@ -95,11 +95,10 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="16dp" + android:enabled="false" android:text="@string/removable_drive_receive_button" - android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - tools:visibility="visible" /> + app:layout_constraintStart_toStartOf="parent" /> diff --git a/briar-android/src/main/res/layout/fragment_transfer_data_send.xml b/briar-android/src/main/res/layout/fragment_transfer_data_send.xml index 173014596..d2fbc9bef 100644 --- a/briar-android/src/main/res/layout/fragment_transfer_data_send.xml +++ b/briar-android/src/main/res/layout/fragment_transfer_data_send.xml @@ -98,11 +98,10 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="16dp" + android:enabled="false" android:text="@string/removable_drive_send_button" - android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - tools:visibility="visible" /> + app:layout_constraintStart_toStartOf="parent" />