diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/OnSafeClickListener.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/OnSafeClickListener.kt new file mode 100644 index 0000000000..49648a3d20 --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/OnSafeClickListener.kt @@ -0,0 +1,26 @@ +package info.nightscout.pump.medtrum.bindingadapters + +import android.view.View +import java.util.concurrent.atomic.AtomicBoolean + +class OnSafeClickListener( + private val clickListener: View.OnClickListener, + private val intervalMs: Long = MIN_CLICK_INTERVAL +) : View.OnClickListener { + private var canClick = AtomicBoolean(true) + + override fun onClick(v: View?) { + if (canClick.getAndSet(false)) { + v?.run { + postDelayed({ + canClick.set(true) + }, intervalMs) + clickListener.onClick(v) + } + } + } + companion object { + // 중복 클릭 방지 시간 설정 + private const val MIN_CLICK_INTERVAL: Long = 1000 + } +} \ No newline at end of file diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/ViewBindingAdapter.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/ViewBindingAdapter.kt new file mode 100644 index 0000000000..f4b51efe1a --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/bindingadapters/ViewBindingAdapter.kt @@ -0,0 +1,29 @@ +package info.nightscout.pump.medtrum.bindingadapters + +import android.view.View +import android.widget.TextView +import androidx.annotation.ColorRes +import androidx.databinding.BindingAdapter +import info.nightscout.pump.medtrum.extension.setVisibleOrGone + +@BindingAdapter("android:visibility") +fun setVisibility(view: View, visible: Boolean) { + view.setVisibleOrGone(visible) +} + +@BindingAdapter("visibleOrGone") +fun setVisibleOrGone(view: View, visibleOrGone: Boolean) { + view.setVisibleOrGone(visibleOrGone) +} + +@BindingAdapter("onSafeClick") +fun View.setOnSafeClickListener(clickListener: View.OnClickListener?) { + clickListener?.also { + setOnClickListener(OnSafeClickListener(it)) + } ?: setOnClickListener(null) +} + +@BindingAdapter("textColor") +fun setTextColor(view: TextView, @ColorRes colorResId: Int) { + view.setTextColor(view.context.getColor(colorResId)) +} diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/di/MedtrumModule.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/di/MedtrumModule.kt index 9fcaf5d9d8..71af92437e 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/di/MedtrumModule.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/di/MedtrumModule.kt @@ -7,11 +7,9 @@ import dagger.Module import dagger.Provides import dagger.android.ContributesAndroidInjector import dagger.multibindings.IntoMap -// import info.nightscout.androidaps.plugins.pump.eopatch.ui.viewmodel.OverviewViewModel import info.nightscout.pump.medtrum.services.MedtrumService import info.nightscout.pump.medtrum.ui.MedtrumOverviewFragment -import info.nightscout.pump.medtrum.ui.viewmodel.OverviewViewModel -// import info.nightscout.pump.medtrum.ui.viewmodel.ViewModel +import info.nightscout.pump.medtrum.ui.viewmodel.MedtrumOverviewViewModel import info.nightscout.pump.medtrum.ui.viewmodel.ViewModelFactory import info.nightscout.pump.medtrum.ui.viewmodel.ViewModelKey import javax.inject.Provider @@ -33,8 +31,8 @@ abstract class MedtrumModule { @Binds @IntoMap @MedtrumPluginQualifier - @ViewModelKey(OverviewViewModel::class) - internal abstract fun bindsOverviewViewmodel(viewModel: OverviewViewModel): ViewModel + @ViewModelKey(MedtrumOverviewViewModel::class) + internal abstract fun bindsMedtrumOverviewViewmodel(viewModel: MedtrumOverviewViewModel): ViewModel // FRAGMENTS @ContributesAndroidInjector diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/extension/ViewExtension.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/extension/ViewExtension.kt new file mode 100644 index 0000000000..5cf65baeb6 --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/extension/ViewExtension.kt @@ -0,0 +1,34 @@ +package info.nightscout.pump.medtrum.extension + +import android.view.View + +fun View?.visible() = this?.run { visibility = View.VISIBLE } + +fun View?.visible(vararg views: View?) { + visible() + for (view in views) + view.visible() +} + +fun View?.invisible() = this?.run { visibility = View.INVISIBLE } + +fun View?.invisible(vararg views: View?) { + invisible() + for (view in views) + view.invisible() +} + +fun View?.gone() = this?.run { visibility = View.GONE } + +fun View?.gone(vararg views: View?) { + gone() + for (view in views) + view.gone() +} + +fun View?.setVisibleOrGone(visibleOrGone: Boolean, vararg views: View?) { + for (view in views) + if (visibleOrGone) view.visible() else view.gone() +} + +fun View?.setVisibleOrGone(visibleOrGone: Boolean) = setVisibleOrGone(visibleOrGone, this) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseActivity.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseActivity.kt new file mode 100644 index 0000000000..65b570f5c8 --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseActivity.kt @@ -0,0 +1,58 @@ +package info.nightscout.pump.medtrum.ui + +import android.content.Intent +import android.os.Bundle +import androidx.activity.result.ActivityResultLauncher +import androidx.annotation.LayoutRes +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding +import androidx.lifecycle.ViewModelProvider +import dagger.android.support.DaggerAppCompatActivity +import info.nightscout.core.ui.R +import info.nightscout.pump.medtrum.di.MedtrumPluginQualifier +import info.nightscout.pump.medtrum.ui.MedtrumBaseNavigator +import info.nightscout.rx.AapsSchedulers +import io.reactivex.rxjava3.disposables.CompositeDisposable +import javax.inject.Inject + +abstract class MedtrumBaseActivity : DaggerAppCompatActivity(), MedtrumBaseNavigator { + @Inject + @MedtrumPluginQualifier + lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject lateinit var aapsSchedulers: AapsSchedulers + + protected lateinit var binding: B + + private val compositeDisposable = CompositeDisposable() + + protected lateinit var getResult: ActivityResultLauncher + + @LayoutRes + abstract fun getLayoutId(): Int + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setTheme(R.style.AppTheme_NoActionBar) + + binding = DataBindingUtil.setContentView(this, getLayoutId()) + binding.lifecycleOwner = this + + } + + override fun back() { + if(supportFragmentManager.backStackEntryCount == 0) { + finish() + } else { + supportFragmentManager.popBackStack() + } + } + + override fun finish(finishAffinity: Boolean) { + if(finishAffinity) { + finishAffinity() + } else { + finish() + } + } +} \ No newline at end of file diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseFragment.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseFragment.kt new file mode 100644 index 0000000000..e09a283c0d --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseFragment.kt @@ -0,0 +1,66 @@ +package info.nightscout.pump.medtrum.ui + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.CallSuper +import androidx.annotation.LayoutRes +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding +import androidx.lifecycle.ViewModelProvider +import dagger.android.support.DaggerFragment +import info.nightscout.pump.medtrum.di.MedtrumPluginQualifier +import io.reactivex.rxjava3.disposables.CompositeDisposable +import javax.inject.Inject + +abstract class MedtrumBaseFragment : DaggerFragment(), MedtrumBaseNavigator { + @Inject + @MedtrumPluginQualifier + lateinit var viewModelFactory: ViewModelProvider.Factory + + protected var baseActivity: MedtrumBaseActivity<*>? = null + + protected lateinit var binding: B + + private val compositeDisposable = CompositeDisposable() + + @LayoutRes + abstract fun getLayoutId(): Int + + @CallSuper + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is MedtrumBaseActivity<*>) { + baseActivity = context + } + } + + @CallSuper + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false) + binding.lifecycleOwner = viewLifecycleOwner + return binding.root + } + + @CallSuper + override fun onDestroy() { + super.onDestroy() + compositeDisposable.dispose() + } + + @CallSuper + override fun onDetach() { + super.onDetach() + baseActivity = null + } + + override fun back() { + baseActivity?.back() + } + + override fun finish(finishAffinity: Boolean) { + baseActivity?.finish(finishAffinity) + } +} \ No newline at end of file diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/BaseNavigator.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseNavigator.kt similarity index 76% rename from pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/BaseNavigator.kt rename to pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseNavigator.kt index c1bebb0a93..ebd597a673 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/BaseNavigator.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumBaseNavigator.kt @@ -1,6 +1,6 @@ package info.nightscout.pump.medtrum.ui -interface BaseNavigator { +interface MedtrumBaseNavigator { fun back() fun finish(finishAffinity: Boolean = false) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumOverviewFragment.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumOverviewFragment.kt index 76f36dded1..a29b8c60ad 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumOverviewFragment.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/MedtrumOverviewFragment.kt @@ -1,101 +1,67 @@ package info.nightscout.pump.medtrum.ui +import android.content.Intent import android.os.Bundle -import android.os.Handler -import android.os.HandlerThread -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import dagger.android.support.DaggerFragment -import info.nightscout.core.extensions.toStringFull -import info.nightscout.core.utils.fabric.FabricPrivacy -import info.nightscout.interfaces.iob.IobCobCalculator -import info.nightscout.interfaces.profile.ProfileFunction +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.lifecycle.ViewModelProvider import info.nightscout.pump.medtrum.databinding.MedtrumOverviewFragmentBinding -import info.nightscout.pump.medtrum.events.EventMedtrumPumpUpdateGui -import info.nightscout.pump.medtrum.MedtrumPlugin +import info.nightscout.pump.medtrum.ui.viewmodel.MedtrumOverviewViewModel +import info.nightscout.pump.medtrum.R import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus -import info.nightscout.rx.events.EventExtendedBolusChange -import info.nightscout.rx.events.EventTempBasalChange -import info.nightscout.shared.interfaces.ResourceHelper -import info.nightscout.shared.utils.DateUtil -import info.nightscout.shared.utils.T +import info.nightscout.rx.logging.AAPSLogger import io.reactivex.rxjava3.disposables.CompositeDisposable -import io.reactivex.rxjava3.kotlin.plusAssign import javax.inject.Inject -class MedtrumOverviewFragment : DaggerFragment() { +class MedtrumOverviewFragment : MedtrumBaseFragment() { @Inject lateinit var rxBus: RxBus - @Inject lateinit var rh: ResourceHelper - @Inject lateinit var dateUtil: DateUtil - @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var MedtrumPlugin: MedtrumPlugin - @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var iobCobCalculator: IobCobCalculator @Inject lateinit var aapsSchedulers: AapsSchedulers + @Inject lateinit var aapsLogger: AAPSLogger + private lateinit var resultLauncherForResume: ActivityResultLauncher + private lateinit var resultLauncherForPause: ActivityResultLauncher - private val disposable = CompositeDisposable() + private var disposable: CompositeDisposable = CompositeDisposable() - private lateinit var refreshLoop: Runnable - private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) + override fun getLayoutId(): Int = R.layout.medtrum_overview_fragment - private var _binding: MedtrumOverviewFragmentBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = - MedtrumOverviewFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root - - @Synchronized - override fun onResume() { - super.onResume() - disposable += rxBus - .toObservable(EventMedtrumPumpUpdateGui::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) - disposable += rxBus - .toObservable(EventTempBasalChange::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) - disposable += rxBus - .toObservable(EventExtendedBolusChange::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGui() }, fabricPrivacy::logException) - refreshLoop = Runnable { - activity?.runOnUiThread { updateGui() } - handler.postDelayed(refreshLoop, T.mins(1).msecs()) - } - handler.postDelayed(refreshLoop, T.mins(1).msecs()) - updateGui() + override fun onDestroy() { + super.onDestroy() + disposable.clear() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.apply { + viewmodel = ViewModelProvider(this@MedtrumOverviewFragment, viewModelFactory).get(MedtrumOverviewViewModel::class.java) + viewmodel?.apply { + // TODO Handle events here, see eopatch eventhandler + } + + resultLauncherForResume = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + when (it.resultCode) { + // TODO Handle events here, see eopatch eventhandler + } + } + + resultLauncherForPause = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + when (it.resultCode) { + // TODO Handle events here, see eopatch eventhandler + } + } + } } - @Synchronized override fun onPause() { super.onPause() - disposable.clear() - handler.removeCallbacksAndMessages(null) + // TODO } - @Synchronized - override fun onDestroyView() { - super.onDestroyView() - _binding = null + override fun onResume() { + super.onResume() + // TODO } - - @Synchronized - private fun updateGui() { - if (_binding == null) return - val profile = profileFunction.getProfile() ?: return - binding.baseBasalRate.text = rh.gs(info.nightscout.core.ui.R.string.pump_base_basal_rate, MedtrumPlugin.baseBasalRate) - binding.tempbasal.text = iobCobCalculator.getTempBasal(dateUtil.now())?.toStringFull(profile, dateUtil) - ?: "" - binding.battery.text = rh.gs(info.nightscout.core.ui.R.string.format_percent, 0) // TODO - binding.reservoir.text = rh.gs(info.nightscout.interfaces.R.string.format_insulin_units, 0.0) // TODO - - binding.serialNumber.text = MedtrumPlugin.serialNumber() - } -} +} \ No newline at end of file diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/BaseViewModel.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/BaseViewModel.kt index 2ff064649f..c3b39693b3 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/BaseViewModel.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/BaseViewModel.kt @@ -1,12 +1,12 @@ package info.nightscout.pump.medtrum.ui.viewmodel import androidx.lifecycle.ViewModel -import info.nightscout.pump.medtrum.ui.BaseNavigator +import info.nightscout.pump.medtrum.ui.MedtrumBaseNavigator import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable import java.lang.ref.WeakReference -abstract class BaseViewModel : ViewModel() { +abstract class BaseViewModel : ViewModel() { private var _navigator: WeakReference? = null var navigator: N? diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/OverviewViewModel.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt similarity index 75% rename from pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/OverviewViewModel.kt rename to pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt index c2288e5e23..0cce7e419c 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/OverviewViewModel.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt @@ -1,19 +1,21 @@ package info.nightscout.pump.medtrum.ui.viewmodel -import info.nightscout.pump.medtrum.ui.BaseNavigator +import info.nightscout.pump.medtrum.ui.MedtrumBaseNavigator import info.nightscout.pump.medtrum.ui.viewmodel.BaseViewModel import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.LTag import javax.inject.Inject -class OverviewViewModel @Inject constructor( +class MedtrumOverviewViewModel @Inject constructor( private val aapsLogger: AAPSLogger -) : BaseViewModel() { +) : BaseViewModel() { val isPatchActivated : Boolean get() = false // TODO val isPatchConnected: Boolean get() = false // TODO + val bleStatus : String + get() ="" //TODO init { // TODO diff --git a/pump/medtrum/src/main/res/layout/medtrum_overview_fragment.xml b/pump/medtrum/src/main/res/layout/medtrum_overview_fragment.xml index f104a351de..471d939b6d 100644 --- a/pump/medtrum/src/main/res/layout/medtrum_overview_fragment.xml +++ b/pump/medtrum/src/main/res/layout/medtrum_overview_fragment.xml @@ -5,7 +5,7 @@ + type="info.nightscout.pump.medtrum.ui.viewmodel.MedtrumOverviewViewModel"/> - + android:fillViewport="true"> - - + android:orientation="horizontal" + android:paddingTop="2dp" + android:paddingBottom="5dp" + android:visibility="gone"> - - - - - + android:layout_marginLeft="5dp" + android:layout_marginRight="5dp" + android:gravity="center_vertical|center_horizontal" + android:text="@string/initializing" + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:background="@color/list_delimiter" /> + android:text="@string/medtrum_ble_status" + android:textSize="16sp" /> + android:text="@string/colon" + android:textSize="16sp" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:text="@{viewmodel.bleStatus}" + android:textColor="@android:color/white" + android:textSize="16sp" /> @@ -286,8 +107,8 @@ android:layout_height="match_parent" android:layout_weight="1" android:text="@string/string_new_patch" - android:enabled="@{!viewmodel.isPatchActivated}"/> - + android:enabled="@{!viewmodel.isPatchActivated}" + app:onSafeClick="@{() -> viewmodel.onClickActivation()}"/>