More WIP on moving parts of omnipod-eros to omnipod-common

This commit is contained in:
Bart Sopers 2021-02-20 00:46:02 +01:00
parent 87d4ba14cb
commit eac0c9a224
17 changed files with 99 additions and 56 deletions

View file

@ -4,16 +4,18 @@ import android.os.Bundle
import androidx.annotation.IdRes import androidx.annotation.IdRes
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.activity.OmnipodWizardActivityBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.activity.OmnipodWizardActivityBase
import javax.inject.Inject
class PodActivationWizardActivity : OmnipodWizardActivityBase() { class PodActivationWizardActivity : OmnipodWizardActivityBase() {
companion object { companion object {
const val KEY_TYPE = "wizardType"
const val KEY_START_DESTINATION = "startDestination" const val KEY_START_DESTINATION = "startDestination"
} }
@Inject enum class Type {
lateinit var podStateManager: PodStateManager SHORT,
LONG
}
@IdRes @IdRes
private var startDestination: Int = R.id.fillPodInfoFragment private var startDestination: Int = R.id.fillPodInfoFragment
@ -24,7 +26,7 @@ class PodActivationWizardActivity : OmnipodWizardActivityBase() {
setContentView(R.layout.omnipod_common_pod_activation_wizard_activity) setContentView(R.layout.omnipod_common_pod_activation_wizard_activity)
startDestination = savedInstanceState?.getInt(KEY_START_DESTINATION, R.id.fillPodInfoFragment) startDestination = savedInstanceState?.getInt(KEY_START_DESTINATION, R.id.fillPodInfoFragment)
?: if (podStateManager.activationProgress.isBefore(ActivationProgress.PRIMING_COMPLETED)) { ?: if (intent.getSerializableExtra(KEY_TYPE) as Type == Type.LONG) {
R.id.fillPodInfoFragment R.id.fillPodInfoFragment
} else { } else {
R.id.attachPodInfoFragment R.id.attachPodInfoFragment

View file

@ -1,17 +1,35 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.fragment package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.fragment
import android.os.Bundle
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.dagger.OmnipodPluginQualifier
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.FillPodInfoViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.InfoFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.InfoFragmentBase
import javax.inject.Inject
class FillPodInfoFragment : InfoFragmentBase() { class FillPodInfoFragment : InfoFragmentBase() {
@Inject
@OmnipodPluginQualifier
lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: FillPodInfoViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val vm: FillPodInfoViewModel by viewModels { viewModelFactory }
this.viewModel = vm
}
@StringRes @StringRes
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_fill_pod_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_fill_pod_title
@StringRes @StringRes
override fun getTextId(): Int = R.string.omnipod_pod_activation_wizard_fill_pod_text override fun getTextId(): Int = viewModel.getTextId()
@IdRes @IdRes
override fun getNextPageActionId(): Int = R.id.action_fillPodInfoFragment_to_initializePodActionFragment override fun getNextPageActionId(): Int = R.id.action_fillPodInfoFragment_to_initializePodActionFragment

View file

@ -27,7 +27,7 @@ class InitializePodActionFragment : PodActivationActionFragmentBase() {
override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title
@StringRes @StringRes
override fun getTextId(): Int = R.string.omnipod_pod_activation_wizard_initialize_pod_text override fun getTextId(): Int = (viewModel as InitializePodActionViewModel).getTextId()
@IdRes @IdRes
override fun getNextPageActionId(): Int = R.id.action_initializePodActionFragment_to_attachPodInfoFragment override fun getNextPageActionId(): Int = R.id.action_initializePodActionFragment_to_attachPodInfoFragment

View file

@ -5,24 +5,16 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Button import android.widget.Button
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.PodActivationActionViewModelBase
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.ActionFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.ActionFragmentBase
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.PodDeactivationWizardActivity import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.PodDeactivationWizardActivity
import javax.inject.Inject
abstract class PodActivationActionFragmentBase : ActionFragmentBase() { abstract class PodActivationActionFragmentBase : ActionFragmentBase() {
@Inject protected lateinit var podStateManager: PodStateManager
private lateinit var buttonDeactivatePod: Button
private lateinit var buttonRetry: Button
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
buttonDeactivatePod = view.findViewById(R.id.omnipod_wizard_button_deactivate_pod) view.findViewById<Button>(R.id.omnipod_wizard_button_deactivate_pod).setOnClickListener {
buttonRetry = view.findViewById(R.id.omnipod_wizard_button_retry)
buttonDeactivatePod.setOnClickListener {
activity?.let { activity?.let {
startActivity(Intent(it, PodDeactivationWizardActivity::class.java)) startActivity(Intent(it, PodDeactivationWizardActivity::class.java))
it.finish() it.finish()
@ -30,10 +22,14 @@ abstract class PodActivationActionFragmentBase : ActionFragmentBase() {
} }
} }
override fun onActionFailure() { override fun onFailure() {
if ((podStateManager.isPodActivationTimeExceeded && podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)) || podStateManager.isPodFaulted) { (viewModel as? PodActivationActionViewModelBase)?.let { viewModel ->
buttonRetry.visibility = View.GONE if (viewModel.isPodDeactivatable() and (viewModel.isPodInAlarm() or viewModel.isPodActivationTimeExceeded())) {
buttonDeactivatePod.visibility = View.VISIBLE view?.let {
it.findViewById<Button>(R.id.omnipod_wizard_button_retry)?.visibility = View.GONE
it.findViewById<Button>(R.id.omnipod_wizard_button_deactivate_pod)?.visibility = View.VISIBLE
}
}
} }
} }
} }

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel
import androidx.annotation.StringRes
import androidx.lifecycle.ViewModel
import info.nightscout.androidaps.plugins.pump.omnipod.common.R
class FillPodInfoViewModel : ViewModel() {
@StringRes fun getTextId(): Int = R.string.omnipod_pod_activation_wizard_fill_pod_text
}

View file

@ -1,11 +1,20 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel
import androidx.annotation.StringRes
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager
import javax.inject.Inject import javax.inject.Inject
class InitializePodActionViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodManager) : ActionViewModelBase() { class InitializePodActionViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodManager, private val podStateManager: AapsPodStateManager) : PodActivationActionViewModelBase() {
override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted
override fun isPodActivationTimeExceeded(): Boolean = podStateManager.isPodActivationTimeExceeded
override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)
override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.initializePod() override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.initializePod()
@StringRes fun getTextId() = R.string.omnipod_pod_activation_wizard_initialize_pod_text
} }

View file

@ -2,11 +2,16 @@ package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activat
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager
import javax.inject.Inject import javax.inject.Inject
class InsertCannulaActionViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodManager, private val profileFunction: ProfileFunction) : ActionViewModelBase() { class InsertCannulaActionViewModel @Inject constructor(private val aapsOmnipodManager: AapsOmnipodManager, private val podStateManager: AapsPodStateManager, private val profileFunction: ProfileFunction) : PodActivationActionViewModelBase() {
override fun isPodInAlarm(): Boolean = podStateManager.isPodFaulted
override fun isPodActivationTimeExceeded(): Boolean = podStateManager.isPodActivationTimeExceeded
override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)
override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.insertCannula(profileFunction.getProfile()) override fun doExecuteAction(): PumpEnactResult = aapsOmnipodManager.insertCannula(profileFunction.getProfile())
} }

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase
abstract class PodActivationActionViewModelBase : ActionViewModelBase() {
abstract fun isPodInAlarm(): Boolean
abstract fun isPodActivationTimeExceeded(): Boolean
abstract fun isPodDeactivatable(): Boolean
}

View file

@ -8,9 +8,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.R
abstract class OmnipodWizardActivityBase : NoSplashAppCompatActivity() { abstract class OmnipodWizardActivityBase : NoSplashAppCompatActivity() {
override fun onBackPressed() { override fun onBackPressed() = exitActivityAfterConfirmation()
exitActivityAfterConfirmation()
}
fun exitActivityAfterConfirmation() { fun exitActivityAfterConfirmation() {
if (getNavController().previousBackStackEntry == null) { if (getNavController().previousBackStackEntry == null) {

View file

@ -43,11 +43,9 @@ abstract class ActionFragmentBase : WizardFragmentBase() {
view.findViewById<Button>(R.id.omnipod_wizard_action_error).visibility = (!isExecuting && !result.success).toVisibility() view.findViewById<Button>(R.id.omnipod_wizard_action_error).visibility = (!isExecuting && !result.success).toVisibility()
view.findViewById<Button>(R.id.omnipod_wizard_button_retry).visibility = (!isExecuting && !result.success).toVisibility() view.findViewById<Button>(R.id.omnipod_wizard_button_retry).visibility = (!isExecuting && !result.success).toVisibility()
if (result.success) { if (!result.success) {
onActionSuccess()
} else {
view.findViewById<Button>(R.id.omnipod_wizard_action_error).text = result.comment view.findViewById<Button>(R.id.omnipod_wizard_action_error).text = result.comment
onActionFailure() onFailure()
} }
} }
}) })
@ -66,15 +64,11 @@ abstract class ActionFragmentBase : WizardFragmentBase() {
viewModel.actionResultLiveData.removeObservers(viewLifecycleOwner) viewModel.actionResultLiveData.removeObservers(viewLifecycleOwner)
} }
fun onActionSuccess() {} abstract fun onFailure()
open fun onActionFailure() {}
@StringRes @StringRes
abstract fun getTextId(): Int abstract fun getTextId(): Int
@LayoutRes @LayoutRes
override fun getLayoutId(): Int { override fun getLayoutId(): Int = R.layout.omnipod_common_wizard_action_page_fragment
return R.layout.omnipod_common_wizard_action_page_fragment
}
} }

