diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt b/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt index 300e235dac507a32d253b64e884fd672b0520d41..7c50e19a02e550320111a27fcd1771c9085bd4f5 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/MailboxService.kt @@ -26,6 +26,8 @@ import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.IntentFilter import android.os.IBinder +import androidx.core.app.ServiceCompat +import androidx.core.app.ServiceCompat.stopForeground import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint import org.briarproject.mailbox.R @@ -103,7 +105,10 @@ class MailboxService : Service() { startForeground( NOTIFICATION_MAIN_ID, notificationManager.getServiceNotification( - Starting(getString(R.string.startup_headline)) + Starting( + status = getString(R.string.startup_headline), + isCancelable = false, + ) ) ) @@ -156,7 +161,7 @@ class MailboxService : Service() { override fun onDestroy() { super.onDestroy() LOG.info("Destroyed") - stopForeground(true) + stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) if (receiver != null) unregisterReceiver(receiver) if (started) { androidExecutor.runOnBackgroundThread { diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/StatusManager.kt b/mailbox-android/src/main/java/org/briarproject/mailbox/android/StatusManager.kt index 455321245797ae82a040439dc1bfff4157056ba5..6d2bce89ca6c22484d27ccc892fa2298dabaa80d 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/StatusManager.kt +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/StatusManager.kt @@ -25,6 +25,7 @@ import android.graphics.Bitmap import androidx.annotation.StringRes import androidx.annotation.UiThread import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.GlobalScope @@ -60,6 +61,7 @@ import javax.inject.Singleton import kotlin.math.min @Singleton +@OptIn(DelicateCoroutinesApi::class) class StatusManager @Inject constructor( @ApplicationContext private val context: Context, lifecycleManager: LifecycleManager, @@ -123,7 +125,7 @@ class StatusManager @Inject constructor( object NeedOnboarding : MailboxAppState(false) object NeedsDozeExemption : MailboxAppState(false) object NotStarted : MailboxAppState(false) - data class Starting(val status: String) : MailboxAppState(true) + data class Starting(val status: String, val isCancelable: Boolean) : MailboxAppState(true) data class StartedSettingUp(val qrCode: Bitmap, val link: String) : MailboxAppState(true) object StartedSetupComplete : MailboxAppState(true) object ErrorClockSkew : MailboxAppState(true) @@ -192,16 +194,26 @@ class StatusManager @Inject constructor( // Keep this check below WIPING, STOPPING and STOPPED so that the online check // does not interfere with these states - no point in showing a network error then. online != null && !online -> ErrorNoNetwork - ls != LifecycleState.RUNNING -> Starting(getString(R.string.startup_init_app)) + ls != LifecycleState.RUNNING -> Starting( + status = getString(R.string.startup_init_app), + isCancelable = false, + ) // RUNNING tor != TorState.Published -> when (tor) { - TorState.StartingStopping -> Starting(getString(R.string.startup_init_app)) + TorState.StartingStopping -> Starting( + status = getString(R.string.startup_init_app), + isCancelable = true, + ) is TorState.Enabling -> Starting( - getString(R.string.startup_bootstrapping_tor, tor.percent) + status = getString(R.string.startup_bootstrapping_tor, tor.percent), + isCancelable = true, ) TorState.ClockSkewed -> ErrorClockSkew TorState.Inactive -> ErrorNoNetwork - else -> Starting(getString(R.string.startup_publishing_onion_service)) + else -> Starting( + status = getString(R.string.startup_publishing_onion_service), + isCancelable = true, + ) } setup == SetupComplete.FALSE -> { // FIXME we shouldn't do expensive calls on the UiThread diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/android/ui/StartupFragment.kt b/mailbox-android/src/main/java/org/briarproject/mailbox/android/ui/StartupFragment.kt index 792e7f6f9eb261871bed2cca0a82ede2f18c9877..542cae88421cb8f8db81e377f57f68e5e51ae79e 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/android/ui/StartupFragment.kt +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/android/ui/StartupFragment.kt @@ -22,7 +22,10 @@ package org.briarproject.mailbox.android.ui import android.os.Bundle import android.view.LayoutInflater import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE import android.view.ViewGroup +import android.widget.Button import android.widget.TextView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -36,6 +39,7 @@ class StartupFragment : Fragment() { private val viewModel: MailboxViewModel by activityViewModels() private lateinit var statusDetail: TextView + private lateinit var cancelButton: Button override fun onCreateView( inflater: LayoutInflater, @@ -47,6 +51,7 @@ class StartupFragment : Fragment() { override fun onViewCreated(v: View, savedInstanceState: Bundle?) { statusDetail = v.findViewById(R.id.statusDetail) + cancelButton = v.findViewById(R.id.button) launchAndRepeatWhileStarted { viewModel.appState.collect { onAppStateChanged(it) } @@ -58,6 +63,15 @@ class StartupFragment : Fragment() { private fun onAppStateChanged(state: MailboxAppState) { if (state is Starting) { statusDetail.text = state.status + if (state.isCancelable) { + cancelButton.visibility = VISIBLE + cancelButton.setOnClickListener { + viewModel.stopLifecycle() + requireActivity().finishAffinity() + } + } else { + cancelButton.visibility = GONE + } } } diff --git a/mailbox-android/src/main/res/layout/fragment_startup.xml b/mailbox-android/src/main/res/layout/fragment_startup.xml index 1ce5cd181a571784f2e5548dbb385d7e3296035b..1680ce47098a801bd3f746e576123238e627c302 100644 --- a/mailbox-android/src/main/res/layout/fragment_startup.xml +++ b/mailbox-android/src/main/res/layout/fragment_startup.xml @@ -46,4 +46,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/statusHeadline" /> + <Button + android:id="@+id/button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="16dp" + android:text="@string/cancel" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/statusDetail" + app:layout_constraintVertical_bias="1.0" + tools:visibility="visible" /> + </androidx.constraintlayout.widget.ConstraintLayout>