diff --git a/app/build.gradle b/app/build.gradle index 4ce21e51c3d..fce7945392c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -224,6 +224,11 @@ android { configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9' } + + buildFeatures { + dataBinding true + } + } allprojects { @@ -259,7 +264,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.biometric:biometric:1.0.1' - implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.recyclerview:recyclerview:${recyclerview_version}' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation "androidx.preference:preference-ktx:1.1.1" @@ -283,6 +288,7 @@ dependencies { implementation 'com.madgag.spongycastle:core:1.58.0.0' // Omnipod wizard implementation(name: "com.atech-software.android.library.wizardpager-1.1.4", ext: "aar") + implementation "androidx.paging:paging-runtime-ktx:${paging_version}" implementation("com.google.android:flexbox:0.3.0") { exclude group: "com.android.support" } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index d96fda8d3b4..0f7bc6bc7f0 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -1891,6 +1891,36 @@ public List getAllOmnipodHistoryRecordsFromTimeStamp(long } + public List getFilteredOmnipodHistoryRecords(long predecessor, long limit, String podSerial, boolean ascending) { + try { + Dao daoPodHistory = getDaoPodHistory(); + List podHistories; + QueryBuilder queryBuilder = daoPodHistory.queryBuilder(); + queryBuilder.orderBy("date", ascending); + queryBuilder.limit(limit); + if (predecessor > 0 || podSerial != null) { + Where where = queryBuilder.where(); + if (predecessor > 0) { + if (ascending) { + where.gt("date", predecessor); + } else { + where.lt("date", predecessor); + } + } + if (podSerial != null) { + where.eq("podSerial", podSerial); + } + } + PreparedQuery preparedQuery = queryBuilder.prepare(); + podHistories = daoPodHistory.query(preparedQuery); + return podHistories; + } catch (SQLException e) { + aapsLogger.error("Unhandled exception", e); + } + return new ArrayList<>(); + } + + // Copied from xDrip+ String calculateDirection(BgReading bgReading) { // Rework to get bgreaings from internal DB and calculate on that base diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java index 4468692189e..bf9258bef0b 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java @@ -3,6 +3,7 @@ import com.j256.ormlite.dao.CloseableIterator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.sql.SQLException; import java.util.List; @@ -99,6 +100,10 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { return MainApp.getDbHelper().getAllOmnipodHistoryRecordsFromTimeStamp(timestamp, ascending); } + @NotNull @Override public List getFilteredOmnipodHistoryRecords(long until, long limit, @Nullable String podSerial, boolean ascending) { + return MainApp.getDbHelper().getFilteredOmnipodHistoryRecords(until,limit,podSerial,ascending); + } + @NotNull @Override public List getTDDsForLastXDays(int days) { return MainApp.getDbHelper().getTDDsForLastXDays(days); } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt index b59f4a84165..bf1d228aa50 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt @@ -16,6 +16,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.initpod.InitPod import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.pages.InitPodRefreshAction import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.pages.PodInfoFragment import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.removepod.RemoveActionFragment +import info.nightscout.androidaps.plugins.pump.omnipod.ui.PodHistoryDetailFragment +import info.nightscout.androidaps.plugins.pump.omnipod.ui.PodHistoryListFragment @Module @Suppress("unused") @@ -30,6 +32,8 @@ abstract class OmnipodModule { @ContributesAndroidInjector abstract fun initActionFragment(): InitActionFragment @ContributesAndroidInjector abstract fun removeActionFragment(): RemoveActionFragment @ContributesAndroidInjector abstract fun podInfoFragment(): PodInfoFragment + @ContributesAndroidInjector abstract fun podHistoryListFragment(): PodHistoryListFragment + @ContributesAndroidInjector abstract fun podHistoryDetailFragment(): PodHistoryDetailFragment // Service @ContributesAndroidInjector diff --git a/build.gradle b/build.gradle index aeeb75768d0..9eeba28619b 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,8 @@ buildscript { activityVersion = '1.2.0-alpha06' fragmentVersion = '1.3.0-alpha07' ormLiteVersion = "4.46" + paging_version = "2.1.2" + recyclerview_version = "1.1.0" } repositories { google() diff --git a/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java b/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java index 0f4b56b096b..dd83b26c63c 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java +++ b/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java @@ -3,13 +3,15 @@ import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import java.io.Serializable; + import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; /** * Created by andy on 30.11.2019. */ @DatabaseTable(tableName = "PodHistory") -public class OmnipodHistoryRecord implements DbObjectBase, Comparable { +public class OmnipodHistoryRecord implements DbObjectBase, Comparable, Serializable { @DatabaseField(id = true) public long date; diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt index 007ff88b90a..2cc25e2dff0 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt @@ -24,6 +24,7 @@ interface DatabaseHelperInterface { fun getTemporaryBasalsDataFromTime(mills: Long, ascending: Boolean): List fun getCareportalEventFromTimestamp(timestamp: Long): CareportalEvent? fun getAllOmnipodHistoryRecordsFromTimestamp(timestamp: Long, ascending: Boolean): List + fun getFilteredOmnipodHistoryRecords(until: Long, limit: Long, podSerial: String?, ascending: Boolean): List fun getTDDsForLastXDays(days: Int): List fun getProfileSwitchData(from: Long, ascending: Boolean): List } diff --git a/omnipod/build.gradle b/omnipod/build.gradle index c3b3a84f35d..993b965f260 100644 --- a/omnipod/build.gradle +++ b/omnipod/build.gradle @@ -48,6 +48,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildFeatures { + dataBinding true + } } allprojects { @@ -91,10 +94,13 @@ dependencies { implementation 'net.danlew:android.joda:2.10.6' implementation "com.google.code.gson:gson:2.8.6" implementation(name: "com.atech-software.android.library.wizardpager-1.1.4", ext: "aar") + implementation "androidx.paging:paging-runtime-ktx:${paging_version}" // Omnipod - end implementation "com.google.dagger:dagger-android:$dagger_version" implementation "com.google.dagger:dagger-android-support:$dagger_version" + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.recyclerview:recyclerview:${recyclerview_version}' annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version" kapt "com.google.dagger:dagger-android-processor:$dagger_version" diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/data/OmnipodHistoryRecordDataSource.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/data/OmnipodHistoryRecordDataSource.kt new file mode 100644 index 00000000000..51ae554fe94 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/data/OmnipodHistoryRecordDataSource.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.data + +import androidx.paging.ItemKeyedDataSource +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.interfaces.DatabaseHelperInterface +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import java.lang.Exception + +class OmnipodHistoryRecordDataSource(val databaseHelper: DatabaseHelperInterface, val aapsLogger: AAPSLogger) : ItemKeyedDataSource() { + + override fun getKey(item: OmnipodHistoryRecord): Long { + return item.date + } + + override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { + aapsLogger.info(LTag.PUMP,"Fetching initial data") + try { + val results = databaseHelper.getFilteredOmnipodHistoryRecords( + params.requestedInitialKey ?: 0, + params.requestedLoadSize.toLong(), + null, + false) + aapsLogger.info(LTag.PUMP, "Got %d results", results.size) + callback.onResult(results) + } catch (e : Exception) { + aapsLogger.error(LTag.PUMP,e.toString()) + } + } + + override fun loadAfter(params: LoadParams, callback: LoadCallback) { + val results = databaseHelper.getFilteredOmnipodHistoryRecords( + params.key, + params.requestedLoadSize.toLong(), + null, + false) + callback.onResult(results) + } + + override fun loadBefore(params: LoadParams, callback: LoadCallback) { + val results = databaseHelper.getFilteredOmnipodHistoryRecords( + params.key, + params.requestedLoadSize.toLong(), + null, + true) + callback.onResult(results) + } + +} \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodHistoryItemClicked.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodHistoryItemClicked.kt new file mode 100644 index 00000000000..39aa08130e6 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/event/EventOmnipodHistoryItemClicked.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.event + +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.events.Event + +data class EventOmnipodHistoryItemClicked(val record: OmnipodHistoryRecord) : Event() \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordViewHolder.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordViewHolder.kt new file mode 100644 index 00000000000..7bcc24b0d2c --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordViewHolder.kt @@ -0,0 +1,129 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.ui + +import android.graphics.Color +import android.graphics.PorterDuff +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil +import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.definition.PodHistoryEntryType +import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodHistoryItemClicked +import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil +import info.nightscout.androidaps.utils.resources.ResourceHelper + +class OmnipodHistoryRecordViewHolder(view: View, val aapsLogger: AAPSLogger, val aapsOmnipodUtil: AapsOmnipodUtil, val resourceHelper: ResourceHelper, val rxBus: RxBusWrapper) : RecyclerView.ViewHolder(view) { + + private val time: TextView = view.findViewById(R.id.omnipod_history_time) + private val type: TextView = view.findViewById(R.id.omnipod_history_source) + private val value: TextView = view.findViewById(R.id.omnipod_history_description) + private val layout: LinearLayout = view.findViewById(R.id.omnipod_history_item_layout) + private val standardBackgroundColorFilter = view.background.colorFilter + + private var record: OmnipodHistoryRecord? = null + + init { + itemView.setOnClickListener { + val record = this.record + record?.let { + rxBus.send(EventOmnipodHistoryItemClicked(record)) + } + } + } + + fun bind(record: OmnipodHistoryRecord?) { + this.record = record + record?.let { + time.text = record.dateTimeString + type.setText(PodHistoryEntryType.getByCode(record.podEntryTypeCode).resourceId) + value.text = description(record) + + when { + !record.isSuccess -> + layout.background.setColorFilter(Color.parseColor("#80ff0000"), PorterDuff.Mode.OVERLAY) + PodHistoryEntryType.getByCode(record.podEntryTypeCode) == PodHistoryEntryType.PAIR_AND_PRIME -> + layout.background.setColorFilter(Color.parseColor("#8000ff00"), PorterDuff.Mode.OVERLAY) + else -> + layout.background.colorFilter = standardBackgroundColorFilter + } + } + } + + private fun description(record: OmnipodHistoryRecord) : String { + if (record.isSuccess) { + return when (PodHistoryEntryType.getByCode(record.podEntryTypeCode)) { + PodHistoryEntryType.SET_TEMPORARY_BASAL -> { + val tempBasalPair: TempBasalPair = aapsOmnipodUtil.gsonInstance.fromJson(record.data, TempBasalPair::class.java) + resourceHelper.gs(R.string.omnipod_cmd_tbr_value, tempBasalPair.insulinRate, tempBasalPair.durationMinutes) + } + + PodHistoryEntryType.FILL_CANNULA_SET_BASAL_PROFILE, + PodHistoryEntryType.SET_BASAL_SCHEDULE -> profileValue(record.data) + + PodHistoryEntryType.SET_BOLUS -> { + if (record.data.contains(";")) { + val splitVal = record.data.split(";".toRegex()).toTypedArray() + resourceHelper.gs(R.string.omnipod_cmd_bolus_value_with_carbs, java.lang.Double.valueOf(splitVal[0]), java.lang.Double.valueOf(splitVal[1])) + } else { + resourceHelper.gs(R.string.omnipod_cmd_bolus_value, java.lang.Double.valueOf(record.data)) + } + } + + PodHistoryEntryType.PAIR_AND_PRIME -> { + resourceHelper.gs(R.string.omnipod_history_new_pod_serial,record.podSerial) + } + + PodHistoryEntryType.GET_POD_STATUS, + PodHistoryEntryType.GET_POD_INFO, + PodHistoryEntryType.SET_TIME, + PodHistoryEntryType.CANCEL_TEMPORARY_BASAL, + PodHistoryEntryType.CANCEL_TEMPORARY_BASAL_BY_DRIVER, + PodHistoryEntryType.CONFIGURE_ALERTS, + PodHistoryEntryType.CANCEL_BOLUS, + PodHistoryEntryType.DEACTIVATE_POD, + PodHistoryEntryType.RESET_POD_STATE, + PodHistoryEntryType.ACKNOWLEDGE_ALERTS, + PodHistoryEntryType.SUSPEND_DELIVERY, + PodHistoryEntryType.RESUME_DELIVERY, + PodHistoryEntryType.UNKNOWN_ENTRY_TYPE -> "" + else -> "" + } + } else { + return record.data + } + } + + private fun profileValue(data: String?) : String { + if (data != null) { + aapsLogger.debug(LTag.PUMP, "Profile json:\n$data") + try { + val profileValuesArray: Array = aapsOmnipodUtil.getGsonInstance().fromJson(data, Array::class.java) + return ProfileUtil.getBasalProfilesDisplayable(profileValuesArray, PumpType.Insulet_Omnipod) + } catch (e: Exception) { + aapsLogger.error(LTag.PUMP, "Problem parsing Profile json. Ex: {}, Data:\n{}", e.message, data) + return "" + } + } else { + return "" + } + } + + companion object { + + fun create(parent: ViewGroup, aapsLogger: AAPSLogger, aapsOmnipodUtil: AapsOmnipodUtil, resourceHelper: ResourceHelper, rxBus: RxBusWrapper) : OmnipodHistoryRecordViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.omnipod_pod_history_item, parent, false) + return OmnipodHistoryRecordViewHolder(view, aapsLogger, aapsOmnipodUtil, resourceHelper, rxBus) + } + } + +} \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordsAdapter.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordsAdapter.kt new file mode 100644 index 00000000000..e833ae26612 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodHistoryRecordsAdapter.kt @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.ui + +import android.view.ViewGroup +import androidx.paging.PagedListAdapter +import androidx.recyclerview.widget.DiffUtil +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +class OmnipodHistoryRecordsAdapter @Inject constructor() : PagedListAdapter(DIFF_CALLBACK) { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var aapsOmnipodUtil: AapsOmnipodUtil + @Inject lateinit var rxBus: RxBusWrapper + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OmnipodHistoryRecordViewHolder { + return OmnipodHistoryRecordViewHolder.create(parent ,aapsLogger, aapsOmnipodUtil, resourceHelper, rxBus) + } + + override fun onBindViewHolder(holder: OmnipodHistoryRecordViewHolder, position: Int) { + val record: OmnipodHistoryRecord = getItem(position)!! + holder.bind(record) + } + + companion object { + + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: OmnipodHistoryRecord, newItem: OmnipodHistoryRecord) = + oldItem.compareTo(newItem) == 0 + + override fun areContentsTheSame(oldItem: OmnipodHistoryRecord, newItem: OmnipodHistoryRecord) = + areItemsTheSame(oldItem,newItem) + + } + + } + +} \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java deleted file mode 100644 index 4913bb66149..00000000000 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.java +++ /dev/null @@ -1,340 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.ui; - -import android.os.Bundle; -import android.os.SystemClock; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Spinner; -import android.widget.TextView; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.List; - -import javax.inject.Inject; - -import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.OmnipodHistoryRecord; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.R; -import info.nightscout.androidaps.plugins.pump.omnipod.definition.PodHistoryEntryType; -import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil; -import info.nightscout.androidaps.utils.resources.ResourceHelper; - -public class PodHistoryActivity extends NoSplashAppCompatActivity { - - @Inject AAPSLogger aapsLogger; - @Inject AapsOmnipodUtil aapsOmnipodUtil; - @Inject ResourceHelper resourceHelper; - @Inject DatabaseHelperInterface databaseHelper; - - private Spinner historyTypeSpinner; - private TextView statusView; - private RecyclerView recyclerView; - private LinearLayoutManager linearLayoutManager; - - private static PumpHistoryEntryGroup selectedGroup = PumpHistoryEntryGroup.All; - private final List fullHistoryList = new ArrayList<>(); - private final List filteredHistoryList = new ArrayList<>(); - - private RecyclerViewAdapter recyclerViewAdapter; - private boolean manualChange = false; - - private List typeListFull; - - - public PodHistoryActivity() { - super(); - } - - - private void prepareData() { - GregorianCalendar gc = new GregorianCalendar(); - gc.add(Calendar.HOUR_OF_DAY, -24); - - databaseHelper.getAllOmnipodHistoryRecordsFromTimestamp(gc.getTimeInMillis(), false); - - fullHistoryList.addAll(databaseHelper.getAllOmnipodHistoryRecordsFromTimestamp(gc.getTimeInMillis(), true)); - } - - - private void filterHistory(PumpHistoryEntryGroup group) { - - this.filteredHistoryList.clear(); - - aapsLogger.debug(LTag.PUMP, "Items on full list: {}", fullHistoryList.size()); - - if (group == PumpHistoryEntryGroup.All) { - this.filteredHistoryList.addAll(fullHistoryList); - } else { - for (OmnipodHistoryRecord pumpHistoryEntry : fullHistoryList) { - if (PodHistoryEntryType.getByCode(pumpHistoryEntry.getPodEntryTypeCode()).getGroup() == group) { - this.filteredHistoryList.add(pumpHistoryEntry); - } - } - } - - if (this.recyclerViewAdapter != null) { - this.recyclerViewAdapter.setHistoryList(this.filteredHistoryList); - this.recyclerViewAdapter.notifyDataSetChanged(); - } - - aapsLogger.debug(LTag.PUMP, "Items on filtered list: {}", filteredHistoryList.size()); - } - - - @Override - protected void onResume() { - super.onResume(); - filterHistory(selectedGroup); - setHistoryTypeSpinner(); - } - - - private void setHistoryTypeSpinner() { - this.manualChange = true; - - for (int i = 0; i < typeListFull.size(); i++) { - if (typeListFull.get(i).entryGroup == selectedGroup) { - historyTypeSpinner.setSelection(i); - break; - } - } - - SystemClock.sleep(200); - this.manualChange = false; - } - - - @Override - protected void onPause() { - super.onPause(); - } - - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.omnipod_pod_history_activity); - - historyTypeSpinner = findViewById(R.id.omnipod_historytype); - statusView = findViewById(R.id.omnipod_historystatus); - recyclerView = findViewById(R.id.omnipod_history_recyclerview); - recyclerView.setHasFixedSize(true); - - linearLayoutManager = new LinearLayoutManager(this); - recyclerView.setLayoutManager(linearLayoutManager); - - prepareData(); - - recyclerViewAdapter = new RecyclerViewAdapter(filteredHistoryList); - recyclerView.setAdapter(recyclerViewAdapter); - - statusView.setVisibility(View.GONE); - - typeListFull = getTypeList(PumpHistoryEntryGroup.getTranslatedList(resourceHelper)); - - ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, R.layout.spinner_centered, typeListFull); - historyTypeSpinner.setAdapter(spinnerAdapter); - - historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - if (manualChange) - return; - TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); - selectedGroup = selected.entryGroup; - filterHistory(selectedGroup); - } - - - @Override - public void onNothingSelected(AdapterView parent) { - if (manualChange) - return; - filterHistory(PumpHistoryEntryGroup.All); - } - }); - - } - - - private List getTypeList(List list) { - - ArrayList typeList = new ArrayList<>(); - - for (PumpHistoryEntryGroup pumpHistoryEntryGroup : list) { - typeList.add(new TypeList(pumpHistoryEntryGroup)); - } - - return typeList; - } - - static class TypeList { - - final PumpHistoryEntryGroup entryGroup; - final String name; - - TypeList(PumpHistoryEntryGroup entryGroup) { - this.entryGroup = entryGroup; - this.name = entryGroup.getTranslated(); - } - - @NotNull - @Override - public String toString() { - return name; - } - } - - public class RecyclerViewAdapter extends RecyclerView.Adapter { - - List historyList; - - RecyclerViewAdapter(List historyList) { - this.historyList = historyList; - } - - - void setHistoryList(List historyList) { - this.historyList = historyList; - Collections.sort(this.historyList); - } - - - @NotNull - @Override - public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.omnipod_pod_history_item, // - viewGroup, false); - return new HistoryViewHolder(v); - } - - - @Override - public void onBindViewHolder(@NotNull HistoryViewHolder holder, int position) { - OmnipodHistoryRecord record = historyList.get(position); - - if (record != null) { - holder.timeView.setText(record.getDateTimeString()); - holder.typeView.setText(PodHistoryEntryType.getByCode(record.getPodEntryTypeCode()).getResourceId()); - setValue(record, holder.valueView); - } - } - - - private void setValue(OmnipodHistoryRecord historyEntry, TextView valueView) { - //valueView.setText(""); - - if (historyEntry.isSuccess()) { - PodHistoryEntryType entryType = PodHistoryEntryType.getByCode(historyEntry.getPodEntryTypeCode()); - switch (entryType) { - - case SET_TEMPORARY_BASAL: { - TempBasalPair tempBasalPair = aapsOmnipodUtil.getGsonInstance().fromJson(historyEntry.getData(), TempBasalPair.class); - valueView.setText(resourceHelper.gs(R.string.omnipod_cmd_tbr_value, tempBasalPair.getInsulinRate(), tempBasalPair.getDurationMinutes())); - } - break; - - case FILL_CANNULA_SET_BASAL_PROFILE: - case SET_BASAL_SCHEDULE: { - if (historyEntry.getData() != null) { - setProfileValue(historyEntry.getData(), valueView); - } - } - break; - - case SET_BOLUS: { - if (historyEntry.getData().contains(";")) { - String[] splitVal = historyEntry.getData().split(";"); - valueView.setText(resourceHelper.gs(R.string.omnipod_cmd_bolus_value_with_carbs, Double.valueOf(splitVal[0]), Double.valueOf(splitVal[1]))); - } else { - valueView.setText(resourceHelper.gs(R.string.omnipod_cmd_bolus_value, Double.valueOf(historyEntry.getData()))); - } - } - break; - - case GET_POD_STATUS: - case GET_POD_INFO: - case SET_TIME: - case PAIR_AND_PRIME: - case CANCEL_TEMPORARY_BASAL_BY_DRIVER: - case CANCEL_TEMPORARY_BASAL: - case CONFIGURE_ALERTS: - case CANCEL_BOLUS: - case DEACTIVATE_POD: - case RESET_POD_STATE: - case ACKNOWLEDGE_ALERTS: - case SUSPEND_DELIVERY: - case RESUME_DELIVERY: - case UNKNOWN_ENTRY_TYPE: - default: - valueView.setText(""); - break; - - } - } else { - valueView.setText(historyEntry.getData()); - } - - } - - private void setProfileValue(String data, TextView valueView) { - aapsLogger.debug(LTag.PUMP, "Profile json:\n" + data); - - try { - Profile.ProfileValue[] profileValuesArray = aapsOmnipodUtil.getGsonInstance().fromJson(data, Profile.ProfileValue[].class); - valueView.setText(ProfileUtil.getBasalProfilesDisplayable(profileValuesArray, PumpType.Insulet_Omnipod)); - } catch (Exception e) { - aapsLogger.error(LTag.PUMP, "Problem parsing Profile json. Ex: {}, Data:\n{}", e.getMessage(), data); - valueView.setText(""); - } - } - - - @Override - public int getItemCount() { - return historyList.size(); - } - - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - - class HistoryViewHolder extends RecyclerView.ViewHolder { - - final TextView timeView; - final TextView typeView; - final TextView valueView; - - HistoryViewHolder(View itemView) { - super(itemView); - timeView = itemView.findViewById(R.id.omnipod_history_time); - typeView = itemView.findViewById(R.id.omnipod_history_source); - valueView = itemView.findViewById(R.id.omnipod_history_description); - } - } - } - -} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.kt new file mode 100644 index 00000000000..e9678e4ce97 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryActivity.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.ui + +import android.os.Bundle +import android.widget.Toast +import androidx.databinding.DataBindingUtil +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.databinding.OmnipodPodHistoryActivityBinding +import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodHistoryItemClicked +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.extensions.plusAssign +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import javax.inject.Inject + +class PodHistoryActivity @Inject constructor() : NoSplashAppCompatActivity() { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var fabricPrivacy: FabricPrivacy + + private var disposables: CompositeDisposable = CompositeDisposable() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + DataBindingUtil.setContentView(this, R.layout.omnipod_pod_history_activity) + } + + override fun onResume() { + super.onResume() + disposables += rxBus + .toObservable(EventOmnipodHistoryItemClicked::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + val detailFragment = PodHistoryDetailFragment.newInstance(it.record) + detailFragment.show(supportFragmentManager,detailFragment.tag) + }, { fabricPrivacy.logException(it) }) + } + + override fun onPause() { + super.onPause() + disposables.clear() + } + +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryDetailFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryDetailFragment.kt new file mode 100644 index 00000000000..1486544db42 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryDetailFragment.kt @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.ui + +import android.os.Bundle +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.databinding.OmnipodFragmentPodHistoryDetailListBinding + +const val ARG_RECORD = "omnipod_history_record" + +class PodHistoryDetailFragment : BottomSheetDialogFragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val binding = DataBindingUtil.inflate(inflater,R.layout.omnipod_fragment_pod_history_detail_list, container, false) + binding.record = requireArguments().getSerializable(ARG_RECORD) as OmnipodHistoryRecord + return binding.root + } + + companion object { + + fun newInstance(record: OmnipodHistoryRecord): PodHistoryDetailFragment = + PodHistoryDetailFragment().apply { + arguments = Bundle().apply { + putSerializable(ARG_RECORD,record) + } + } + + } +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryListFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryListFragment.kt new file mode 100644 index 00000000000..c218edfe70c --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodHistoryListFragment.kt @@ -0,0 +1,85 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.ui + +import android.content.Context +import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.Observer +import androidx.paging.DataSource +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import androidx.recyclerview.widget.DividerItemDecoration +import dagger.android.support.AndroidSupportInjection +import info.nightscout.androidaps.db.OmnipodHistoryRecord +import info.nightscout.androidaps.interfaces.DatabaseHelperInterface +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.data.OmnipodHistoryRecordDataSource +import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsPodStateManager +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +/** + * A fragment representing a list of Items. + */ +class PodHistoryListFragment @Inject constructor() : Fragment() { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var databaseHelper: DatabaseHelperInterface + @Inject lateinit var podStateManager: AapsPodStateManager + @Inject lateinit var omnipodHistoryRecordsAdapter: OmnipodHistoryRecordsAdapter + + override fun onAttach(context: Context) { + AndroidSupportInjection.inject(this) + super.onAttach(context) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + + try { + aapsLogger.info(LTag.PUMP, "Creating list view fragment") + + val view = inflater.inflate(R.layout.omnipod_fragment_pod_history_list, container, false) + + val recyclerView: RecyclerView = view.findViewById(R.id.omnipod_history_recyclerview) + recyclerView.setHasFixedSize(true) + //linearLayoutManager = LinearLayoutManager(this) + recyclerView.layoutManager = LinearLayoutManager(activity as Context) + recyclerView.adapter = omnipodHistoryRecordsAdapter + recyclerView.addItemDecoration(DividerItemDecoration(recyclerView.context, DividerItemDecoration.VERTICAL)) + //view.findViewById().visibility = View.GONE + + val dataSourceFactory = object : DataSource.Factory() { + override fun create(): DataSource { + return OmnipodHistoryRecordDataSource(databaseHelper, aapsLogger) + } + } + + val records = LivePagedListBuilder(dataSourceFactory, PagedList.Config.Builder().setPageSize(30).build()).build() + + records.observe(activity as FragmentActivity, Observer> { pagedList -> omnipodHistoryRecordsAdapter.submitList(pagedList) }) + + aapsLogger.info(LTag.PUMP, "Created list view fragment") + + return view + } catch (e : Exception) { + aapsLogger.error("Error: ",e) + throw e + } + } + + companion object { + + @JvmStatic + fun newInstance() = + PodHistoryListFragment() + } +} \ No newline at end of file diff --git a/omnipod/src/main/res/layout/omnipod_fragment_pod_history_detail_list.xml b/omnipod/src/main/res/layout/omnipod_fragment_pod_history_detail_list.xml new file mode 100644 index 00000000000..703047652f8 --- /dev/null +++ b/omnipod/src/main/res/layout/omnipod_fragment_pod_history_detail_list.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/omnipod/src/main/res/layout/omnipod_fragment_pod_history_list.xml b/omnipod/src/main/res/layout/omnipod_fragment_pod_history_list.xml new file mode 100644 index 00000000000..d96bce6c006 --- /dev/null +++ b/omnipod/src/main/res/layout/omnipod_fragment_pod_history_list.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/omnipod/src/main/res/layout/omnipod_pod_history_activity.xml b/omnipod/src/main/res/layout/omnipod_pod_history_activity.xml index 9a2c304b5cc..cacb504a042 100644 --- a/omnipod/src/main/res/layout/omnipod_pod_history_activity.xml +++ b/omnipod/src/main/res/layout/omnipod_pod_history_activity.xml @@ -1,58 +1,18 @@ - + - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + - - - - - + \ No newline at end of file diff --git a/omnipod/src/main/res/layout/omnipod_pod_history_item.xml b/omnipod/src/main/res/layout/omnipod_pod_history_item.xml index bbbc8ddc089..1c8e2761205 100644 --- a/omnipod/src/main/res/layout/omnipod_pod_history_item.xml +++ b/omnipod/src/main/res/layout/omnipod_pod_history_item.xml @@ -1,8 +1,10 @@ @@ -30,4 +32,4 @@ android:gravity="center_vertical" android:textSize="12dp" /> - \ No newline at end of file + diff --git a/omnipod/src/main/res/values/dimens.xml b/omnipod/src/main/res/values/dimens.xml new file mode 100644 index 00000000000..2bbc1fd2001 --- /dev/null +++ b/omnipod/src/main/res/values/dimens.xml @@ -0,0 +1,6 @@ + + + 16dp + 8dp + 16dp + \ No newline at end of file diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 65a8b8d45a2..e508673741a 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -123,6 +123,7 @@ Set basal profile Cancel delivery Deactivate Pod + New pod serial: %s Finish pairing reminder