View file

@ -19,7 +19,5 @@ abstract class InfoFragmentBase : WizardFragmentBase() {
abstract fun getTextId(): Int abstract fun getTextId(): Int
@LayoutRes @LayoutRes
override fun getLayoutId(): Int { override fun getLayoutId(): Int = R.layout.omnipod_common_wizard_info_page_fragment
return R.layout.omnipod_common_wizard_info_page_fragment
}
} }

View file

@ -11,19 +11,20 @@ import androidx.annotation.StringRes
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import dagger.android.support.DaggerFragment import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.plugins.pump.omnipod.common.R import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.databinding.OmnipodCommonWizardBaseFragmentBinding
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.activity.OmnipodWizardActivityBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.activity.OmnipodWizardActivityBase
import kotlin.math.roundToInt import kotlin.math.roundToInt
abstract class WizardFragmentBase : DaggerFragment() { abstract class WizardFragmentBase : DaggerFragment() {
var _binding: OmnipodWizardBaseFragmentBinding? = null var _binding: OmnipodCommonWizardBaseFragmentBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
// onDestroyView. // onDestroyView.
val binding get() = _binding!! val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = OmnipodWizardBaseFragmentBinding.inflate(inflater, container, false) _binding = OmnipodCommonWizardBaseFragmentBinding.inflate(inflater, container, false)
binding.fragmentContent.let { binding.fragmentContent.let {
it.layoutResource = getLayoutId() it.layoutResource = getLayoutId()

View file

@ -9,7 +9,7 @@ import io.reactivex.subjects.SingleSubject
abstract class ActionViewModelBase : ViewModel() { abstract class ActionViewModelBase : ViewModel() {
private val _isActionExecutingLiveData = MutableLiveData<Boolean>(false) private val _isActionExecutingLiveData = MutableLiveData(false)
val isActionExecutingLiveData: LiveData<Boolean> = _isActionExecutingLiveData val isActionExecutingLiveData: LiveData<Boolean> = _isActionExecutingLiveData
private val _actionResultLiveData = MutableLiveData<PumpEnactResult?>(null) private val _actionResultLiveData = MutableLiveData<PumpEnactResult?>(null)

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.R
import info.nightscout.androidaps.plugins.pump.omnipod.common.dagger.OmnipodPluginQualifier import info.nightscout.androidaps.plugins.pump.omnipod.common.dagger.OmnipodPluginQualifier
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.ActionFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.fragment.ActionFragmentBase
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.DeactivatePodActionViewModel import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactivation.viewmodel.DeactivatePodActionViewModel
import info.nightscout.androidaps.utils.extensions.toVisibility
import javax.inject.Inject import javax.inject.Inject
class DeactivatePodActionFragment : ActionFragmentBase() { class DeactivatePodActionFragment : ActionFragmentBase() {
@ -22,9 +21,6 @@ class DeactivatePodActionFragment : ActionFragmentBase() {
@OmnipodPluginQualifier @OmnipodPluginQualifier
lateinit var viewModelFactory: ViewModelProvider.Factory lateinit var viewModelFactory: ViewModelProvider.Factory
@Inject
lateinit var aapsOmnipodManager: AapsOmnipodManager
private lateinit var buttonDiscardPod: Button private lateinit var buttonDiscardPod: Button
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -36,15 +32,14 @@ class DeactivatePodActionFragment : ActionFragmentBase() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
buttonDiscardPod = view.findViewById(R.id.omnipod_wizard_button_discard_pod) view.findViewById<Button>(R.id.omnipod_wizard_button_discard_pod)?.setOnClickListener {
buttonDiscardPod.setOnClickListener {
context?.let { context?.let {
AlertDialog.Builder(it) AlertDialog.Builder(it)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(getString(R.string.omnipod_common_pod_deactivation_wizard_discard_pod)) .setTitle(getString(R.string.omnipod_common_pod_deactivation_wizard_discard_pod))
.setMessage(getString(R.string.omnipod_common_pod_deactivation_wizard_discard_pod_confirmation)) .setMessage(getString(R.string.omnipod_common_pod_deactivation_wizard_discard_pod_confirmation))
.setPositiveButton(getString(R.string.omnipod_common_yes)) { _, _ -> .setPositiveButton(getString(R.string.omnipod_common_yes)) { _, _ ->
aapsOmnipodManager.discardPodState() (viewModel as DeactivatePodActionViewModel).discardPod()
findNavController().navigate(R.id.action_deactivatePodActionFragment_to_podDiscardedInfoFragment) findNavController().navigate(R.id.action_deactivatePodActionFragment_to_podDiscardedInfoFragment)
} }
.setNegativeButton(getString(R.string.omnipod_common_no), null) .setNegativeButton(getString(R.string.omnipod_common_no), null)
@ -53,8 +48,8 @@ class DeactivatePodActionFragment : ActionFragmentBase() {
} }
} }
override fun onActionFailure() { override fun onFailure() {
buttonDiscardPod.visibility = (!isActionExecuting()).toVisibility() buttonDiscardPod.visibility = View.VISIBLE
} }
@StringRes @StringRes

View file

@ -2,9 +2,9 @@ package info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.deactiv
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.CommandDeactivatePod
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.common.viewmodel.ActionViewModelBase
import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager import info.nightscout.androidaps.plugins.pump.omnipod.eros.manager.AapsOmnipodManager
import info.nightscout.androidaps.plugins.pump.omnipod.eros.queue.command.CommandDeactivatePod
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import io.reactivex.subjects.SingleSubject import io.reactivex.subjects.SingleSubject
import javax.inject.Inject import javax.inject.Inject
@ -20,4 +20,8 @@ class DeactivatePodActionViewModel @Inject constructor(private val aapsOmnipodMa
}) })
return singleSubject.blockingGet() return singleSubject.blockingGet()
} }
fun discardPod() {
aapsOmnipodManager.discardPodState()
}
} }

View file

@ -58,6 +58,7 @@ class ErosPodManagementActivity : NoSplashAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = OmnipodPodManagementBinding.inflate(layoutInflater) binding = OmnipodPodManagementBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)

View file

@ -62,7 +62,7 @@ class OmnipodErosOverviewFragment : DaggerFragment() {
companion object { companion object {
private const val REFRESH_INTERVAL_MILLIS = 15 * 1000L // 15 seconds private const val REFRESH_INTERVAL_MILLIS = 15 * 1000L // 15 seconds
private const val PLACEHOLDER = "-" // 15 seconds private const val PLACEHOLDER = "-"
} }
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@ -93,11 +93,11 @@ class OmnipodErosOverviewFragment : DaggerFragment() {
} }
} }
private var _binding: OmnipodErosOverviewBinding? = null var _binding: OmnipodErosOverviewBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and
// onDestroyView. // onDestroyView.
private val binding get() = _binding!! val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
OmnipodErosOverviewBinding.inflate(inflater, container!!).also { OmnipodErosOverviewBinding.inflate(inflater, container!!).also {