From 81eb4f3a1cf30c7e4b445f20fa07c138d5faea61 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 18 Sep 2023 21:00:54 +0200 Subject: [PATCH] simplify :app-wear-shared:shared --- .../extensions/PackageManagerExtension.kt | 0 .../shared/impl/di/SharedImplModule.kt | 24 + .../impl}/logging/AAPSLoggerProduction.kt | 4 +- .../shared/impl/rx/AapsSchedulersImpl.kt | 16 + .../shared/impl/rx/bus/RxBusImpl.kt | 34 ++ .../nightscout/shared/utils/DateUtilImpl.kt | 470 +++++++++++++++++ .../src/main/res/drawable/background.xml | 6 +- .../src/main/res/drawable/detailed_dial.xml | 306 +++++++++++ .../src/main/res/drawable/hour_hand.xml | 9 + .../src/main/res/drawable/minute_hand.xml | 9 + .../src/main/res/drawable/second_hand.xml | 9 + .../src/main/res/drawable/simplified_dial.xml | 66 +++ .../main/res/drawable/watchface_custom.png | Bin app-wear-shared/shared-tests/build.gradle | 4 +- .../nightscout/sharedtests}/AAPSLoggerTest.kt | 5 +- .../info/nightscout/sharedtests/TestBase.kt | 3 +- .../sharedtests/TestBaseWithProfile.kt | 10 +- .../sharedtests/rx/TestAapsSchedulers.kt | 17 + .../java/info/nightscout/rx/AapsSchedulers.kt | 17 +- .../main/java/info/nightscout/rx/bus/RxBus.kt | 26 +- .../java/info/nightscout/rx/di/RxModule.kt | 25 - .../info/nightscout/shared/di/SharedModule.kt | 9 - .../info/nightscout/shared/utils/DateUtil.kt | 494 ++---------------- .../src/main/res/drawable/detailed_dial.xml | 183 ------- .../src/main/res/drawable/hour_hand.xml | 4 - .../src/main/res/drawable/minute_hand.xml | 4 - .../src/main/res/drawable/second_hand.xml | 4 - .../src/main/res/drawable/simplified_dial.xml | 39 -- .../nightscout/androidaps/di/AppComponent.kt | 8 +- .../interfaces/utils/DecimalFormatter.kt | 0 .../ui/src/main/res/values-sw600dp/layout.xml | 3 + core/ui/src/main/res/values/layout.xml | 3 + core/validators/build.gradle | 1 + .../maintenance/MaintenanceFragment.kt | 3 +- plugins/main/build.gradle | 1 + .../general/overview/OverviewPlugin.kt | 3 +- plugins/source/build.gradle | 1 + plugins/sync/build.gradle | 1 + .../nightscout/pump/combo/ComboFragment.kt | 8 +- pump/diaconn/build.gradle | 1 + .../pump/eopatch/alarm/AlarmRegistry.kt | 49 +- .../omnipod/dash/history/DashHistoryTest.kt | 2 +- .../driver/comm/endecrypt/EnDecryptTest.kt | 2 +- .../dash/driver/comm/pair/KeyExchangeTest.kt | 2 +- .../driver/comm/session/EapMessageTest.kt | 2 +- .../dash/driver/comm/session/MilenageTest.kt | 2 +- pump/omnipod-eros/build.gradle | 2 + .../manager/AapsErosPodStateManagerTest.kt | 6 +- .../nightscout/androidaps/di/WearModule.kt | 4 - .../androidaps/watchfaces/CustomWatchface.kt | 49 +- .../watchfaces/DigitalStyleWatchface.kt | 3 - .../heartrate/HeartRateListenerTest.kt | 26 +- 52 files changed, 1145 insertions(+), 834 deletions(-) rename app-wear-shared/{shared => shared-impl}/src/main/java/info/nightscout/shared/extensions/PackageManagerExtension.kt (100%) rename app-wear-shared/{shared/src/main/java/info/nightscout/rx => shared-impl/src/main/java/info/nightscout/shared/impl}/logging/AAPSLoggerProduction.kt (96%) create mode 100644 app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/AapsSchedulersImpl.kt create mode 100644 app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/bus/RxBusImpl.kt create mode 100644 app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/utils/DateUtilImpl.kt rename app-wear-shared/{shared => shared-impl}/src/main/res/drawable/background.xml (66%) create mode 100644 app-wear-shared/shared-impl/src/main/res/drawable/detailed_dial.xml create mode 100644 app-wear-shared/shared-impl/src/main/res/drawable/hour_hand.xml create mode 100644 app-wear-shared/shared-impl/src/main/res/drawable/minute_hand.xml create mode 100644 app-wear-shared/shared-impl/src/main/res/drawable/second_hand.xml create mode 100644 app-wear-shared/shared-impl/src/main/res/drawable/simplified_dial.xml rename app-wear-shared/{shared => shared-impl}/src/main/res/drawable/watchface_custom.png (100%) rename app-wear-shared/{shared/src/main/java/info/nightscout/rx/logging => shared-tests/src/main/java/info/nightscout/sharedtests}/AAPSLoggerTest.kt (95%) create mode 100644 app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/rx/TestAapsSchedulers.kt delete mode 100644 app-wear-shared/shared/src/main/java/info/nightscout/rx/di/RxModule.kt delete mode 100644 app-wear-shared/shared/src/main/java/info/nightscout/shared/di/SharedModule.kt delete mode 100644 app-wear-shared/shared/src/main/res/drawable/detailed_dial.xml delete mode 100644 app-wear-shared/shared/src/main/res/drawable/hour_hand.xml delete mode 100644 app-wear-shared/shared/src/main/res/drawable/minute_hand.xml delete mode 100644 app-wear-shared/shared/src/main/res/drawable/second_hand.xml delete mode 100644 app-wear-shared/shared/src/main/res/drawable/simplified_dial.xml rename {app-wear-shared/shared => core/interfaces}/src/main/java/info/nightscout/interfaces/utils/DecimalFormatter.kt (100%) create mode 100644 core/ui/src/main/res/values-sw600dp/layout.xml create mode 100644 core/ui/src/main/res/values/layout.xml diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/shared/extensions/PackageManagerExtension.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/extensions/PackageManagerExtension.kt similarity index 100% rename from app-wear-shared/shared/src/main/java/info/nightscout/shared/extensions/PackageManagerExtension.kt rename to app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/extensions/PackageManagerExtension.kt diff --git a/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/di/SharedImplModule.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/di/SharedImplModule.kt index 3bf15a91d9..f823e124f4 100644 --- a/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/di/SharedImplModule.kt +++ b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/di/SharedImplModule.kt @@ -4,10 +4,18 @@ import android.content.Context import androidx.preference.PreferenceManager import dagger.Module import dagger.Provides +import info.nightscout.rx.AapsSchedulers +import info.nightscout.rx.bus.RxBus import info.nightscout.rx.interfaces.L +import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.shared.impl.logging.AAPSLoggerProduction import info.nightscout.shared.impl.logging.LImpl +import info.nightscout.shared.impl.rx.AapsSchedulersImpl +import info.nightscout.shared.impl.rx.bus.RxBusImpl import info.nightscout.shared.impl.sharedPreferences.SPImplementation import info.nightscout.shared.sharedPreferences.SP +import info.nightscout.shared.utils.DateUtil +import info.nightscout.shared.utils.DateUtilImpl import javax.inject.Singleton @Module( @@ -23,4 +31,20 @@ open class SharedImplModule { @Provides @Singleton fun provideL(sp: SP): L = LImpl(sp) + + @Provides + @Singleton + fun provideDateUtil(context: Context): DateUtil = DateUtilImpl(context) + + @Provides + @Singleton + fun provideAAPSLogger(l: L): AAPSLogger = AAPSLoggerProduction(l) + + @Provides + @Singleton + fun provideRxBus(aapsSchedulers: AapsSchedulers, aapsLogger: AAPSLogger): RxBus = RxBusImpl(aapsSchedulers, aapsLogger) + + @Provides + @Singleton + internal fun provideSchedulers(): AapsSchedulers = AapsSchedulersImpl() } \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerProduction.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/logging/AAPSLoggerProduction.kt similarity index 96% rename from app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerProduction.kt rename to app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/logging/AAPSLoggerProduction.kt index 4a6bcd8900..7335f9c842 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerProduction.kt +++ b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/logging/AAPSLoggerProduction.kt @@ -1,6 +1,8 @@ -package info.nightscout.rx.logging +package info.nightscout.shared.impl.logging import info.nightscout.rx.interfaces.L +import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.rx.logging.LTag import org.slf4j.LoggerFactory /** diff --git a/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/AapsSchedulersImpl.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/AapsSchedulersImpl.kt new file mode 100644 index 0000000000..a4f5c62847 --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/AapsSchedulersImpl.kt @@ -0,0 +1,16 @@ +package info.nightscout.shared.impl.rx + +import info.nightscout.rx.AapsSchedulers +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.Scheduler +import io.reactivex.rxjava3.schedulers.Schedulers +import javax.inject.Singleton + +@Singleton +class AapsSchedulersImpl : AapsSchedulers { + + override val main: Scheduler = AndroidSchedulers.mainThread() + override val io: Scheduler = Schedulers.io() + override val cpu: Scheduler = Schedulers.computation() + override val newThread: Scheduler = Schedulers.newThread() +} \ No newline at end of file diff --git a/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/bus/RxBusImpl.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/bus/RxBusImpl.kt new file mode 100644 index 0000000000..6338303dd3 --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/impl/rx/bus/RxBusImpl.kt @@ -0,0 +1,34 @@ +package info.nightscout.shared.impl.rx.bus + +import info.nightscout.annotations.OpenForTesting +import info.nightscout.rx.AapsSchedulers +import info.nightscout.rx.bus.RxBus +import info.nightscout.rx.events.Event +import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.rx.logging.LTag +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.subjects.PublishSubject +import javax.inject.Inject +import javax.inject.Singleton + +@OpenForTesting +@Singleton +class RxBusImpl @Inject constructor( + val aapsSchedulers: AapsSchedulers, + val aapsLogger: AAPSLogger +) : RxBus { + + private val publisher = PublishSubject.create() + + override fun send(event: Event) { + aapsLogger.debug(LTag.EVENTS, "Sending $event") + publisher.onNext(event) + } + + // Listen should return an Observable and not the publisher + // Using ofType we filter only events that match that class type + override fun toObservable(eventType: Class): Observable = + publisher + .subscribeOn(aapsSchedulers.io) + .ofType(eventType) +} \ No newline at end of file diff --git a/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/utils/DateUtilImpl.kt b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/utils/DateUtilImpl.kt new file mode 100644 index 0000000000..ee093019d6 --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/java/info/nightscout/shared/utils/DateUtilImpl.kt @@ -0,0 +1,470 @@ +package info.nightscout.shared.utils + +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.collection.LongSparseArray +import info.nightscout.annotations.OpenForTesting +import info.nightscout.shared.R +import info.nightscout.shared.SafeParse +import info.nightscout.shared.interfaces.ResourceHelper +import org.apache.commons.lang3.time.DateUtils.isSameDay +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import org.joda.time.format.ISODateTimeFormat +import java.security.SecureRandom +import java.text.DateFormat +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import java.text.SimpleDateFormat +import java.time.Instant +import java.time.ZoneId +import java.time.ZoneOffset +import java.util.Calendar +import java.util.Date +import java.util.EnumSet +import java.util.GregorianCalendar +import java.util.Locale +import java.util.TimeZone +import java.util.concurrent.TimeUnit +import java.util.regex.Pattern +import java.util.stream.Collectors +import javax.inject.Inject +import javax.inject.Singleton +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 + * with TZ + */ +@OpenForTesting +@Singleton +class DateUtilImpl @Inject constructor(private val context: Context) : DateUtil { + + /** + * The date format in iso. + */ + @Suppress("PrivatePropertyName", "SpellCheckingInspection") + private val FORMAT_DATE_ISO_OUT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + + /** + * Takes in an ISO date string of the following format: + * yyyy-mm-ddThh:mm:ss.ms+HoMo + * + * @param isoDateString the iso date string + * @return the date + */ + override fun fromISODateString(isoDateString: String): Long { + val parser = ISODateTimeFormat.dateTimeParser() + val dateTime = DateTime.parse(isoDateString, parser) + return dateTime.toDate().time + } + + /** + * Render date + * + * @param date the date obj + * @return the iso-formatted date string + */ + override fun toISOString(date: Long): String { + val f: DateFormat = SimpleDateFormat(FORMAT_DATE_ISO_OUT, Locale.getDefault()) + f.timeZone = TimeZone.getTimeZone("UTC") + return f.format(date) + } + + @Suppress("SpellCheckingInspection") + override fun toISOAsUTC(timestamp: Long): String { + val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'0000Z'", Locale.US) + format.timeZone = TimeZone.getTimeZone("UTC") + return format.format(timestamp) + } + + @Suppress("SpellCheckingInspection") + override fun toISONoZone(timestamp: Long): String { + val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US) + format.timeZone = TimeZone.getDefault() + return format.format(timestamp) + } + + override fun secondsOfTheDayToMilliseconds(seconds: Int): Long { + val calendar: Calendar = GregorianCalendar() + calendar[Calendar.MONTH] = 0 // Set january to be sure we miss DST changing + calendar[Calendar.HOUR_OF_DAY] = seconds / 60 / 60 + calendar[Calendar.MINUTE] = seconds / 60 % 60 + calendar[Calendar.SECOND] = 0 + return calendar.timeInMillis + } + + override fun toSeconds(hhColonMm: String): Int { + val p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)") + val m = p.matcher(hhColonMm) + var retVal = 0 + if (m.find()) { + retVal = SafeParse.stringToInt(m.group(1)) * 60 * 60 + SafeParse.stringToInt(m.group(2)) * 60 + if ((m.group(3) == " a.m." || m.group(3) == " AM" || m.group(3) == "AM") && m.group(1) == "12") retVal -= 12 * 60 * 60 + if ((m.group(3) == " p.m." || m.group(3) == " PM" || m.group(3) == "PM") && m.group(1) != "12") retVal += 12 * 60 * 60 + } + return retVal + } + + override fun dateString(mills: Long): String { + val df = DateFormat.getDateInstance(DateFormat.SHORT) + return df.format(mills) + } + + override 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 + } + } + + override fun dateStringShort(mills: Long): String { + var format = "MM/dd" + if (android.text.format.DateFormat.is24HourFormat(context)) { + format = "dd/MM" + } + return DateTime(mills).toString(DateTimeFormat.forPattern(format)) + } + + override fun timeString(): String = timeString(now()) + override fun timeString(mills: Long): String { + var format = "hh:mma" + if (android.text.format.DateFormat.is24HourFormat(context)) { + format = "HH:mm" + } + return DateTime(mills).toString(DateTimeFormat.forPattern(format)) + } + + override fun secondString(): String = secondString(now()) + override fun secondString(mills: Long): String = + DateTime(mills).toString(DateTimeFormat.forPattern("ss")) + + override fun minuteString(): String = minuteString(now()) + override fun minuteString(mills: Long): String = + DateTime(mills).toString(DateTimeFormat.forPattern("mm")) + + override fun hourString(): String = hourString(now()) + override fun hourString(mills: Long): String { + var format = "hh" + if (android.text.format.DateFormat.is24HourFormat(context)) { + format = "HH" + } + return DateTime(mills).toString(DateTimeFormat.forPattern(format)) + } + + override fun amPm(): String = amPm(now()) + override fun amPm(mills: Long): String = + DateTime(mills).toString(DateTimeFormat.forPattern("a")) + + override fun dayNameString(format: String): String = dayNameString(now(), format) + override fun dayNameString(mills: Long, format: String): String = + DateTime(mills).toString(DateTimeFormat.forPattern(format)) + + override fun dayString(): String = dayString(now()) + override fun dayString(mills: Long): String = + DateTime(mills).toString(DateTimeFormat.forPattern("dd")) + + override fun monthString(format: String): String = monthString(now(), format) + override fun monthString(mills: Long, format: String): String = + DateTime(mills).toString(DateTimeFormat.forPattern(format)) + + override fun weekString(): String = weekString(now()) + override fun weekString(mills: Long): String = + DateTime(mills).toString(DateTimeFormat.forPattern("ww")) + + override fun timeStringWithSeconds(mills: Long): String { + var format = "hh:mm:ssa" + if (android.text.format.DateFormat.is24HourFormat(context)) { + format = "HH:mm:ss" + } + return DateTime(mills).toString(DateTimeFormat.forPattern(format)) + } + + override fun dateAndTimeRangeString(start: Long, end: Long): String { + return dateAndTimeString(start) + " - " + timeString(end) + } + + override fun timeRangeString(start: Long, end: Long): String { + return timeString(start) + " - " + timeString(end) + } + + override fun dateAndTimeString(mills: Long): String { + return if (mills == 0L) "" else dateString(mills) + " " + timeString(mills) + } + + override fun dateAndTimeAndSecondsString(mills: Long): String { + return if (mills == 0L) "" else dateString(mills) + " " + timeStringWithSeconds(mills) + } + + override fun minAgo(rh: ResourceHelper, time: Long?): String { + if (time == null) return "" + val minutes = ((now() - time) / 1000 / 60).toInt() + return rh.gs(R.string.minago, minutes) + } + + override fun minAgoShort(time: Long?): String { + if (time == null) return "" + val minutes = ((time - now()) / 1000 / 60).toInt() + return (if (minutes > 0) "+" else "") + minutes + } + + override fun minAgoLong(rh: ResourceHelper, time: Long?): String { + if (time == null) return "" + val minutes = ((now() - time) / 1000 / 60).toInt() + return rh.gs(R.string.minago_long, minutes) + } + + override fun hourAgo(time: Long, rh: ResourceHelper): String { + val hours = (now() - time) / 1000.0 / 60 / 60 + return rh.gs(R.string.hoursago, hours) + } + + override fun dayAgo(time: Long, rh: ResourceHelper, round: Boolean): String { + var days = (now() - time) / 1000.0 / 60 / 60 / 24 + if (round) { + return if (now() > time) { + days = ceil(days) + rh.gs(R.string.days_ago_round, days) + } else { + days = floor(days) + 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) + } + + override 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 + } + + override fun timeStringFromSeconds(seconds: Int): String { + val cached = timeStrings[seconds.toLong()] + if (cached != null) return cached + val t = timeString(secondsOfTheDayToMilliseconds(seconds)) + timeStrings.put(seconds.toLong(), t) + return t + } + + override fun timeFrameString(timeInMillis: Long, rh: ResourceHelper): String { + var remainingTimeMinutes = timeInMillis / (1000 * 60) + val remainingTimeHours = remainingTimeMinutes / 60 + remainingTimeMinutes %= 60 + return "(" + (if (remainingTimeHours > 0) remainingTimeHours.toString() + rh.gs(R.string.shorthour) + " " else "") + remainingTimeMinutes + "')" + } + + override fun sinceString(timestamp: Long, rh: ResourceHelper): String { + return timeFrameString(System.currentTimeMillis() - timestamp, rh) + } + + override fun untilString(timestamp: Long, rh: ResourceHelper): String { + return timeFrameString(timestamp - System.currentTimeMillis(), rh) + } + + override fun now(): Long { + return System.currentTimeMillis() + } + + override fun nowWithoutMilliseconds(): Long { + var n = System.currentTimeMillis() + n -= n % 1000 + return n + } + + override fun isOlderThan(date: Long, minutes: Long): Boolean { + val diff = now() - date + return diff > T.mins(minutes).msecs() + } + + override fun getTimeZoneOffsetMs(): Long { + return GregorianCalendar().timeZone.rawOffset.toLong() + } + + override fun getTimeZoneOffsetMinutes(timestamp: Long): Int { + return TimeZone.getDefault().getOffset(timestamp) / 60000 + } + + override fun isSameDay(timestamp1: Long, timestamp2: Long) = isSameDay(Date(timestamp1), Date(timestamp2)) + + override fun isSameDayGroup(timestamp1: Long, timestamp2: Long): Boolean { + val now = now() + if (now in (timestamp1 + 1) until timestamp2 || now in (timestamp2 + 1) until timestamp1) + return false + return isSameDay(Date(timestamp1), Date(timestamp2)) + } + + //Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} + override fun computeDiff(date1: Long, date2: Long): Map { + val units: MutableList = ArrayList(EnumSet.allOf(TimeUnit::class.java)) + units.reverse() + val result: MutableMap = LinkedHashMap() + var millisecondsRest = date2 - date1 + for (unit in units) { + val diff = unit.convert(millisecondsRest, TimeUnit.MILLISECONDS) + val diffInMillisecondsForUnit = unit.toMillis(diff) + millisecondsRest -= diffInMillisecondsForUnit + result[unit] = diff + } + return result + } + + override fun age(milliseconds: Long, useShortText: Boolean, rh: ResourceHelper): String { + val diff = computeDiff(0L, milliseconds) + var days = " " + rh.gs(R.string.days) + " " + var hours = " " + rh.gs(R.string.hours) + " " + var minutes = " " + rh.gs(R.string.unit_minutes) + " " + if (useShortText) { + days = rh.gs(R.string.shortday) + hours = rh.gs(R.string.shorthour) + minutes = rh.gs(R.string.shortminute) + } + var result = "" + if (diff.getOrDefault(TimeUnit.DAYS, -1) > 0) result += diff[TimeUnit.DAYS].toString() + days + if (diff.getOrDefault(TimeUnit.HOURS, -1) > 0) result += diff[TimeUnit.HOURS].toString() + hours + if (diff[TimeUnit.DAYS] == 0L) result += diff[TimeUnit.MINUTES].toString() + minutes + return result + } + + override fun niceTimeScalar(time: Long, rh: ResourceHelper): String { + var t = time + var unit = rh.gs(R.string.unit_second) + t /= 1000 + if (t != 1L) unit = rh.gs(R.string.unit_seconds) + if (t > 59) { + unit = rh.gs(R.string.unit_minute) + t /= 60 + if (t != 1L) unit = rh.gs(R.string.unit_minutes) + if (t > 59) { + unit = rh.gs(R.string.unit_hour) + t /= 60 + if (t != 1L) unit = rh.gs(R.string.unit_hours) + if (t > 24) { + unit = rh.gs(R.string.unit_day) + t /= 24 + if (t != 1L) unit = rh.gs(R.string.unit_days) + if (t > 28) { + unit = rh.gs(R.string.unit_week) + t /= 7 + @Suppress("KotlinConstantConditions") + if (t != 1L) unit = rh.gs(R.string.unit_weeks) + } + } + } + } + //if (t != 1) unit = unit + "s"; //implemented plurality in every step, because in other languages plurality of time is not every time adding the same character + return qs(t.toDouble(), 0) + " " + unit + } + + override fun qs(x: Double, numDigits: Int): String { + var digits = numDigits + if (digits == -1) { + digits = 0 + if ((x.toInt() % x == 0.0)) { + digits++ + if ((x.toInt() * 10 / 10).toDouble() != x) { + digits++ + if ((x.toInt() * 100 / 100).toDouble() != x) digits++ + } + } + } + if (dfs == null) { + val localDfs = DecimalFormatSymbols() + localDfs.decimalSeparator = '.' + dfs = localDfs // avoid race condition + } + val thisDf: DecimalFormat? + // use singleton if on ui thread otherwise allocate new as DecimalFormat is not thread safe + if (Thread.currentThread().id == 1L) { + if (df == null) { + val localDf = DecimalFormat("#", dfs) + localDf.minimumIntegerDigits = 1 + df = localDf // avoid race condition + } + thisDf = df + } else { + thisDf = DecimalFormat("#", dfs) + } + thisDf?.maximumFractionDigits = digits + return thisDf?.format(x) ?: "" + } + + override fun formatHHMM(timeAsSeconds: Int): String { + val hour = timeAsSeconds / 60 / 60 + val minutes = (timeAsSeconds - hour * 60 * 60) / 60 + val df = DecimalFormat("00") + return df.format(hour.toLong()) + ":" + df.format(minutes.toLong()) + } + + @RequiresApi(Build.VERSION_CODES.O) + override fun timeZoneByOffset(offsetInMilliseconds: Long): TimeZone = + TimeZone.getTimeZone( + if (offsetInMilliseconds == 0L) ZoneId.of("UTC") + else ZoneId.getAvailableZoneIds() + .stream() + .map(ZoneId::of) + .filter { z -> z.rules.getOffset(Instant.now()).totalSeconds == ZoneOffset.ofHours((offsetInMilliseconds / 1000 / 3600).toInt()).totalSeconds } + .collect(Collectors.toList()) + .firstOrNull() ?: ZoneId.of("UTC") + ) + + override fun timeStampToUtcDateMillis(timestamp: Long): Long { + val current = Calendar.getInstance().apply { timeInMillis = timestamp } + return Calendar.getInstance().apply { + set(Calendar.YEAR, current[Calendar.YEAR]) + set(Calendar.MONTH, current[Calendar.MONTH]) + set(Calendar.DAY_OF_MONTH, current[Calendar.DAY_OF_MONTH]) + }.timeInMillis + } + + override fun mergeUtcDateToTimestamp(timestamp: Long, dateUtcMillis: Long): Long { + val selected = Calendar.getInstance().apply { timeInMillis = dateUtcMillis } + return Calendar.getInstance().apply { + timeInMillis = timestamp + set(Calendar.YEAR, selected[Calendar.YEAR]) + set(Calendar.MONTH, selected[Calendar.MONTH]) + set(Calendar.DAY_OF_MONTH, selected[Calendar.DAY_OF_MONTH]) + }.timeInMillis + } + + override fun mergeHourMinuteToTimestamp(timestamp: Long, hour: Int, minute: Int, randomSecond: Boolean): Long { + return Calendar.getInstance().apply { + timeInMillis = timestamp + set(Calendar.HOUR_OF_DAY, hour) + set(Calendar.MINUTE, minute) + if (randomSecond) set(Calendar.SECOND, seconds++) + }.timeInMillis + } + + companion object { + + private val timeStrings = LongSparseArray() + private var seconds: Int = (SecureRandom().nextDouble() * 59.0).toInt() + + // singletons to avoid repeated allocation + private var dfs: DecimalFormatSymbols? = null + private var df: DecimalFormat? = null + } +} diff --git a/app-wear-shared/shared/src/main/res/drawable/background.xml b/app-wear-shared/shared-impl/src/main/res/drawable/background.xml similarity index 66% rename from app-wear-shared/shared/src/main/res/drawable/background.xml rename to app-wear-shared/shared-impl/src/main/res/drawable/background.xml index 76226923e6..e8f62fdfa3 100644 --- a/app-wear-shared/shared/src/main/res/drawable/background.xml +++ b/app-wear-shared/shared-impl/src/main/res/drawable/background.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - + diff --git a/app-wear-shared/shared-impl/src/main/res/drawable/detailed_dial.xml b/app-wear-shared/shared-impl/src/main/res/drawable/detailed_dial.xml new file mode 100644 index 0000000000..d3a62c944e --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/res/drawable/detailed_dial.xml @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app-wear-shared/shared-impl/src/main/res/drawable/hour_hand.xml b/app-wear-shared/shared-impl/src/main/res/drawable/hour_hand.xml new file mode 100644 index 0000000000..fc748e1b8f --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/res/drawable/hour_hand.xml @@ -0,0 +1,9 @@ + + + diff --git a/app-wear-shared/shared-impl/src/main/res/drawable/minute_hand.xml b/app-wear-shared/shared-impl/src/main/res/drawable/minute_hand.xml new file mode 100644 index 0000000000..8e11c2fa1d --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/res/drawable/minute_hand.xml @@ -0,0 +1,9 @@ + + + diff --git a/app-wear-shared/shared-impl/src/main/res/drawable/second_hand.xml b/app-wear-shared/shared-impl/src/main/res/drawable/second_hand.xml new file mode 100644 index 0000000000..e768022ba5 --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/res/drawable/second_hand.xml @@ -0,0 +1,9 @@ + + + diff --git a/app-wear-shared/shared-impl/src/main/res/drawable/simplified_dial.xml b/app-wear-shared/shared-impl/src/main/res/drawable/simplified_dial.xml new file mode 100644 index 0000000000..aa440fe5ab --- /dev/null +++ b/app-wear-shared/shared-impl/src/main/res/drawable/simplified_dial.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + diff --git a/app-wear-shared/shared/src/main/res/drawable/watchface_custom.png b/app-wear-shared/shared-impl/src/main/res/drawable/watchface_custom.png similarity index 100% rename from app-wear-shared/shared/src/main/res/drawable/watchface_custom.png rename to app-wear-shared/shared-impl/src/main/res/drawable/watchface_custom.png diff --git a/app-wear-shared/shared-tests/build.gradle b/app-wear-shared/shared-tests/build.gradle index da77123e24..9c4a8730fa 100644 --- a/app-wear-shared/shared-tests/build.gradle +++ b/app-wear-shared/shared-tests/build.gradle @@ -14,16 +14,18 @@ apply from: "${project.rootDir}/core/main/jacoco_global.gradle" android { namespace 'info.nightscout.sharedtests' - } +} dependencies { implementation project(':database:entities') implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') implementation project(':core:interfaces') implementation project(':core:main') implementation project(':core:utils') implementation project(':implementation') + api "org.mockito:mockito-junit-jupiter:$mockito_version" api "org.mockito.kotlin:mockito-kotlin:5.1.0" api "org.junit.jupiter:junit-jupiter-api:$junit_jupiter_version" diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerTest.kt b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/AAPSLoggerTest.kt similarity index 95% rename from app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerTest.kt rename to app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/AAPSLoggerTest.kt index 88142c93a8..562aa66403 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/logging/AAPSLoggerTest.kt +++ b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/AAPSLoggerTest.kt @@ -1,4 +1,7 @@ -package info.nightscout.rx.logging +package info.nightscout.sharedtests + +import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.rx.logging.LTag /** * Created by adrian on 2019-12-27. diff --git a/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBase.kt b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBase.kt index 1e52c7fbea..35f4960822 100644 --- a/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBase.kt +++ b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBase.kt @@ -2,8 +2,7 @@ package info.nightscout.sharedtests import android.annotation.SuppressLint import info.nightscout.rx.AapsSchedulers -import info.nightscout.rx.TestAapsSchedulers -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.rx.TestAapsSchedulers import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.extension.ExtendWith import org.mockito.ArgumentMatcher diff --git a/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBaseWithProfile.kt b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBaseWithProfile.kt index cb2ceb610f..8a03a6fbbb 100644 --- a/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBaseWithProfile.kt +++ b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/TestBaseWithProfile.kt @@ -19,11 +19,11 @@ import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileStore import info.nightscout.interfaces.utils.DecimalFormatter import info.nightscout.interfaces.utils.HardLimits -import info.nightscout.rx.bus.RxBus +import info.nightscout.shared.impl.rx.bus.RxBusImpl import info.nightscout.shared.interfaces.ProfileUtil import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP -import info.nightscout.shared.utils.DateUtil +import info.nightscout.shared.utils.DateUtilImpl import org.json.JSONObject import org.junit.jupiter.api.BeforeEach import org.mockito.ArgumentMatchers.anyDouble @@ -45,11 +45,11 @@ open class TestBaseWithProfile : TestBase() { @Mock lateinit var context: Context @Mock lateinit var sp: SP - lateinit var dateUtil: DateUtil + lateinit var dateUtil: DateUtilImpl lateinit var profileUtil: ProfileUtil lateinit var decimalFormatter: DecimalFormatter lateinit var hardLimits: HardLimits - val rxBus = RxBus(aapsSchedulers, aapsLogger) + val rxBus = RxBusImpl(aapsSchedulers, aapsLogger) val profileInjector = HasAndroidInjector { AndroidInjector { @@ -82,7 +82,7 @@ open class TestBaseWithProfile : TestBase() { invalidProfileJSON = "{\"dia\":\"1\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," + "{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," + "\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" - dateUtil = Mockito.spy(DateUtil(context)) + dateUtil = Mockito.spy(DateUtilImpl(context)) decimalFormatter = DecimalFormatterImpl(rh) profileUtil = ProfileUtilImpl(sp, decimalFormatter) testPumpPlugin = TestPumpPlugin(profileInjector) diff --git a/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/rx/TestAapsSchedulers.kt b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/rx/TestAapsSchedulers.kt new file mode 100644 index 0000000000..e9b18431ce --- /dev/null +++ b/app-wear-shared/shared-tests/src/main/java/info/nightscout/sharedtests/rx/TestAapsSchedulers.kt @@ -0,0 +1,17 @@ +package info.nightscout.sharedtests.rx + +import info.nightscout.rx.AapsSchedulers +import io.reactivex.rxjava3.core.Scheduler +import io.reactivex.rxjava3.schedulers.Schedulers + +/** + * Created by adrian on 12.04.20. + */ + +class TestAapsSchedulers : AapsSchedulers { + + override val main: Scheduler = Schedulers.trampoline() + override val io: Scheduler = Schedulers.trampoline() + override val cpu: Scheduler = Schedulers.trampoline() + override val newThread: Scheduler = Schedulers.trampoline() +} \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/AapsSchedulers.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/AapsSchedulers.kt index 4377909f3d..af6f4f1cda 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/AapsSchedulers.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/AapsSchedulers.kt @@ -1,30 +1,15 @@ package info.nightscout.rx -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Scheduler -import io.reactivex.rxjava3.schedulers.Schedulers /** * Created by adrian on 12.04.20. */ interface AapsSchedulers { + val main: Scheduler val io: Scheduler val cpu: Scheduler val newThread: Scheduler -} - -class DefaultAapsSchedulers : AapsSchedulers { - override val main: Scheduler = AndroidSchedulers.mainThread() - override val io: Scheduler = Schedulers.io() - override val cpu: Scheduler = Schedulers.computation() - override val newThread: Scheduler = Schedulers.newThread() -} - -class TestAapsSchedulers : AapsSchedulers { - override val main: Scheduler = Schedulers.trampoline() - override val io: Scheduler = Schedulers.trampoline() - override val cpu: Scheduler = Schedulers.trampoline() - override val newThread: Scheduler = Schedulers.trampoline() } \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/bus/RxBus.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/bus/RxBus.kt index 438fad7ed9..e2649036c5 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/bus/RxBus.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/bus/RxBus.kt @@ -1,33 +1,13 @@ package info.nightscout.rx.bus -import info.nightscout.annotations.OpenForTesting -import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.events.Event -import info.nightscout.rx.logging.AAPSLogger -import info.nightscout.rx.logging.LTag import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.subjects.PublishSubject -import javax.inject.Inject -import javax.inject.Singleton -@OpenForTesting -@Singleton -class RxBus @Inject constructor( - val aapsSchedulers: AapsSchedulers, - val aapsLogger: AAPSLogger -) { +interface RxBus { - private val publisher = PublishSubject.create() - - fun send(event: Event) { - aapsLogger.debug(LTag.EVENTS, "Sending $event") - publisher.onNext(event) - } + fun send(event: Event) // Listen should return an Observable and not the publisher // Using ofType we filter only events that match that class type - fun toObservable(eventType: Class): Observable = - publisher - .subscribeOn(aapsSchedulers.io) - .ofType(eventType) + fun toObservable(eventType: Class): Observable } \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/di/RxModule.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/di/RxModule.kt deleted file mode 100644 index 0e584cf5e7..0000000000 --- a/app-wear-shared/shared/src/main/java/info/nightscout/rx/di/RxModule.kt +++ /dev/null @@ -1,25 +0,0 @@ -package info.nightscout.rx.di - -import dagger.Module -import dagger.Provides -import info.nightscout.rx.AapsSchedulers -import info.nightscout.rx.DefaultAapsSchedulers -import info.nightscout.rx.interfaces.L -import info.nightscout.rx.logging.AAPSLogger -import info.nightscout.rx.logging.AAPSLoggerProduction -import javax.inject.Singleton - -@Module( - includes = [ - ] -) -open class RxModule { - - @Provides - @Singleton - internal fun provideSchedulers(): AapsSchedulers = DefaultAapsSchedulers() - - @Provides - @Singleton - fun provideAAPSLogger(l: L): AAPSLogger = AAPSLoggerProduction(l) -} \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/shared/di/SharedModule.kt b/app-wear-shared/shared/src/main/java/info/nightscout/shared/di/SharedModule.kt deleted file mode 100644 index 735de9f807..0000000000 --- a/app-wear-shared/shared/src/main/java/info/nightscout/shared/di/SharedModule.kt +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.shared.di - -import dagger.Module - -@Module( - includes = [ - ] -) -open class SharedModule \ No newline at end of file diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/shared/utils/DateUtil.kt b/app-wear-shared/shared/src/main/java/info/nightscout/shared/utils/DateUtil.kt index 361a52b600..41afa1adb2 100644 --- a/app-wear-shared/shared/src/main/java/info/nightscout/shared/utils/DateUtil.kt +++ b/app-wear-shared/shared/src/main/java/info/nightscout/shared/utils/DateUtil.kt @@ -1,52 +1,16 @@ package info.nightscout.shared.utils -import android.content.Context import android.os.Build import androidx.annotation.RequiresApi -import androidx.collection.LongSparseArray -import info.nightscout.annotations.OpenForTesting -import info.nightscout.shared.R -import info.nightscout.shared.SafeParse import info.nightscout.shared.interfaces.ResourceHelper -import org.apache.commons.lang3.time.DateUtils.isSameDay -import org.joda.time.DateTime -import org.joda.time.format.DateTimeFormat -import org.joda.time.format.ISODateTimeFormat -import java.security.SecureRandom -import java.text.DateFormat -import java.text.DecimalFormat -import java.text.DecimalFormatSymbols -import java.text.SimpleDateFormat -import java.time.Instant -import java.time.ZoneId -import java.time.ZoneOffset -import java.util.Calendar -import java.util.Date -import java.util.EnumSet -import java.util.GregorianCalendar -import java.util.Locale import java.util.TimeZone import java.util.concurrent.TimeUnit -import java.util.regex.Pattern -import java.util.stream.Collectors -import javax.inject.Inject -import javax.inject.Singleton -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 * with TZ */ -@OpenForTesting -@Singleton -class DateUtil @Inject constructor(private val context: Context) { - - /** - * The date format in iso. - */ - @Suppress("PrivatePropertyName", "SpellCheckingInspection") - private val FORMAT_DATE_ISO_OUT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" +interface DateUtil { /** * Takes in an ISO date string of the following format: @@ -55,11 +19,7 @@ class DateUtil @Inject constructor(private val context: Context) { * @param isoDateString the iso date string * @return the date */ - fun fromISODateString(isoDateString: String): Long { - val parser = ISODateTimeFormat.dateTimeParser() - val dateTime = DateTime.parse(isoDateString, parser) - return dateTime.toDate().time - } + fun fromISODateString(isoDateString: String): Long /** * Render date @@ -67,404 +27,66 @@ class DateUtil @Inject constructor(private val context: Context) { * @param date the date obj * @return the iso-formatted date string */ - fun toISOString(date: Long): String { - val f: DateFormat = SimpleDateFormat(FORMAT_DATE_ISO_OUT, Locale.getDefault()) - f.timeZone = TimeZone.getTimeZone("UTC") - return f.format(date) - } - - @Suppress("SpellCheckingInspection") - fun toISOAsUTC(timestamp: Long): String { - val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'0000Z'", Locale.US) - format.timeZone = TimeZone.getTimeZone("UTC") - return format.format(timestamp) - } - - @Suppress("SpellCheckingInspection") - fun toISONoZone(timestamp: Long): String { - val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US) - format.timeZone = TimeZone.getDefault() - return format.format(timestamp) - } - - fun secondsOfTheDayToMilliseconds(seconds: Int): Long { - val calendar: Calendar = GregorianCalendar() - calendar[Calendar.MONTH] = 0 // Set january to be sure we miss DST changing - calendar[Calendar.HOUR_OF_DAY] = seconds / 60 / 60 - calendar[Calendar.MINUTE] = seconds / 60 % 60 - calendar[Calendar.SECOND] = 0 - return calendar.timeInMillis - } - - fun toSeconds(hhColonMm: String): Int { - val p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)") - val m = p.matcher(hhColonMm) - var retVal = 0 - if (m.find()) { - retVal = SafeParse.stringToInt(m.group(1)) * 60 * 60 + SafeParse.stringToInt(m.group(2)) * 60 - if ((m.group(3) == " a.m." || m.group(3) == " AM" || m.group(3) == "AM") && m.group(1) == "12") retVal -= 12 * 60 * 60 - if ((m.group(3) == " p.m." || m.group(3) == " PM" || m.group(3) == "PM") && m.group(1) != "12") retVal += 12 * 60 * 60 - } - return retVal - } - - fun dateString(mills: Long): String { - val df = DateFormat.getDateInstance(DateFormat.SHORT) - 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)) { - format = "dd/MM" - } - return DateTime(mills).toString(DateTimeFormat.forPattern(format)) - } - - fun timeString(): String = timeString(now()) - fun timeString(mills: Long): String { - var format = "hh:mma" - if (android.text.format.DateFormat.is24HourFormat(context)) { - format = "HH:mm" - } - return DateTime(mills).toString(DateTimeFormat.forPattern(format)) - } - - fun secondString(): String = secondString(now()) - fun secondString(mills: Long): String = - DateTime(mills).toString(DateTimeFormat.forPattern("ss")) - - fun minuteString(): String = minuteString(now()) - fun minuteString(mills: Long): String = - DateTime(mills).toString(DateTimeFormat.forPattern("mm")) - - fun hourString(): String = hourString(now()) - fun hourString(mills: Long): String { - var format = "hh" - if (android.text.format.DateFormat.is24HourFormat(context)) { - format = "HH" - } - return DateTime(mills).toString(DateTimeFormat.forPattern(format)) - } - - fun amPm(): String = amPm(now()) - fun amPm(mills: Long): String = - DateTime(mills).toString(DateTimeFormat.forPattern("a")) - - fun dayNameString(format: String = "E"): String = dayNameString(now(), format) - fun dayNameString(mills: Long, format: String = "E"): String = - DateTime(mills).toString(DateTimeFormat.forPattern(format)) - + fun toISOString(date: Long): String + fun toISOAsUTC(timestamp: Long): String + fun toISONoZone(timestamp: Long): String + fun secondsOfTheDayToMilliseconds(seconds: Int): Long + fun toSeconds(hhColonMm: String): Int + fun dateString(mills: Long): String + fun dateStringRelative(mills: Long, rh: ResourceHelper): String + fun dateStringShort(mills: Long): String + fun timeString(): String + fun timeString(mills: Long): String + fun secondString(): String + fun secondString(mills: Long): String + fun minuteString(): String + fun minuteString(mills: Long): String + fun hourString(): String + fun hourString(mills: Long): String + fun amPm(): String + fun amPm(mills: Long): String + fun dayNameString(format: String = "E"): String + fun dayNameString(mills: Long, format: String = "E"): String fun dayString(): String = dayString(now()) - fun dayString(mills: Long): String = - DateTime(mills).toString(DateTimeFormat.forPattern("dd")) + fun dayString(mills: Long): String + fun monthString(format: String = "MMM"): String + fun monthString(mills: Long, format: String = "MMM"): String + fun weekString(): String + fun weekString(mills: Long): String + fun timeStringWithSeconds(mills: Long): String + fun dateAndTimeRangeString(start: Long, end: Long): String + fun timeRangeString(start: Long, end: Long): String + fun dateAndTimeString(mills: Long): String + fun dateAndTimeAndSecondsString(mills: Long): String + fun minAgo(rh: ResourceHelper, time: Long?): String + fun minAgoShort(time: Long?): String + fun minAgoLong(rh: ResourceHelper, time: Long?): String + fun hourAgo(time: Long, rh: ResourceHelper): String + fun dayAgo(time: Long, rh: ResourceHelper, round: Boolean = false): String + fun beginOfDay(mills: Long): Long + fun timeStringFromSeconds(seconds: Int): String + fun timeFrameString(timeInMillis: Long, rh: ResourceHelper): String + fun sinceString(timestamp: Long, rh: ResourceHelper): String + fun untilString(timestamp: Long, rh: ResourceHelper): String + fun now(): Long + fun nowWithoutMilliseconds(): Long + fun isOlderThan(date: Long, minutes: Long): Boolean + fun getTimeZoneOffsetMs(): Long + fun getTimeZoneOffsetMinutes(timestamp: Long): Int + fun isSameDay(timestamp1: Long, timestamp2: Long): Boolean - fun monthString(format: String = "MMM"): String = monthString(now(), format) - fun monthString(mills: Long, format: String = "MMM"): String = - DateTime(mills).toString(DateTimeFormat.forPattern(format)) - - fun weekString(): String = weekString(now()) - fun weekString(mills: Long): String = - DateTime(mills).toString(DateTimeFormat.forPattern("ww")) - - fun timeStringWithSeconds(mills: Long): String { - var format = "hh:mm:ssa" - if (android.text.format.DateFormat.is24HourFormat(context)) { - format = "HH:mm:ss" - } - return DateTime(mills).toString(DateTimeFormat.forPattern(format)) - } - - fun dateAndTimeRangeString(start: Long, end: Long): String { - return dateAndTimeString(start) + " - " + timeString(end) - } - - fun timeRangeString(start: Long, end: Long): String { - return timeString(start) + " - " + timeString(end) - } - - fun dateAndTimeString(mills: Long): String { - return if (mills == 0L) "" else dateString(mills) + " " + timeString(mills) - } - - fun dateAndTimeAndSecondsString(mills: Long): String { - return if (mills == 0L) "" else dateString(mills) + " " + timeStringWithSeconds(mills) - } - - fun minAgo(rh: ResourceHelper, time: Long?): String { - if (time == null) return "" - val minutes = ((now() - time) / 1000 / 60).toInt() - return rh.gs(R.string.minago, minutes) - } - - fun minAgoShort(time: Long?): String { - if (time == null) return "" - val minutes = ((time - now()) / 1000 / 60).toInt() - return (if (minutes > 0) "+" else "") + minutes - } - - fun minAgoLong(rh: ResourceHelper, time: Long?): String { - if (time == null) return "" - val minutes = ((now() - time) / 1000 / 60).toInt() - return rh.gs(R.string.minago_long, minutes) - } - - fun hourAgo(time: Long, rh: ResourceHelper): String { - val hours = (now() - time) / 1000.0 / 60 / 60 - 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) { - return if (now() > time) { - days = ceil(days) - rh.gs(R.string.days_ago_round, days) - } else { - days = floor(days) - 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 - val t = timeString(secondsOfTheDayToMilliseconds(seconds)) - timeStrings.put(seconds.toLong(), t) - return t - } - - fun timeFrameString(timeInMillis: Long, rh: ResourceHelper): String { - var remainingTimeMinutes = timeInMillis / (1000 * 60) - val remainingTimeHours = remainingTimeMinutes / 60 - remainingTimeMinutes %= 60 - return "(" + (if (remainingTimeHours > 0) remainingTimeHours.toString() + rh.gs(R.string.shorthour) + " " else "") + remainingTimeMinutes + "')" - } - - fun sinceString(timestamp: Long, rh: ResourceHelper): String { - return timeFrameString(System.currentTimeMillis() - timestamp, rh) - } - - fun untilString(timestamp: Long, rh: ResourceHelper): String { - return timeFrameString(timestamp - System.currentTimeMillis(), rh) - } - - fun now(): Long { - return System.currentTimeMillis() - } - - fun nowWithoutMilliseconds(): Long { - var n = System.currentTimeMillis() - n -= n % 1000 - return n - } - - fun isOlderThan(date: Long, minutes: Long): Boolean { - val diff = now() - date - return diff > T.mins(minutes).msecs() - } - - fun getTimeZoneOffsetMs(): Long { - return GregorianCalendar().timeZone.rawOffset.toLong() - } - - fun getTimeZoneOffsetMinutes(timestamp: Long): Int { - return TimeZone.getDefault().getOffset(timestamp) / 60000 - } - - fun isSameDay(timestamp1: Long, timestamp2: Long) = isSameDay(Date(timestamp1), Date(timestamp2)) - - fun isSameDayGroup(timestamp1: Long, timestamp2: Long): Boolean { - val now = now() - if (now in (timestamp1 + 1) until timestamp2 || now in (timestamp2 + 1) until timestamp1) - return false - return isSameDay(Date(timestamp1), Date(timestamp2)) - } + fun isSameDayGroup(timestamp1: Long, timestamp2: Long): Boolean //Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} - fun computeDiff(date1: Long, date2: Long): Map { - val units: MutableList = ArrayList(EnumSet.allOf(TimeUnit::class.java)) - units.reverse() - val result: MutableMap = LinkedHashMap() - var millisecondsRest = date2 - date1 - for (unit in units) { - val diff = unit.convert(millisecondsRest, TimeUnit.MILLISECONDS) - val diffInMillisecondsForUnit = unit.toMillis(diff) - millisecondsRest -= diffInMillisecondsForUnit - result[unit] = diff - } - return result - } - - fun age(milliseconds: Long, useShortText: Boolean, rh: ResourceHelper): String { - val diff = computeDiff(0L, milliseconds) - var days = " " + rh.gs(R.string.days) + " " - var hours = " " + rh.gs(R.string.hours) + " " - var minutes = " " + rh.gs(R.string.unit_minutes) + " " - if (useShortText) { - days = rh.gs(R.string.shortday) - hours = rh.gs(R.string.shorthour) - minutes = rh.gs(R.string.shortminute) - } - var result = "" - if (diff.getOrDefault(TimeUnit.DAYS, -1) > 0) result += diff[TimeUnit.DAYS].toString() + days - if (diff.getOrDefault(TimeUnit.HOURS, -1) > 0) result += diff[TimeUnit.HOURS].toString() + hours - if (diff[TimeUnit.DAYS] == 0L) result += diff[TimeUnit.MINUTES].toString() + minutes - return result - } - - fun niceTimeScalar(time: Long, rh: ResourceHelper): String { - var t = time - var unit = rh.gs(R.string.unit_second) - t /= 1000 - if (t != 1L) unit = rh.gs(R.string.unit_seconds) - if (t > 59) { - unit = rh.gs(R.string.unit_minute) - t /= 60 - if (t != 1L) unit = rh.gs(R.string.unit_minutes) - if (t > 59) { - unit = rh.gs(R.string.unit_hour) - t /= 60 - if (t != 1L) unit = rh.gs(R.string.unit_hours) - if (t > 24) { - unit = rh.gs(R.string.unit_day) - t /= 24 - if (t != 1L) unit = rh.gs(R.string.unit_days) - if (t > 28) { - unit = rh.gs(R.string.unit_week) - t /= 7 - @Suppress("KotlinConstantConditions") - if (t != 1L) unit = rh.gs(R.string.unit_weeks) - } - } - } - } - //if (t != 1) unit = unit + "s"; //implemented plurality in every step, because in other languages plurality of time is not every time adding the same character - return qs(t.toDouble(), 0) + " " + unit - } - - fun qs(x: Double, numDigits: Int): String { - var digits = numDigits - if (digits == -1) { - digits = 0 - if ((x.toInt() % x == 0.0)) { - digits++ - if ((x.toInt() * 10 / 10).toDouble() != x) { - digits++ - if ((x.toInt() * 100 / 100).toDouble() != x) digits++ - } - } - } - if (dfs == null) { - val localDfs = DecimalFormatSymbols() - localDfs.decimalSeparator = '.' - dfs = localDfs // avoid race condition - } - val thisDf: DecimalFormat? - // use singleton if on ui thread otherwise allocate new as DecimalFormat is not thread safe - if (Thread.currentThread().id == 1L) { - if (df == null) { - val localDf = DecimalFormat("#", dfs) - localDf.minimumIntegerDigits = 1 - df = localDf // avoid race condition - } - thisDf = df - } else { - thisDf = DecimalFormat("#", dfs) - } - thisDf?.maximumFractionDigits = digits - return thisDf?.format(x) ?: "" - } - - fun formatHHMM(timeAsSeconds: Int): String { - val hour = timeAsSeconds / 60 / 60 - val minutes = (timeAsSeconds - hour * 60 * 60) / 60 - val df = DecimalFormat("00") - return df.format(hour.toLong()) + ":" + df.format(minutes.toLong()) - } + fun computeDiff(date1: Long, date2: Long): Map + fun age(milliseconds: Long, useShortText: Boolean, rh: ResourceHelper): String + fun niceTimeScalar(time: Long, rh: ResourceHelper): String + fun qs(x: Double, numDigits: Int): String + fun formatHHMM(timeAsSeconds: Int): String @RequiresApi(Build.VERSION_CODES.O) - fun timeZoneByOffset(offsetInMilliseconds: Long): TimeZone = - TimeZone.getTimeZone( - if (offsetInMilliseconds == 0L) ZoneId.of("UTC") - else ZoneId.getAvailableZoneIds() - .stream() - .map(ZoneId::of) - .filter { z -> z.rules.getOffset(Instant.now()).totalSeconds == ZoneOffset.ofHours((offsetInMilliseconds / 1000 / 3600).toInt()).totalSeconds } - .collect(Collectors.toList()) - .firstOrNull() ?: ZoneId.of("UTC") - ) - - fun timeStampToUtcDateMillis(timestamp: Long): Long { - val current = Calendar.getInstance().apply { timeInMillis = timestamp } - return Calendar.getInstance().apply { - set(Calendar.YEAR, current[Calendar.YEAR]) - set(Calendar.MONTH, current[Calendar.MONTH]) - set(Calendar.DAY_OF_MONTH, current[Calendar.DAY_OF_MONTH]) - }.timeInMillis - } - - fun mergeUtcDateToTimestamp(timestamp: Long, dateUtcMillis: Long): Long { - val selected = Calendar.getInstance().apply { timeInMillis = dateUtcMillis } - return Calendar.getInstance().apply { - timeInMillis = timestamp - set(Calendar.YEAR, selected[Calendar.YEAR]) - set(Calendar.MONTH, selected[Calendar.MONTH]) - set(Calendar.DAY_OF_MONTH, selected[Calendar.DAY_OF_MONTH]) - }.timeInMillis - } - - fun mergeHourMinuteToTimestamp(timestamp: Long, hour: Int, minute: Int, randomSecond: Boolean = false): Long { - return Calendar.getInstance().apply { - timeInMillis = timestamp - set(Calendar.HOUR_OF_DAY, hour) - set(Calendar.MINUTE, minute) - if (randomSecond) set(Calendar.SECOND, seconds++) - }.timeInMillis - } - - companion object { - - private val timeStrings = LongSparseArray() - private var seconds: Int = (SecureRandom().nextDouble() * 59.0).toInt() - - // singletons to avoid repeated allocation - private var dfs: DecimalFormatSymbols? = null - private var df: DecimalFormat? = null - } + fun timeZoneByOffset(offsetInMilliseconds: Long): TimeZone + fun timeStampToUtcDateMillis(timestamp: Long): Long + fun mergeUtcDateToTimestamp(timestamp: Long, dateUtcMillis: Long): Long + fun mergeHourMinuteToTimestamp(timestamp: Long, hour: Int, minute: Int, randomSecond: Boolean = false): Long } diff --git a/app-wear-shared/shared/src/main/res/drawable/detailed_dial.xml b/app-wear-shared/shared/src/main/res/drawable/detailed_dial.xml deleted file mode 100644 index fa5c92bde2..0000000000 --- a/app-wear-shared/shared/src/main/res/drawable/detailed_dial.xml +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app-wear-shared/shared/src/main/res/drawable/hour_hand.xml b/app-wear-shared/shared/src/main/res/drawable/hour_hand.xml deleted file mode 100644 index c29364421b..0000000000 --- a/app-wear-shared/shared/src/main/res/drawable/hour_hand.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/app-wear-shared/shared/src/main/res/drawable/minute_hand.xml b/app-wear-shared/shared/src/main/res/drawable/minute_hand.xml deleted file mode 100644 index ae37534d34..0000000000 --- a/app-wear-shared/shared/src/main/res/drawable/minute_hand.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/app-wear-shared/shared/src/main/res/drawable/second_hand.xml b/app-wear-shared/shared/src/main/res/drawable/second_hand.xml deleted file mode 100644 index 96464ba7a8..0000000000 --- a/app-wear-shared/shared/src/main/res/drawable/second_hand.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/app-wear-shared/shared/src/main/res/drawable/simplified_dial.xml b/app-wear-shared/shared/src/main/res/drawable/simplified_dial.xml deleted file mode 100644 index 63cca01bfb..0000000000 --- a/app-wear-shared/shared/src/main/res/drawable/simplified_dial.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/java/info/nightscout/androidaps/di/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/di/AppComponent.kt index f96fd72374..26e84713c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/di/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/di/AppComponent.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.danar.di.DanaRModule import info.nightscout.androidaps.insight.di.InsightDatabaseModule import info.nightscout.androidaps.insight.di.InsightModule -import info.nightscout.plugins.sync.di.OpenHumansModule import info.nightscout.androidaps.plugins.pump.common.di.RileyLinkModule import info.nightscout.androidaps.plugins.pump.eopatch.dagger.EopatchModule import info.nightscout.androidaps.plugins.pump.medtronic.di.MedtronicModule @@ -24,6 +23,7 @@ import info.nightscout.insulin.di.InsulinModule import info.nightscout.plugins.aps.di.ApsModule import info.nightscout.plugins.constraints.di.PluginsConstraintsModule import info.nightscout.plugins.di.PluginsModule +import info.nightscout.plugins.sync.di.OpenHumansModule import info.nightscout.plugins.sync.di.SyncModule import info.nightscout.pump.combo.di.ComboModule import info.nightscout.pump.combov2.di.ComboV2Module @@ -31,11 +31,9 @@ import info.nightscout.pump.common.di.PumpCommonModule import info.nightscout.pump.dana.di.DanaHistoryModule import info.nightscout.pump.dana.di.DanaModule import info.nightscout.pump.danars.di.DanaRSModule -import info.nightscout.pump.medtrum.di.MedtrumModule import info.nightscout.pump.diaconn.di.DiaconnG8Module +import info.nightscout.pump.medtrum.di.MedtrumModule import info.nightscout.pump.virtual.di.VirtualPumpModule -import info.nightscout.rx.di.RxModule -import info.nightscout.shared.di.SharedModule import info.nightscout.shared.impl.di.SharedImplModule import info.nightscout.source.di.SourceModule import info.nightscout.ui.di.UiModule @@ -62,8 +60,6 @@ import javax.inject.Singleton InsulinModule::class, OpenHumansModule::class, PluginsModule::class, - RxModule::class, - SharedModule::class, SharedImplModule::class, UiModule::class, ValidatorsModule::class, diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/interfaces/utils/DecimalFormatter.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/utils/DecimalFormatter.kt similarity index 100% rename from app-wear-shared/shared/src/main/java/info/nightscout/interfaces/utils/DecimalFormatter.kt rename to core/interfaces/src/main/java/info/nightscout/interfaces/utils/DecimalFormatter.kt diff --git a/core/ui/src/main/res/values-sw600dp/layout.xml b/core/ui/src/main/res/values-sw600dp/layout.xml new file mode 100644 index 0000000000..7c98f55487 --- /dev/null +++ b/core/ui/src/main/res/values-sw600dp/layout.xml @@ -0,0 +1,3 @@ + + true + \ No newline at end of file diff --git a/core/ui/src/main/res/values/layout.xml b/core/ui/src/main/res/values/layout.xml new file mode 100644 index 0000000000..57f058c48b --- /dev/null +++ b/core/ui/src/main/res/values/layout.xml @@ -0,0 +1,3 @@ + + false + \ No newline at end of file diff --git a/core/validators/build.gradle b/core/validators/build.gradle index b864f8f969..c96c66abe0 100644 --- a/core/validators/build.gradle +++ b/core/validators/build.gradle @@ -17,5 +17,6 @@ android { dependencies { implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') api "com.google.android.material:material:$material_version" } \ No newline at end of file diff --git a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/MaintenanceFragment.kt b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/MaintenanceFragment.kt index a00baaca9b..544e8dd99a 100644 --- a/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/MaintenanceFragment.kt +++ b/plugins/configuration/src/main/java/info/nightscout/configuration/maintenance/MaintenanceFragment.kt @@ -32,7 +32,6 @@ import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.LTag -import info.nightscout.shared.extensions.runOnUiThread import info.nightscout.shared.extensions.toVisibility import info.nightscout.shared.interfaces.ResourceHelper import io.reactivex.rxjava3.core.Completable @@ -106,7 +105,7 @@ class MaintenanceFragment : DaggerFragment() { onError = { aapsLogger.error("Error clearing databases", it) }, onComplete = { rxBus.send(EventPreferenceChange(rh.gs(info.nightscout.core.utils.R.string.key_units))) - runOnUiThread { activity.recreate() } + info.nightscout.shared.extensions.runOnUiThread { activity.recreate() } } ) uel.log(Action.RESET_DATABASES, Sources.Maintenance) diff --git a/plugins/main/build.gradle b/plugins/main/build.gradle index 07d9669272..dfd942ee1a 100644 --- a/plugins/main/build.gradle +++ b/plugins/main/build.gradle @@ -16,6 +16,7 @@ android { dependencies { implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') implementation project(':database:entities') implementation project(':database:impl') implementation project(':core:graphview') diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/overview/OverviewPlugin.kt b/plugins/main/src/main/java/info/nightscout/plugins/general/overview/OverviewPlugin.kt index 6b514eb010..8094509045 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/overview/OverviewPlugin.kt +++ b/plugins/main/src/main/java/info/nightscout/plugins/general/overview/OverviewPlugin.kt @@ -34,6 +34,7 @@ import info.nightscout.rx.events.EventNewHistoryData import info.nightscout.rx.events.EventPumpStatusChanged import info.nightscout.rx.events.EventUpdateOverviewCalcProgress import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.shared.impl.rx.bus.RxBusImpl import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.sharedPreferences.SP import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -72,7 +73,7 @@ class OverviewPlugin @Inject constructor( private var disposable: CompositeDisposable = CompositeDisposable() - override val overviewBus = RxBus(aapsSchedulers, aapsLogger) + override val overviewBus = RxBusImpl(aapsSchedulers, aapsLogger) override fun addNotificationWithDialogResponse(id: Int, text: String, level: Int, @StringRes actionButtonId: Int, title: String, message: String) { rxBus.send( diff --git a/plugins/source/build.gradle b/plugins/source/build.gradle index 9a3c60f00b..92d8f31d79 100644 --- a/plugins/source/build.gradle +++ b/plugins/source/build.gradle @@ -17,6 +17,7 @@ android { dependencies { implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') implementation project(':database:entities') implementation project(':database:impl') implementation project(':core:interfaces') diff --git a/plugins/sync/build.gradle b/plugins/sync/build.gradle index 2551c23cb3..63f799cc9c 100644 --- a/plugins/sync/build.gradle +++ b/plugins/sync/build.gradle @@ -16,6 +16,7 @@ android { dependencies { implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') implementation project(':database:entities') implementation project(':database:impl') implementation project(':core:main') diff --git a/pump/combo/src/main/java/info/nightscout/pump/combo/ComboFragment.kt b/pump/combo/src/main/java/info/nightscout/pump/combo/ComboFragment.kt index 5273087c94..012713ed01 100644 --- a/pump/combo/src/main/java/info/nightscout/pump/combo/ComboFragment.kt +++ b/pump/combo/src/main/java/info/nightscout/pump/combo/ComboFragment.kt @@ -19,7 +19,6 @@ import info.nightscout.pump.combo.ruffyscripter.PumpState import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventQueueChanged -import info.nightscout.shared.extensions.runOnUiThread import info.nightscout.shared.interfaces.ResourceHelper import info.nightscout.shared.utils.DateUtil import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -62,7 +61,7 @@ class ComboFragment : DaggerFragment() { binding.comboRefreshButton.isEnabled = false commandQueue.readStatus(rh.gs(info.nightscout.core.ui.R.string.user_request), object : Callback() { override fun run() { - runOnUiThread { binding.comboRefreshButton.isEnabled = true } + activity?.runOnUiThread { binding.comboRefreshButton.isEnabled = true } } }) } @@ -153,14 +152,17 @@ class ComboFragment : DaggerFragment() { binding.comboInsulinstate.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.defaultTextColor)) binding.comboInsulinstate.setTypeface(null, Typeface.NORMAL) } + PumpState.LOW -> { binding.comboInsulinstate.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.omniYellowColor)) binding.comboInsulinstate.setTypeface(null, Typeface.BOLD) } + PumpState.EMPTY -> { binding.comboInsulinstate.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.warningColor)) binding.comboInsulinstate.setTypeface(null, Typeface.BOLD) } + else -> { binding.comboInsulinstate.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.defaultTextColor)) binding.comboInsulinstate.setTypeface(null, Typeface.NORMAL) @@ -175,10 +177,12 @@ class ComboFragment : DaggerFragment() { binding.comboLastconnection.setText(R.string.combo_pump_connected_now) binding.comboLastconnection.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.defaultTextColor)) } + comboPlugin.pump.lastSuccessfulCmdTime + 30 * 60 * 1000 < System.currentTimeMillis() -> { binding.comboLastconnection.text = rh.gs(R.string.combo_no_pump_connection, min) binding.comboLastconnection.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.warningColor)) } + else -> { binding.comboLastconnection.text = minAgo binding.comboLastconnection.setTextColor(rh.gac(context, info.nightscout.core.ui.R.attr.defaultTextColor)) diff --git a/pump/diaconn/build.gradle b/pump/diaconn/build.gradle index 81af70ba94..f6e0c7934b 100644 --- a/pump/diaconn/build.gradle +++ b/pump/diaconn/build.gradle @@ -26,6 +26,7 @@ android { dependencies { implementation project(':app-wear-shared:shared') + implementation project(':app-wear-shared:shared-impl') implementation project(':core:libraries') implementation project(':core:interfaces') implementation project(':core:utils') diff --git a/pump/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmRegistry.kt b/pump/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmRegistry.kt index ae020d1ccf..9897559ff8 100644 --- a/pump/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmRegistry.kt +++ b/pump/eopatch/src/main/java/info/nightscout/androidaps/plugins/pump/eopatch/alarm/AlarmRegistry.kt @@ -27,6 +27,7 @@ import javax.inject.Inject import javax.inject.Singleton interface IAlarmRegistry { + fun add(alarmCode: AlarmCode, triggerAfter: Long, isFirst: Boolean = false): Maybe fun add(patchAeCodes: Set) fun remove(alarmCode: AlarmCode): Maybe @@ -34,11 +35,13 @@ interface IAlarmRegistry { @Singleton class AlarmRegistry @Inject constructor() : IAlarmRegistry { + @Inject lateinit var mContext: Context @Inject lateinit var pm: IPreferenceManager @Inject lateinit var rxBus: RxBus @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsSchedulers: AapsSchedulers + @Inject lateinit var dateUtil: DateUtil private lateinit var mOsAlarmManager: AlarmManager private var mDisposable: Disposable? = null @@ -49,19 +52,21 @@ class AlarmRegistry @Inject constructor() : IAlarmRegistry { mDisposable = pm.observePatchLifeCycle() .observeOn(aapsSchedulers.main) .subscribe { - when(it){ + when (it) { PatchLifecycle.REMOVE_NEEDLE_CAP -> { val triggerAfter = pm.getPatchConfig().patchWakeupTimestamp + TimeUnit.HOURS.toMillis(1) - System.currentTimeMillis() compositeDisposable.add(add(AlarmCode.A020, triggerAfter).subscribe()) } - PatchLifecycle.ACTIVATED -> { + + PatchLifecycle.ACTIVATED -> { } - PatchLifecycle.SHUTDOWN -> { + + PatchLifecycle.SHUTDOWN -> { val sources = ArrayList>() sources.add(Maybe.just(true)) - pm.getAlarms().occurred.let{ occurredAlarms -> - if(occurredAlarms.isNotEmpty()){ + pm.getAlarms().occurred.let { occurredAlarms -> + if (occurredAlarms.isNotEmpty()) { occurredAlarms.keys.forEach { alarmCode -> sources.add( Maybe.just(alarmCode) @@ -71,30 +76,30 @@ class AlarmRegistry @Inject constructor() : IAlarmRegistry { } } } - pm.getAlarms().registered.let{ registeredAlarms -> - if(registeredAlarms.isNotEmpty()){ + pm.getAlarms().registered.let { registeredAlarms -> + if (registeredAlarms.isNotEmpty()) { registeredAlarms.keys.forEach { alarmCode -> sources.add(remove(alarmCode)) } } } compositeDisposable.add(Maybe.concat(sources) - .subscribe { - pm.getAlarms().clear() - pm.flushAlarms() - } + .subscribe { + pm.getAlarms().clear() + pm.flushAlarms() + } ) } - else -> Unit + else -> Unit } } } override fun add(alarmCode: AlarmCode, triggerAfter: Long, isFirst: Boolean): Maybe { - if(pm.getAlarms().occurred.containsKey(alarmCode)){ + if (pm.getAlarms().occurred.containsKey(alarmCode)) { return Maybe.just(alarmCode) - }else { + } else { val triggerTimeMilli = System.currentTimeMillis() + triggerAfter pm.getAlarms().register(alarmCode, triggerAfter) pm.flushAlarms() @@ -109,11 +114,11 @@ class AlarmRegistry @Inject constructor() : IAlarmRegistry { override fun add(patchAeCodes: Set) { compositeDisposable.add( Observable.fromIterable(patchAeCodes) - .filter{patchAeCodeItem -> AlarmCode.findByPatchAeCode(patchAeCodeItem.aeValue) != null} - .observeOn(aapsSchedulers.main) - .filter { aeCodes -> AlarmCode.findByPatchAeCode(aeCodes.aeValue) != null } - .flatMapMaybe{aeCodeResponse -> add(AlarmCode.findByPatchAeCode(aeCodeResponse.aeValue)!!, 0L, true)} - .subscribe() + .filter { patchAeCodeItem -> AlarmCode.findByPatchAeCode(patchAeCodeItem.aeValue) != null } + .observeOn(aapsSchedulers.main) + .filter { aeCodes -> AlarmCode.findByPatchAeCode(aeCodes.aeValue) != null } + .flatMapMaybe { aeCodeResponse -> add(AlarmCode.findByPatchAeCode(aeCodeResponse.aeValue)!!, 0L, true) } + .subscribe() ) } @@ -121,21 +126,21 @@ class AlarmRegistry @Inject constructor() : IAlarmRegistry { return Maybe.fromCallable { cancelOsAlarmInternal(alarmCode) val pendingIntent = createPendingIntent(alarmCode, 0) - aapsLogger.debug("[${alarmCode}] OS Alarm added. ${DateUtil(mContext).toISOString(triggerTime)}") + aapsLogger.debug("[${alarmCode}] OS Alarm added. ${dateUtil.toISOString(triggerTime)}") mOsAlarmManager.setAlarmClock(AlarmClockInfo(triggerTime, pendingIntent), pendingIntent) alarmCode } } override fun remove(alarmCode: AlarmCode): Maybe { - return if(pm.getAlarms().registered.containsKey(alarmCode)) { + return if (pm.getAlarms().registered.containsKey(alarmCode)) { cancelOsAlarms(alarmCode) .doOnSuccess { pm.getAlarms().unregister(alarmCode) pm.flushAlarms() } .map { alarmCode } - }else{ + } else { Maybe.just(alarmCode) } } diff --git a/pump/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt b/pump/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt index 3ce25b2115..1dfda4ffc1 100644 --- a/pump/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt +++ b/pump/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt @@ -8,7 +8,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.Omnipod import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.AAPSLoggerTest import org.junit.Before import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test diff --git a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt index 735938a9e8..d8ef9a4200 100644 --- a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt +++ b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecry import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket import info.nightscout.core.utils.toHex -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.AAPSLoggerTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.spongycastle.util.encoders.Hex diff --git a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt index 43a71e621c..0b95e71c27 100644 --- a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt +++ b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt @@ -4,7 +4,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.Rand import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.X25519KeyGenerator import info.nightscout.core.utils.toHex import info.nightscout.interfaces.Config -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.AAPSLoggerTest import info.nightscout.sharedtests.TestBase import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test diff --git a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt index d8871467bf..c399939cd3 100644 --- a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt +++ b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessageTest.kt @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session import info.nightscout.core.utils.toHex -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.AAPSLoggerTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.spongycastle.util.encoders.Hex diff --git a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt index ad82492289..2c7914eb24 100644 --- a/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt +++ b/pump/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/MilenageTest.kt @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session import info.nightscout.core.utils.toHex import info.nightscout.interfaces.Config -import info.nightscout.rx.logging.AAPSLoggerTest +import info.nightscout.sharedtests.AAPSLoggerTest import info.nightscout.sharedtests.TestBase import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test diff --git a/pump/omnipod-eros/build.gradle b/pump/omnipod-eros/build.gradle index c3ff28071f..7974db371f 100644 --- a/pump/omnipod-eros/build.gradle +++ b/pump/omnipod-eros/build.gradle @@ -37,6 +37,8 @@ dependencies { implementation project(':pump:rileylink') implementation project(':pump:omnipod-common') + testImplementation project(':app-wear-shared:shared-impl') + api "androidx.room:room-ktx:$room_version" api "androidx.room:room-runtime:$room_version" api "androidx.room:room-rxjava3:$room_version" diff --git a/pump/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsErosPodStateManagerTest.kt b/pump/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsErosPodStateManagerTest.kt index 782ecc7604..9d63fafec5 100644 --- a/pump/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsErosPodStateManagerTest.kt +++ b/pump/omnipod-eros/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsErosPodStateManagerTest.kt @@ -2,10 +2,10 @@ package info.nightscout.androidaps.plugins.pump.omnipod.eros.manager import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.FirmwareVersion import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.PodProgressStatus -import info.nightscout.rx.TestAapsSchedulers -import info.nightscout.rx.bus.RxBus +import info.nightscout.shared.impl.rx.bus.RxBusImpl import info.nightscout.shared.sharedPreferences.SP import info.nightscout.sharedtests.TestBase +import info.nightscout.sharedtests.rx.TestAapsSchedulers import org.joda.time.DateTime import org.joda.time.DateTimeUtils import org.joda.time.DateTimeZone @@ -19,7 +19,7 @@ class AapsErosPodStateManagerTest : TestBase() { @Mock lateinit var sp: SP - private val rxBus = RxBus(TestAapsSchedulers(), aapsLogger) + private val rxBus = RxBusImpl(TestAapsSchedulers(), aapsLogger) @Test fun times() { val timeZone = DateTimeZone.UTC diff --git a/wear/src/main/java/info/nightscout/androidaps/di/WearModule.kt b/wear/src/main/java/info/nightscout/androidaps/di/WearModule.kt index 014b247cc8..a4b8295bbd 100644 --- a/wear/src/main/java/info/nightscout/androidaps/di/WearModule.kt +++ b/wear/src/main/java/info/nightscout/androidaps/di/WearModule.kt @@ -6,8 +6,6 @@ import dagger.Module import dagger.Provides import dagger.android.HasAndroidInjector import info.nightscout.androidaps.WearApp -import info.nightscout.rx.di.RxModule -import info.nightscout.shared.di.SharedModule import info.nightscout.shared.impl.di.SharedImplModule import kotlinx.datetime.Clock @@ -16,8 +14,6 @@ import kotlinx.datetime.Clock includes = [ WearModule.AppBindings::class, WearActivitiesModule::class, - RxModule::class, - SharedModule::class, SharedImplModule::class ] ) diff --git a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt index cfb1765d17..f3f5d7ddba 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/CustomWatchface.kt @@ -35,15 +35,15 @@ import info.nightscout.androidaps.watchfaces.utils.BaseWatchFace import info.nightscout.rx.logging.LTag import info.nightscout.rx.weardata.CUSTOM_VERSION import info.nightscout.rx.weardata.CwfData -import info.nightscout.rx.weardata.ResFileMap -import info.nightscout.rx.weardata.CwfResDataMap import info.nightscout.rx.weardata.CwfMetadataKey import info.nightscout.rx.weardata.CwfMetadataMap -import info.nightscout.rx.weardata.ResData -import info.nightscout.rx.weardata.ResFormat +import info.nightscout.rx.weardata.CwfResDataMap import info.nightscout.rx.weardata.EventData import info.nightscout.rx.weardata.JsonKeyValues import info.nightscout.rx.weardata.JsonKeys.* +import info.nightscout.rx.weardata.ResData +import info.nightscout.rx.weardata.ResFileMap +import info.nightscout.rx.weardata.ResFormat import info.nightscout.rx.weardata.ViewKeys import info.nightscout.rx.weardata.ZipWatchfaceFormat import info.nightscout.shared.extensions.toVisibility @@ -208,7 +208,7 @@ class CustomWatchface : BaseWatchFace() { it.clearColorFilter() view.setImageDrawable(it) } ?: apply { - view.setImageDrawable(id.defaultDrawable?.let {resources.getDrawable(it)}) + view.setImageDrawable(id.defaultDrawable?.let { resources.getDrawable(it) }) if (viewJson.has(COLOR.key)) view.setColorFilter(getColor(viewJson.optString(COLOR.key))) else @@ -217,7 +217,7 @@ class CustomWatchface : BaseWatchFace() { } } - } ?:apply { + } ?: apply { view.visibility = View.GONE if (view is TextView) { view.text = "" @@ -301,7 +301,7 @@ class CustomWatchface : BaseWatchFace() { } val metadataMap = ZipWatchfaceFormat.loadMetadata(json) val drawableDataMap: CwfResDataMap = mutableMapOf() - getResourceByteArray(info.nightscout.shared.R.drawable.watchface_custom)?.let { + getResourceByteArray(info.nightscout.shared.impl.R.drawable.watchface_custom)?.let { drawableDataMap[ResFileMap.CUSTOM_WATCHFACE.fileName] = ResData(it, ResFormat.PNG) } return EventData.ActionSetCustomWatchface(CwfData(json.toString(4), metadataMap, drawableDataMap)) @@ -394,7 +394,7 @@ class CustomWatchface : BaseWatchFace() { @StringRes val pref: Int?, @IdRes val defaultDrawable: Int?, val customDrawable: ResFileMap?, - val customHigh:ResFileMap?, + val customHigh: ResFileMap?, val customLow: ResFileMap? ) { @@ -402,7 +402,7 @@ class CustomWatchface : BaseWatchFace() { ViewKeys.BACKGROUND.key, R.id.background, null, - info.nightscout.shared.R.drawable.background, + info.nightscout.shared.impl.R.drawable.background, ResFileMap.BACKGROUND, ResFileMap.BACKGROUND_HIGH, ResFileMap.BACKGROUND_LOW @@ -448,7 +448,7 @@ class CustomWatchface : BaseWatchFace() { ViewKeys.COVER_PLATE.key, R.id.cover_plate, null, - info.nightscout.shared.R.drawable.simplified_dial, + info.nightscout.shared.impl.R.drawable.simplified_dial, ResFileMap.COVER_PLATE, ResFileMap.COVER_PLATE_HIGH, ResFileMap.COVER_PLATE_LOW @@ -457,7 +457,7 @@ class CustomWatchface : BaseWatchFace() { ViewKeys.HOUR_HAND.key, R.id.hour_hand, null, - info.nightscout.shared.R.drawable.hour_hand, + info.nightscout.shared.impl.R.drawable.hour_hand, ResFileMap.HOUR_HAND, ResFileMap.HOUR_HAND_HIGH, ResFileMap.HOUR_HAND_LOW @@ -466,7 +466,7 @@ class CustomWatchface : BaseWatchFace() { ViewKeys.MINUTE_HAND.key, R.id.minute_hand, null, - info.nightscout.shared.R.drawable.minute_hand, + info.nightscout.shared.impl.R.drawable.minute_hand, ResFileMap.MINUTE_HAND, ResFileMap.MINUTE_HAND_HIGH, ResFileMap.MINUTE_HAND_LOW @@ -475,7 +475,7 @@ class CustomWatchface : BaseWatchFace() { ViewKeys.SECOND_HAND.key, R.id.second_hand, R.string.key_show_seconds, - info.nightscout.shared.R.drawable.second_hand, + info.nightscout.shared.impl.R.drawable.second_hand, ResFileMap.SECOND_HAND, ResFileMap.SECOND_HAND_HIGH, ResFileMap.SECOND_HAND_LOW @@ -491,16 +491,25 @@ class CustomWatchface : BaseWatchFace() { fun drawable(resources: Resources, drawableDataMap: CwfResDataMap, sgvLevel: Long): Drawable? = customDrawable?.let { cd -> when (sgvLevel) { - 1L -> { customHigh?.let {drawableDataMap[customHigh.fileName]}?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) } - 0L -> { drawableDataMap[cd.fileName]?.toDrawable(resources) } - -1L -> { customLow?.let {drawableDataMap[customLow.fileName]}?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) } + 1L -> { + customHigh?.let { drawableDataMap[customHigh.fileName] }?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) + } + + 0L -> { + drawableDataMap[cd.fileName]?.toDrawable(resources) + } + + -1L -> { + customLow?.let { drawableDataMap[customLow.fileName] }?.toDrawable(resources) ?: drawableDataMap[cd.fileName]?.toDrawable(resources) + } + else -> drawableDataMap[cd.fileName]?.toDrawable(resources) } } } } -private enum class TrendArrowMap(val symbol: String, @DrawableRes val icon: Int,val customDrawable: ResFileMap?) { +private enum class TrendArrowMap(val symbol: String, @DrawableRes val icon: Int, val customDrawable: ResFileMap?) { NONE("??", R.drawable.ic_invalid, ResFileMap.ARROW_NONE), TRIPLE_UP("X", R.drawable.ic_doubleup, ResFileMap.ARROW_DOUBLE_UP), DOUBLE_UP("\u21c8", R.drawable.ic_doubleup, ResFileMap.ARROW_DOUBLE_UP), @@ -515,8 +524,8 @@ private enum class TrendArrowMap(val symbol: String, @DrawableRes val icon: Int, companion object { fun drawable(direction: String?, resources: Resources, drawableDataMap: CwfResDataMap): Drawable { - val arrow = values().firstOrNull { it.symbol == direction } ?:NONE - return arrow.customDrawable?. let {drawableDataMap[arrow.customDrawable.fileName]}?.toDrawable(resources) ?:resources.getDrawable(arrow.icon) + val arrow = values().firstOrNull { it.symbol == direction } ?: NONE + return arrow.customDrawable?.let { drawableDataMap[arrow.customDrawable.fileName] }?.toDrawable(resources) ?: resources.getDrawable(arrow.icon) } } @@ -558,7 +567,7 @@ private enum class FontMap(val key: String, var font: Typeface, @FontRes val fon resDataMap.filter { (_, resData) -> resData.format == ResFormat.TTF || resData.format == ResFormat.OTF }.forEach { (key, resData) -> - customFonts[key.lowercase()] = resData.toTypeface() ?:Typeface.DEFAULT + customFonts[key.lowercase()] = resData.toTypeface() ?: Typeface.DEFAULT } } diff --git a/wear/src/main/java/info/nightscout/androidaps/watchfaces/DigitalStyleWatchface.kt b/wear/src/main/java/info/nightscout/androidaps/watchfaces/DigitalStyleWatchface.kt index b9db42cdd9..8cac6aecc7 100644 --- a/wear/src/main/java/info/nightscout/androidaps/watchfaces/DigitalStyleWatchface.kt +++ b/wear/src/main/java/info/nightscout/androidaps/watchfaces/DigitalStyleWatchface.kt @@ -7,16 +7,13 @@ import android.support.wearable.watchface.WatchFaceStyle import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout -import android.widget.TextView import androidx.core.content.ContextCompat import androidx.viewbinding.ViewBinding import info.nightscout.androidaps.R import info.nightscout.androidaps.databinding.ActivityDigitalstyleBinding -import info.nightscout.shared.extensions.toVisibility import info.nightscout.androidaps.watchfaces.utils.BaseWatchFace import info.nightscout.rx.logging.LTag - class DigitalStyleWatchface : BaseWatchFace() { private lateinit var binding: ActivityDigitalstyleBinding diff --git a/wear/src/test/java/info/nightscout/androidaps/heartrate/HeartRateListenerTest.kt b/wear/src/test/java/info/nightscout/androidaps/heartrate/HeartRateListenerTest.kt index 7b542b1afc..10d734a525 100644 --- a/wear/src/test/java/info/nightscout/androidaps/heartrate/HeartRateListenerTest.kt +++ b/wear/src/test/java/info/nightscout/androidaps/heartrate/HeartRateListenerTest.kt @@ -4,8 +4,8 @@ import android.content.Context import android.hardware.Sensor import android.hardware.SensorManager import info.nightscout.rx.AapsSchedulers -import info.nightscout.rx.logging.AAPSLoggerTest import info.nightscout.rx.weardata.EventData.ActionHeartRate +import info.nightscout.sharedtests.AAPSLoggerTest import io.reactivex.rxjava3.core.Scheduler import io.reactivex.rxjava3.disposables.Disposable import org.junit.jupiter.api.AfterEach @@ -22,8 +22,9 @@ import org.mockito.Mockito.`when` import java.util.concurrent.TimeUnit internal class HeartRateListenerTest { + private val aapsLogger = AAPSLoggerTest() - private val aapsSchedulers = object: AapsSchedulers { + private val aapsSchedulers = object : AapsSchedulers { override val main: Scheduler = mock(Scheduler::class.java) override val io: Scheduler = mock(Scheduler::class.java) override val cpu: Scheduler = mock(Scheduler::class.java) @@ -35,11 +36,15 @@ internal class HeartRateListenerTest { private fun create(timestampMillis: Long): HeartRateListener { val ctx = mock(Context::class.java) - `when`(aapsSchedulers.io.schedulePeriodicallyDirect( - any(), eq(60_000L), eq(60_000L), eq(TimeUnit.MILLISECONDS))).thenReturn(schedule) + `when`( + aapsSchedulers.io.schedulePeriodicallyDirect( + any(), eq(60_000L), eq(60_000L), eq(TimeUnit.MILLISECONDS) + ) + ).thenReturn(schedule) val listener = HeartRateListener(ctx, aapsLogger, aapsSchedulers, timestampMillis) verify(aapsSchedulers.io).schedulePeriodicallyDirect( - any(), eq(60_000L), eq(60_000L), eq(TimeUnit.MILLISECONDS)) + any(), eq(60_000L), eq(60_000L), eq(TimeUnit.MILLISECONDS) + ) listener.sendHeartRate = { hr -> heartRates.add(hr) } return listener } @@ -49,10 +54,11 @@ internal class HeartRateListenerTest { timestamp: Long, heartRate: Int, sensorType: Int? = Sensor.TYPE_HEART_RATE, - accuracy: Int = SensorManager.SENSOR_STATUS_ACCURACY_HIGH) { + accuracy: Int = SensorManager.SENSOR_STATUS_ACCURACY_HIGH + ) { listener.onSensorChanged(sensorType, accuracy, timestamp, floatArrayOf(heartRate.toFloat())) } - + @BeforeEach fun before() { heartRates.clear() @@ -66,7 +72,7 @@ internal class HeartRateListenerTest { Mockito.verifyNoInteractions(aapsSchedulers.newThread) verify(schedule).dispose() } - + @Test fun onSensorChanged() { val start = System.currentTimeMillis() @@ -95,7 +101,7 @@ internal class HeartRateListenerTest { sendSensorEvent(listener, start, 80) assertEquals(0, heartRates.size) assertEquals(80, listener.currentHeartRateBpm) - sendSensorEvent(listener, start + d1,100) + sendSensorEvent(listener, start + d1, 100) assertEquals(0, heartRates.size) assertEquals(100, listener.currentHeartRateBpm) @@ -117,7 +123,7 @@ internal class HeartRateListenerTest { listener.send(start + d1) assertEquals(1, heartRates.size) - sendSensorEvent(listener, start + d1,100) + sendSensorEvent(listener, start + d1, 100) assertEquals(1, heartRates.size) listener.send(start + d2) assertEquals(2, heartRates.size)