Merge pull request #1449 from Andries-Smit/feat/relative-date
Feat relative date
This commit is contained in:
commit
873ef227db
|
@ -3,7 +3,6 @@ package info.nightscout.androidaps.activities.fragments
|
|||
import android.annotation.SuppressLint
|
||||
import android.graphics.Paint
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.SparseArray
|
||||
import android.view.*
|
||||
import android.widget.CompoundButton
|
||||
|
@ -190,7 +189,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
removeActionMode?.let { it.finish() }
|
||||
removeActionMode?.finish()
|
||||
binding.recyclerview.adapter = null // avoid leaks
|
||||
_binding = null
|
||||
}
|
||||
|
@ -206,9 +205,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
val profile = profileFunction.getProfile() ?: return
|
||||
val ml = mealLinks[position]
|
||||
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(timestamp(ml), timestamp(mealLinks[position - 1]))
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(timestamp(ml))
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(timestamp(ml), timestamp(mealLinks[position - 1]))
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(timestamp(ml), rh) else ""
|
||||
|
||||
// Metadata
|
||||
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility()
|
||||
|
@ -272,7 +271,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
|||
}
|
||||
holder.binding.calculation.tag = ml
|
||||
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(timestamp(ml), nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = mealLinks.size
|
||||
|
|
|
@ -149,7 +149,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
removeActionMode?.let { it.finish() }
|
||||
removeActionMode?.finish()
|
||||
binding.recyclerview.adapter = null // avoid leaks
|
||||
_binding = null
|
||||
}
|
||||
|
@ -165,9 +165,9 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
val therapyEvent = therapyList[position]
|
||||
holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility()
|
||||
holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility()
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(therapyEvent.timestamp, therapyList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(therapyEvent.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(therapyEvent.timestamp, therapyList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(therapyEvent.timestamp, rh) else ""
|
||||
holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp)
|
||||
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
|
||||
holder.binding.note.text = therapyEvent.note
|
||||
|
@ -185,7 +185,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
|||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||
}
|
||||
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = therapyList.size
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.activities.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.util.SparseArray
|
||||
import android.view.*
|
||||
|
@ -114,7 +113,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
removeActionMode?.let { it.finish() }
|
||||
removeActionMode?.finish()
|
||||
binding.recyclerview.adapter = null // avoid leaks
|
||||
_binding = null
|
||||
}
|
||||
|
@ -131,10 +130,9 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
|
||||
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
|
||||
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp)
|
||||
@SuppressLint("SetTextI18n")
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(extendedBolus.timestamp, rh) else ""
|
||||
if (extendedBolus.isInProgress(dateUtil)) {
|
||||
holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp)
|
||||
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
|
||||
|
@ -162,7 +160,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
|||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||
}
|
||||
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = extendedBolusList.size
|
||||
|
|
|
@ -184,9 +184,9 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
|||
val profileSwitch = profileSwitchList[position]
|
||||
holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
|
||||
holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility()
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(profileSwitch.timestamp, rh) else ""
|
||||
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
|
||||
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
|
||||
holder.binding.name.text =
|
||||
|
@ -213,7 +213,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
|||
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||
val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = profileSwitchList.size
|
||||
|
|
|
@ -154,7 +154,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
removeActionMode?.let { it.finish() }
|
||||
removeActionMode?.finish()
|
||||
binding.recyclerview.adapter = null // avoid leaks
|
||||
_binding = null
|
||||
}
|
||||
|
@ -185,9 +185,9 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
}
|
||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||
}
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(tempTarget.timestamp, tempTargetList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempTarget.timestamp, rh) else ""
|
||||
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
|
||||
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
|
||||
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
|
||||
|
@ -201,7 +201,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
|||
}
|
||||
)
|
||||
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempTarget.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = tempTargetList.size
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package info.nightscout.androidaps.activities.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.SparseArray
|
||||
import android.view.*
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
|
@ -155,7 +154,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
@Synchronized
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
removeActionMode?.let { it.finish() }
|
||||
removeActionMode?.finish()
|
||||
binding.recyclerview.adapter = null // avoid leaks
|
||||
_binding = null
|
||||
}
|
||||
|
@ -172,7 +171,9 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempBasal.timestamp, rh) else ""
|
||||
if (tempBasal.isInProgress) {
|
||||
holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp)
|
||||
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
|
||||
|
@ -206,7 +207,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
|||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
||||
}
|
||||
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempBasal.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
override fun getItemCount() = tempBasalList.size
|
||||
|
|
|
@ -128,9 +128,9 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
|||
|
||||
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
|
||||
val current = entries[position]
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(current.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDayGroup(current.timestamp, entries[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(current.timestamp, rh) else ""
|
||||
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
|
||||
holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action)
|
||||
holder.binding.notes.text = current.note
|
||||
|
@ -140,7 +140,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
|||
holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values)
|
||||
holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE
|
||||
val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(current.timestamp, nextTimestamp).toVisibility()
|
||||
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(current.timestamp, nextTimestamp).toVisibility()
|
||||
}
|
||||
|
||||
inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
|
|
@ -147,9 +147,9 @@ class BGSourceFragment : DaggerFragment() {
|
|||
val glucoseValue = glucoseValues[position]
|
||||
holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility()
|
||||
holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility()
|
||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp)
|
||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||
holder.binding.date.text = dateUtil.dateString(glucoseValue.timestamp)
|
||||
val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp)
|
||||
holder.binding.date.visibility = newDay.toVisibility()
|
||||
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else ""
|
||||
holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp)
|
||||
holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
|
||||
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.stream.Collectors
|
|||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* The Class DateUtil. A simple wrapper around SimpleDateFormat to ease the handling of iso date string <-> date obj
|
||||
|
@ -56,8 +58,6 @@ class DateUtil @Inject constructor(private val context: Context) {
|
|||
* Render date
|
||||
*
|
||||
* @param date the date obj
|
||||
* @param format - if not specified, will use FORMAT_DATE_ISO
|
||||
* @param tz - tz to set to, if not specified uses local timezone
|
||||
* @return the iso-formatted date string
|
||||
*/
|
||||
fun toISOString(date: Long): String {
|
||||
|
@ -104,6 +104,26 @@ class DateUtil @Inject constructor(private val context: Context) {
|
|||
return df.format(mills)
|
||||
}
|
||||
|
||||
fun dateStringRelative(mills: Long, rh: ResourceHelper): String {
|
||||
val df = DateFormat.getDateInstance(DateFormat.SHORT)
|
||||
val day = df.format(mills)
|
||||
val beginOfToday = beginOfDay(now())
|
||||
return if (mills < now()) // Past
|
||||
when {
|
||||
mills > beginOfToday -> rh.gs(R.string.today)
|
||||
mills > beginOfToday - T.days(1).msecs() -> rh.gs(R.string.yesterday)
|
||||
mills > beginOfToday - T.days(7).msecs() -> dayAgo(mills, rh, true)
|
||||
else -> day
|
||||
}
|
||||
else // Future
|
||||
when {
|
||||
mills < beginOfToday + T.days(1).msecs() -> rh.gs(R.string.later_today)
|
||||
mills < beginOfToday + T.days(2).msecs() -> rh.gs(R.string.tomorrow)
|
||||
mills < beginOfToday + T.days(7).msecs() -> dayAgo(mills, rh, true)
|
||||
else -> day
|
||||
}
|
||||
}
|
||||
|
||||
fun dateStringShort(mills: Long): String {
|
||||
var format = "MM/dd"
|
||||
if (android.text.format.DateFormat.is24HourFormat(context)) {
|
||||
|
@ -167,6 +187,33 @@ class DateUtil @Inject constructor(private val context: Context) {
|
|||
return rh.gs(R.string.hoursago, hours)
|
||||
}
|
||||
|
||||
fun dayAgo(time: Long, rh: ResourceHelper, round: Boolean = false): String {
|
||||
var days = (now() - time) / 1000.0 / 60 / 60 / 24
|
||||
if (round) {
|
||||
if (now() > time) {
|
||||
days = ceil(days)
|
||||
return rh.gs(R.string.days_ago_round, days)
|
||||
} else {
|
||||
days = floor(days)
|
||||
return rh.gs(R.string.in_days_round, days)
|
||||
}
|
||||
}
|
||||
return if (now() > time)
|
||||
rh.gs(R.string.days_ago, days)
|
||||
else
|
||||
rh.gs(R.string.in_days, days)
|
||||
}
|
||||
|
||||
fun beginOfDay(mills: Long): Long {
|
||||
val givenDate = Calendar.getInstance()
|
||||
givenDate.timeInMillis = mills
|
||||
givenDate[Calendar.HOUR_OF_DAY] = 0
|
||||
givenDate[Calendar.MINUTE] = 0
|
||||
givenDate[Calendar.SECOND] = 0
|
||||
givenDate[Calendar.MILLISECOND] = 0
|
||||
return givenDate.timeInMillis
|
||||
}
|
||||
|
||||
fun timeStringFromSeconds(seconds: Int): String {
|
||||
val cached = timeStrings[seconds.toLong()]
|
||||
if (cached != null) return cached
|
||||
|
@ -220,6 +267,13 @@ class DateUtil @Inject constructor(private val context: Context) {
|
|||
|
||||
fun isSameDay(timestamp1: Long, timestamp2: Long) = isSameDay(Date(timestamp1), Date(timestamp2))
|
||||
|
||||
fun isSameDayGroup(timestamp1: Long, timestamp2: Long): Boolean {
|
||||
val now = now()
|
||||
if (timestamp1 < now && timestamp2 > now || timestamp1 > now && timestamp2 < now)
|
||||
return false
|
||||
return isSameDay(Date(timestamp1), Date(timestamp2))
|
||||
}
|
||||
|
||||
//Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
|
||||
fun computeDiff(date1: Long, date2: Long): Map<TimeUnit, Long> {
|
||||
val units: MutableList<TimeUnit> = ArrayList(EnumSet.allOf(TimeUnit::class.java))
|
||||
|
|
|
@ -204,6 +204,10 @@
|
|||
<string name="minago">%1$d m ago</string>
|
||||
<string name="minago_long">%1$d minutes ago</string>
|
||||
<string name="hoursago">%1$.1f h ago</string>
|
||||
<string name="days_ago">%1$.1f days ago</string>
|
||||
<string name="days_ago_round">%1$.0f days ago</string>
|
||||
<string name="in_days">in %1$.0f days</string>
|
||||
<string name="in_days_round">in %1$.0f days</string>
|
||||
<string name="shorthour">h</string>
|
||||
<string name="days">days</string>
|
||||
<string name="hours">hours</string>
|
||||
|
@ -219,6 +223,10 @@
|
|||
<string name="unit_weeks">weeks</string>
|
||||
<string name="shortminute">m</string>
|
||||
<string name="shortday">d</string>
|
||||
<string name="later_today">Later today</string>
|
||||
<string name="tomorrow">Tomorrow</string>
|
||||
<string name="today">Today</string>
|
||||
<string name="yesterday">Yesterday</string>
|
||||
|
||||
<!-- Protection-->
|
||||
<string name="wrongpassword">Wrong password</string>
|
||||
|
|
Loading…
Reference in a new issue