Merge branch 'dev' into bug1724_tbr_iob

This commit is contained in:
Milos Kozak 2022-05-31 14:43:36 +02:00 committed by GitHub
commit c8ab2ecd03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 884 additions and 504 deletions

View file

@ -188,11 +188,33 @@ class MainApp : DaggerApplication() {
} }
} }
@Suppress("SpellCheckingInspection")
private fun doMigrations() { private fun doMigrations() {
// set values for different builds // set values for different builds
if (!sp.contains(R.string.key_ns_alarms)) sp.putBoolean(R.string.key_ns_alarms, config.NSCLIENT) if (!sp.contains(R.string.key_ns_alarms)) sp.putBoolean(R.string.key_ns_alarms, config.NSCLIENT)
if (!sp.contains(R.string.key_ns_announcements)) sp.putBoolean(R.string.key_ns_announcements, config.NSCLIENT) if (!sp.contains(R.string.key_ns_announcements)) sp.putBoolean(R.string.key_ns_announcements, config.NSCLIENT)
if (!sp.contains(R.string.key_language)) sp.putString(R.string.key_language, "default") if (!sp.contains(R.string.key_language)) sp.putString(R.string.key_language, "default")
// 3.1.0
if (sp.contains("ns_wifionly")) {
if (sp.getBoolean("ns_wifionly", false)) {
sp.putBoolean(R.string.key_ns_cellular, false)
sp.putBoolean(R.string.key_ns_wifi, true)
} else {
sp.putBoolean(R.string.key_ns_cellular, true)
sp.putBoolean(R.string.key_ns_wifi, false)
}
sp.remove("ns_wifionly")
}
if (sp.contains("ns_charginonly")) {
if (sp.getBoolean("ns_charginonly", false)) {
sp.putBoolean(R.string.key_ns_battery, false)
sp.putBoolean(R.string.key_ns_charging, true)
} else {
sp.putBoolean(R.string.key_ns_battery, true)
sp.putBoolean(R.string.key_ns_charging, true)
}
sp.remove("ns_charginonly")
}
} }
override fun applicationInjector(): AndroidInjector<out DaggerApplication> { override fun applicationInjector(): AndroidInjector<out DaggerApplication> {

View file

@ -21,8 +21,7 @@ import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm
@ -35,11 +34,12 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper.fromHtml import info.nightscout.androidaps.utils.HtmlHelper.fromHtml
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.* import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -80,62 +80,49 @@ class NSClientPlugin @Inject constructor(
var nsClientService: NSClientService? = null var nsClientService: NSClientService? = null
val isAllowed: Boolean val isAllowed: Boolean
get() = nsClientReceiverDelegate.allowed get() = nsClientReceiverDelegate.allowed
val blockingReason: String
get() = nsClientReceiverDelegate.blockingReason
override fun onStart() { override fun onStart() {
paused = sp.getBoolean(R.string.key_nsclientinternal_paused, false) paused = sp.getBoolean(R.string.key_nsclientinternal_paused, false)
autoscroll = sp.getBoolean(R.string.key_nsclientinternal_autoscroll, true) autoscroll = sp.getBoolean(R.string.key_nsclientinternal_autoscroll, true)
val intent = Intent(context, NSClientService::class.java) context.bindService(Intent(context, NSClientService::class.java), mConnection, Context.BIND_AUTO_CREATE)
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
super.onStart() super.onStart()
nsClientReceiverDelegate.grabReceiversState() nsClientReceiverDelegate.grabReceiversState()
disposable.add( disposable += rxBus
rxBus .toObservable(EventNSClientStatus::class.java)
.toObservable(EventNSClientStatus::class.java) .observeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.io) .subscribe({ event: EventNSClientStatus ->
.subscribe({ event: EventNSClientStatus -> status = event.getStatus(rh)
status = event.getStatus(rh) rxBus.send(EventNSClientUpdateGUI())
rxBus.send(EventNSClientUpdateGUI()) }, fabricPrivacy::logException)
}, fabricPrivacy::logException) disposable += rxBus
) .toObservable(EventNetworkChange::class.java)
disposable.add( .observeOn(aapsSchedulers.io)
rxBus .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
.toObservable(EventNetworkChange::class.java) disposable += rxBus
.observeOn(aapsSchedulers.io) .toObservable(EventPreferenceChange::class.java)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) .observeOn(aapsSchedulers.io)
) .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
disposable.add( disposable += rxBus
rxBus .toObservable(EventAppExit::class.java)
.toObservable(EventPreferenceChange::class.java) .observeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.io) .subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) disposable += rxBus
) .toObservable(EventNSClientNewLog::class.java)
disposable.add( .observeOn(aapsSchedulers.io)
rxBus .subscribe({ event: EventNSClientNewLog ->
.toObservable(EventAppExit::class.java) addToLog(event)
.observeOn(aapsSchedulers.io) aapsLogger.debug(LTag.NSCLIENT, event.action + " " + event.logText)
.subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException) }, fabricPrivacy::logException)
) disposable += rxBus
disposable.add( .toObservable(EventChargingState::class.java)
rxBus .observeOn(aapsSchedulers.io)
.toObservable(EventNSClientNewLog::class.java) .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
.observeOn(aapsSchedulers.io) disposable += rxBus
.subscribe({ event: EventNSClientNewLog -> .toObservable(EventNSClientResend::class.java)
addToLog(event) .observeOn(aapsSchedulers.io)
aapsLogger.debug(LTag.NSCLIENT, event.action + " " + event.logText) .subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventChargingState::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
)
} }
override fun onStop() { override fun onStop() {

View file

@ -22,19 +22,26 @@ class NsClientReceiverDelegate @Inject constructor(
private var allowedChargingState = true private var allowedChargingState = true
private var allowedNetworkState = true private var allowedNetworkState = true
var allowed = true var allowed = true
var blockingReason = ""
fun grabReceiversState() { fun grabReceiversState() {
receiverStatusStore.updateNetworkStatus() receiverStatusStore.updateNetworkStatus()
} }
fun onStatusEvent(ev: EventPreferenceChange) { fun onStatusEvent(ev: EventPreferenceChange) {
if (ev.isChanged(rh, R.string.key_ns_wifionly) || when {
ev.isChanged(rh, R.string.key_ns_wifi_ssids) || ev.isChanged(rh, R.string.key_ns_wifi) ||
ev.isChanged(rh, R.string.key_ns_allowroaming)) { ev.isChanged(rh, R.string.key_ns_cellular) ||
receiverStatusStore.updateNetworkStatus() ev.isChanged(rh, R.string.key_ns_wifi_ssids) ||
onStatusEvent(receiverStatusStore.lastNetworkEvent) ev.isChanged(rh, R.string.key_ns_allow_roaming) -> {
} else if (ev.isChanged(rh, R.string.key_ns_chargingonly)) { receiverStatusStore.updateNetworkStatus()
receiverStatusStore.broadcastChargingState() receiverStatusStore.lastNetworkEvent?.let { onStatusEvent(it) }
}
ev.isChanged(rh, R.string.key_ns_charging) ||
ev.isChanged(rh, R.string.key_ns_battery) -> {
receiverStatusStore.broadcastChargingState()
}
} }
} }
@ -42,14 +49,16 @@ class NsClientReceiverDelegate @Inject constructor(
val newChargingState = calculateStatus(ev) val newChargingState = calculateStatus(ev)
if (newChargingState != allowedChargingState) { if (newChargingState != allowedChargingState) {
allowedChargingState = newChargingState allowedChargingState = newChargingState
blockingReason = rh.gs(R.string.blocked_by_charging)
processStateChange() processStateChange()
} }
} }
fun onStatusEvent(ev: EventNetworkChange?) { fun onStatusEvent(ev: EventNetworkChange) {
val newNetworkState = calculateStatus(ev) val newNetworkState = calculateStatus(ev)
if (newNetworkState != allowedNetworkState) { if (newNetworkState != allowedNetworkState) {
allowedNetworkState = newNetworkState allowedNetworkState = newNetworkState
blockingReason = rh.gs(R.string.blocked_by_connectivity)
processStateChange() processStateChange()
} }
} }
@ -62,30 +71,13 @@ class NsClientReceiverDelegate @Inject constructor(
} }
} }
fun calculateStatus(ev: EventChargingState): Boolean { fun calculateStatus(ev: EventChargingState): Boolean =
val chargingOnly = sp.getBoolean(R.string.key_ns_chargingonly, false) !ev.isCharging && sp.getBoolean(R.string.key_ns_battery, true) ||
var newAllowedState = true ev.isCharging && sp.getBoolean(R.string.key_ns_charging, true)
if (!ev.isCharging && chargingOnly) {
newAllowedState = false
}
return newAllowedState
}
fun calculateStatus(ev: EventNetworkChange?): Boolean { fun calculateStatus(ev: EventNetworkChange): Boolean =
val wifiOnly = sp.getBoolean(R.string.key_ns_wifionly, false) ev.mobileConnected && sp.getBoolean(R.string.key_ns_cellular, true) && !ev.roaming ||
val allowedSsidString = sp.getString(R.string.key_ns_wifi_ssids, "") ev.mobileConnected && sp.getBoolean(R.string.key_ns_cellular, true) && ev.roaming && sp.getBoolean(R.string.key_ns_allow_roaming, true) ||
val allowedSSIDs: List<String> = if (allowedSsidString.isEmpty()) List(0) { "" } else allowedSsidString.split(";") ev.wifiConnected && sp.getBoolean(R.string.key_ns_wifi, true) && sp.getString(R.string.key_ns_wifi_ssids, "").isEmpty() ||
val allowRoaming = sp.getBoolean(R.string.key_ns_allowroaming, true) ev.wifiConnected && sp.getBoolean(R.string.key_ns_wifi, true) && sp.getString(R.string.key_ns_wifi_ssids, "").split(";").contains(ev.ssid)
var newAllowedState = true
if (ev?.wifiConnected == true) {
if (allowedSSIDs.isNotEmpty() && !allowedSSIDs.contains(ev.ssid)) {
newAllowedState = false
}
} else {
if (!allowRoaming && ev?.roaming == true || wifiOnly) {
newAllowedState = false
}
}
return newAllowedState
}
} }

View file

@ -16,9 +16,14 @@ import info.nightscout.androidaps.events.EventConfigBuilderChange
import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventPreferenceChange
import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.Config
import info.nightscout.androidaps.interfaces.DataSyncSelector import info.nightscout.androidaps.interfaces.DataSyncSelector
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.food.FoodPlugin.FoodWorker import info.nightscout.androidaps.plugins.general.food.FoodPlugin.FoodWorker
import info.nightscout.androidaps.plugins.general.nsclient.* import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck
import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck
@ -44,12 +49,12 @@ import info.nightscout.androidaps.utils.JsonHelper.safeGetStringAllowNull
import info.nightscout.androidaps.utils.T.Companion.mins import info.nightscout.androidaps.utils.T.Companion.mins
import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.XDripBroadcast
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.socket.client.IO import io.socket.client.IO
import io.socket.client.Socket import io.socket.client.Socket
import io.socket.emitter.Emitter import io.socket.emitter.Emitter
@ -114,70 +119,56 @@ class NSClientService : DaggerService() {
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NSClientService") wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NSClientService")
wakeLock?.acquire() wakeLock?.acquire()
initialize() initialize()
disposable.add( disposable += rxBus
rxBus .toObservable(EventConfigBuilderChange::class.java)
.toObservable(EventConfigBuilderChange::class.java) .observeOn(aapsSchedulers.io)
.observeOn(aapsSchedulers.io) .subscribe({
.subscribe({ if (nsEnabled != nsClientPlugin.isEnabled()) {
if (nsEnabled != nsClientPlugin.isEnabled()) {
latestDateInReceivedData = 0
destroy()
initialize()
}
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ event: EventPreferenceChange ->
if (event.isChanged(rh, R.string.key_nsclientinternal_url) ||
event.isChanged(rh, R.string.key_nsclientinternal_api_secret) ||
event.isChanged(rh, R.string.key_nsclientinternal_paused)
) {
latestDateInReceivedData = 0
destroy()
initialize()
}
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received")
destroy()
stopSelf()
}, fabricPrivacy::logException)
)
disposable.add(
rxBus
.toObservable(EventNSClientRestart::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
latestDateInReceivedData = 0 latestDateInReceivedData = 0
restart() destroy()
}, fabricPrivacy::logException) initialize()
) }
disposable.add( }, fabricPrivacy::logException)
rxBus disposable += rxBus
.toObservable(NSAuthAck::class.java) .toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAuthAck(ack) }, fabricPrivacy::logException) .subscribe({ event: EventPreferenceChange ->
) if (event.isChanged(rh, R.string.key_nsclientinternal_url) ||
disposable.add( event.isChanged(rh, R.string.key_nsclientinternal_api_secret) ||
rxBus event.isChanged(rh, R.string.key_nsclientinternal_paused)
.toObservable(NSUpdateAck::class.java) ) {
.observeOn(aapsSchedulers.io) latestDateInReceivedData = 0
.subscribe({ ack -> processUpdateAck(ack) }, fabricPrivacy::logException) destroy()
) initialize()
disposable.add( }
rxBus }, fabricPrivacy::logException)
.toObservable(NSAddAck::class.java) disposable += rxBus
.observeOn(aapsSchedulers.io) .toObservable(EventAppExit::class.java)
.subscribe({ ack -> processAddAck(ack) }, fabricPrivacy::logException) .observeOn(aapsSchedulers.io)
) .subscribe({
aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received")
destroy()
stopSelf()
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNSClientRestart::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({
latestDateInReceivedData = 0
restart()
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSAuthAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAuthAck(ack) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSUpdateAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processUpdateAck(ack) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(NSAddAck::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ ack -> processAddAck(ack) }, fabricPrivacy::logException)
} }
override fun onDestroy() { override fun onDestroy() {
@ -234,13 +225,9 @@ class NSClientService : DaggerService() {
get() = this@NSClientService get() = this@NSClientService
} }
override fun onBind(intent: Intent): IBinder { override fun onBind(intent: Intent): IBinder = binder
return binder
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int = START_STICKY
return START_STICKY
}
fun initialize() { fun initialize() {
dataCounter = 0 dataCounter = 0
@ -249,8 +236,8 @@ class NSClientService : DaggerService() {
if (nsAPISecret != "") nsApiHashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString() if (nsAPISecret != "") nsApiHashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString()
rxBus.send(EventNSClientStatus("Initializing")) rxBus.send(EventNSClientStatus("Initializing"))
if (!nsClientPlugin.isAllowed) { if (!nsClientPlugin.isAllowed) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "not allowed")) rxBus.send(EventNSClientNewLog("NSCLIENT", nsClientPlugin.blockingReason))
rxBus.send(EventNSClientStatus("Not allowed")) rxBus.send(EventNSClientStatus(nsClientPlugin.blockingReason))
} else if (nsClientPlugin.paused) { } else if (nsClientPlugin.paused) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "paused")) rxBus.send(EventNSClientNewLog("NSCLIENT", "paused"))
rxBus.send(EventNSClientStatus("Paused")) rxBus.send(EventNSClientStatus("Paused"))

View file

@ -0,0 +1,6 @@
<vector android:height="48dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M21,10V4c0,-1.1 -0.9,-2 -2,-2H3C1.9,2 1.01,2.9 1.01,4L1,16c0,1.1 0.9,2 2,2h11v-5c0,-1.66 1.34,-3 3,-3H21zM11,11L3,6V4l8,5l8,-5v2L11,11z"/>
<path android:fillColor="@android:color/white" android:pathData="M21,14v4c0,1.1 -0.9,2 -2,2s-2,-0.9 -2,-2v-4.5c0,-0.28 0.22,-0.5 0.5,-0.5s0.5,0.22 0.5,0.5V18h2v-4.5c0,-1.38 -1.12,-2.5 -2.5,-2.5S15,12.12 15,13.5V18c0,2.21 1.79,4 4,4s4,-1.79 4,-4v-4H21z"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M12.375,4.563h8.688v14.188h-8.688z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M20.634,4.168h-6.852V2.553L2.52,4.292v15.237l11.263,1.94v-2.393h6.852c0.456,0 0.825,-0.332 0.825,-0.741V4.909C21.459,4.5 21.09,4.168 20.634,4.168zM20.743,18.458H13.76l-0.011,-1.278h1.682v-1.488h-1.695l-0.008,-0.88h1.703v-1.488h-1.716l-0.008,-0.88h1.724v-1.488h-1.73v-0.88h1.73V8.588h-1.73v-0.88h1.73V6.22h-1.73V4.868h7.042V18.458z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M16.377,6.22h2.924v1.488h-2.924z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M16.377,8.588h2.924v1.488h-2.924z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M16.377,10.956h2.924v1.488h-2.924z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M16.377,13.324h2.924v1.488h-2.924z"/>
<path android:fillColor="#20744A" android:fillType="evenOdd" android:pathData="M16.377,15.692h2.924v1.488h-2.924z"/>
<path android:fillColor="#FFFFFF" android:fillType="evenOdd" android:pathData="M5.46,8.407l1.452,-0.083l0.912,2.509l1.078,-2.612l1.452,-0.083l-1.763,3.562l1.763,3.571l-1.535,-0.104l-1.036,-2.722l-1.037,2.618l-1.41,-0.124l1.638,-3.154z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M13.548,12.645c0.028,-0.206 0.041,-0.42 0.041,-0.647c0,-0.22 -0.014,-0.44 -0.048,-0.647l1.396,-1.087c0.124,-0.096 0.158,-0.282 0.083,-0.42l-1.321,-2.284c-0.083,-0.151 -0.255,-0.199 -0.406,-0.151l-1.644,0.66c-0.344,-0.261 -0.709,-0.482 -1.114,-0.647l-0.248,-1.747c-0.028,-0.165 -0.165,-0.282 -0.33,-0.282H7.315c-0.165,0 -0.296,0.117 -0.323,0.282L6.744,7.424C6.338,7.589 5.967,7.816 5.63,8.07L3.986,7.41c-0.151,-0.055 -0.323,0 -0.406,0.151L2.266,9.845c-0.083,0.144 -0.055,0.323 0.083,0.42l1.396,1.087c-0.034,0.206 -0.062,0.433 -0.062,0.647s0.014,0.44 0.048,0.647l-1.396,1.087c-0.124,0.096 -0.158,0.282 -0.083,0.42l1.321,2.284c0.083,0.151 0.255,0.199 0.406,0.151l1.644,-0.66c0.344,0.261 0.709,0.482 1.114,0.647l0.248,1.747c0.034,0.165 0.165,0.282 0.33,0.282h2.642c0.165,0 0.303,-0.117 0.323,-0.282l0.248,-1.747c0.406,-0.165 0.777,-0.385 1.114,-0.647l1.644,0.66c0.151,0.055 0.323,0 0.406,-0.151l1.321,-2.284c0.083,-0.151 0.048,-0.323 -0.083,-0.42L13.548,12.645zM8.636,14.475c-1.362,0 -2.476,-1.114 -2.476,-2.476s1.114,-2.476 2.476,-2.476s2.476,1.114 2.476,2.476S9.998,14.475 8.636,14.475z"/>
<path android:fillColor="#6AE86D" android:pathData="M21.788,11.998l-4.975,-2.13l0,1.255l-7.896,0l0,1.75l7.896,0l0,1.255z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M20.264,12.645c0.028,-0.206 0.041,-0.42 0.041,-0.647c0,-0.22 -0.014,-0.44 -0.048,-0.647l1.396,-1.087c0.124,-0.096 0.158,-0.282 0.083,-0.42l-1.321,-2.284c-0.083,-0.151 -0.255,-0.199 -0.406,-0.151l-1.644,0.66c-0.344,-0.261 -0.709,-0.482 -1.114,-0.647l-0.248,-1.747c-0.028,-0.165 -0.165,-0.282 -0.33,-0.282h-2.642c-0.165,0 -0.296,0.117 -0.323,0.282L13.46,7.424c-0.406,0.165 -0.777,0.392 -1.114,0.647l-1.644,-0.66c-0.151,-0.055 -0.323,0 -0.406,0.151L8.982,9.845c-0.083,0.144 -0.055,0.323 0.083,0.42l1.396,1.087c-0.034,0.206 -0.062,0.433 -0.062,0.647s0.014,0.44 0.048,0.647l-1.396,1.087c-0.124,0.096 -0.158,0.282 -0.083,0.42l1.321,2.284c0.083,0.151 0.255,0.199 0.406,0.151l1.644,-0.66c0.344,0.261 0.709,0.482 1.114,0.647l0.248,1.747c0.034,0.165 0.165,0.282 0.33,0.282h2.642c0.165,0 0.303,-0.117 0.323,-0.282l0.248,-1.747c0.406,-0.165 0.777,-0.385 1.114,-0.647l1.644,0.66c0.151,0.055 0.323,0 0.406,-0.151l1.321,-2.284c0.083,-0.151 0.048,-0.323 -0.083,-0.42L20.264,12.645zM15.352,14.475c-1.362,0 -2.476,-1.114 -2.476,-2.476s1.114,-2.476 2.476,-2.476s2.476,1.114 2.476,2.476S16.714,14.475 15.352,14.475z"/>
<path android:fillColor="#6AE86D" android:pathData="M15.038,11.998l-4.975,-2.13l0,1.255l-7.896,0l0,1.75l7.896,0l0,1.255z"/>
</vector>

View file

@ -0,0 +1,30 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:pathData="M5.401,4.061h13.198v16.65h-13.198z"
android:strokeColor="?attr/colorControlNormal" android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,5.692L16.986,5.692"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,7.604L16.986,7.604"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,11.428L16.986,11.428"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,9.516L16.986,9.516"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,13.341L16.986,13.341"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,15.253L16.986,15.253"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,19.077L16.986,19.077"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M7.014,17.165L16.986,17.165"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:fillColor="#FF1313" android:pathData="M13.665,12.385l1.886,-1.886c0.081,-0.081 0.081,-0.213 0,-0.294L14.18,8.833c-0.078,-0.078 -0.216,-0.078 -0.294,0L12,10.719l-1.886,-1.886c-0.078,-0.078 -0.216,-0.078 -0.294,0l-1.372,1.372c-0.039,0.039 -0.061,0.092 -0.061,0.147c0,0.055 0.022,0.108 0.061,0.147l1.886,1.886l-1.886,1.886c-0.039,0.039 -0.061,0.092 -0.061,0.147c0,0.055 0.022,0.108 0.061,0.147l1.372,1.372c0.041,0.04 0.094,0.061 0.147,0.061s0.106,-0.02 0.147,-0.061L12,14.05l1.886,1.886c0.04,0.04 0.093,0.061 0.147,0.061s0.106,-0.02 0.147,-0.061l1.371,-1.371c0.081,-0.081 0.081,-0.213 0,-0.294L13.665,12.385z"/>
</vector>

View file

@ -0,0 +1,30 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M22.016,5.822c0.014,-0.103 0.021,-0.209 0.021,-0.322c0,-0.109 -0.007,-0.219 -0.024,-0.322l0.695,-0.541c0.062,-0.048 0.079,-0.14 0.041,-0.209l-0.657,-1.136c-0.041,-0.075 -0.127,-0.099 -0.202,-0.075l-0.818,0.328c-0.171,-0.13 -0.352,-0.239 -0.554,-0.322l-0.123,-0.869c-0.014,-0.082 -0.082,-0.14 -0.164,-0.14h-1.314c-0.082,0 -0.147,0.058 -0.161,0.14l-0.123,0.869c-0.202,0.082 -0.387,0.195 -0.554,0.322L17.26,3.218c-0.075,-0.027 -0.161,0 -0.202,0.075L16.405,4.43c-0.041,0.072 -0.027,0.161 0.041,0.209l0.695,0.541c-0.017,0.103 -0.031,0.216 -0.031,0.322c0,0.106 0.007,0.219 0.024,0.322l-0.695,0.541c-0.062,0.048 -0.079,0.14 -0.041,0.209l0.657,1.136c0.041,0.075 0.127,0.099 0.202,0.075l0.818,-0.328c0.171,0.13 0.352,0.239 0.554,0.322l0.123,0.869c0.017,0.082 0.082,0.14 0.164,0.14h1.314c0.082,0 0.151,-0.058 0.161,-0.14l0.123,-0.869c0.202,-0.082 0.387,-0.192 0.554,-0.322l0.818,0.328c0.075,0.027 0.161,0 0.202,-0.075l0.657,-1.136c0.041,-0.075 0.024,-0.161 -0.041,-0.209L22.016,5.822zM19.573,6.732c-0.677,0 -1.232,-0.554 -1.232,-1.232s0.554,-1.232 1.232,-1.232c0.677,0 1.232,0.554 1.232,1.232S20.25,6.732 19.573,6.732z"/>
<path android:pathData="M2.219,4.061h13.198v16.65h-13.198z"
android:strokeColor="?attr/colorControlNormal" android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,5.692L13.804,5.692"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,7.604L13.804,7.604"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,11.428L13.804,11.428"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,9.516L13.804,9.516"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,13.341L13.804,13.341"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,15.253L13.804,15.253"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,19.077L13.804,19.077"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
<path android:pathData="M3.831,17.165L13.804,17.165"
android:strokeColor="?attr/colorControlNormal" android:strokeLineCap="round"
android:strokeLineJoin="round" android:strokeWidth="0.4819"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#21A366" android:pathData="M14.149,4.479H8.418c-0.393,0 -0.716,0.323 -0.716,0.716v3.044L14.149,12l3.223,1.36L20.596,12V8.239L14.149,4.479z"/>
<path android:fillColor="#107C41" android:pathData="M7.702,8.239h6.447V12H7.702V8.239z"/>
<path android:fillColor="#33C481" android:pathData="M19.879,4.479h-5.731v3.761h6.447V5.195C20.596,4.802 20.272,4.479 19.879,4.479L19.879,4.479z"/>
<path android:fillColor="#185C37" android:pathData="M14.149,12H7.702v6.805c0,0.393 0.323,0.716 0.716,0.716h11.461c0.393,0 0.716,-0.323 0.716,-0.716v-3.044L14.149,12z"/>
<path android:fillColor="#107C41" android:pathData="M14.149,12h6.447v3.761h-6.447V12z"/>
<path android:fillAlpha="0.0941" android:fillColor="#FF000000" android:pathData="M12.358,7.165H7.702v10.207h4.656c0.392,-0.001 0.715,-0.324 0.716,-0.716V7.881C13.073,7.489 12.751,7.166 12.358,7.165L12.358,7.165z"/>
<path android:fillAlpha="0.2" android:fillColor="#FF000000" android:pathData="M11.821,7.702H7.702V17.91h4.119c0.392,-0.001 0.715,-0.324 0.716,-0.716V8.418C12.536,8.026 12.213,7.703 11.821,7.702L11.821,7.702z"/>
<path android:fillAlpha="0.2" android:fillColor="#FF000000" android:pathData="M11.821,7.702H7.702v9.133h4.119c0.392,-0.001 0.715,-0.324 0.716,-0.716v-7.7C12.536,8.026 12.213,7.703 11.821,7.702L11.821,7.702z"/>
<path android:fillAlpha="0.2" android:fillColor="#FF000000" android:pathData="M11.284,7.702H7.702v9.133h3.582c0.392,-0.001 0.715,-0.324 0.716,-0.716v-7.7C11.999,8.026 11.676,7.703 11.284,7.702L11.284,7.702z"/>
<path android:fillColor="#107C41" android:pathData="M4.121,7.702h7.163C11.677,7.702 12,8.026 12,8.418v7.163c0,0.393 -0.323,0.716 -0.716,0.716H4.121c-0.393,0 -0.716,-0.323 -0.716,-0.716V8.418C3.404,8.026 3.728,7.702 4.121,7.702L4.121,7.702z"/>
<path android:fillColor="#FFFFFF" android:pathData="M5.303,14.686l1.738,-2.694L5.449,9.314H6.73l0.869,1.712c0.08,0.162 0.135,0.284 0.165,0.364h0.011c0.057,-0.13 0.117,-0.256 0.18,-0.378l0.929,-1.697h1.176l-1.633,2.664l1.675,2.709H8.85l-1.004,-1.881c-0.047,-0.08 -0.087,-0.164 -0.12,-0.251H7.712c-0.029,0.085 -0.068,0.167 -0.116,0.243l-1.034,1.888L5.303,14.686z"/>
</vector>

View file

@ -0,0 +1,8 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M4.598,5.728a7.505,2.62 0,1 0,15.01 0a7.505,2.62 0,1 0,-15.01 0z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M19.051,7.533c-0.41,0.264 -0.91,0.493 -1.475,0.687c-1.517,0.521 -3.5,0.787 -5.473,0.787c-1.973,0 -3.957,-0.267 -5.473,-0.787C6.065,8.026 5.565,7.797 5.155,7.533C4.945,7.398 4.757,7.254 4.598,7.1v3.578c0.003,0.003 0.007,0.007 0.011,0.01c1.315,1.25 4.419,1.897 7.495,1.897c3.076,0 6.18,-0.647 7.495,-1.897c0.001,0 0.001,-0.001 0.002,-0.001V7.109C19.441,7.259 19.257,7.4 19.051,7.533z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M19.051,11.937c-0.41,0.264 -0.91,0.493 -1.475,0.687c-1.517,0.521 -3.5,0.787 -5.473,0.787c-1.973,0 -3.957,-0.267 -5.473,-0.787c-0.565,-0.194 -1.065,-0.423 -1.475,-0.687c-0.21,-0.135 -0.397,-0.28 -0.557,-0.433v3.578c0.003,0.003 0.007,0.007 0.011,0.01c1.315,1.25 4.419,1.897 7.495,1.897c3.076,0 6.18,-0.647 7.495,-1.897c0.001,0 0.001,-0.001 0.002,-0.001v-3.578C19.441,11.663 19.257,11.804 19.051,11.937z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M19.051,16.341c-0.41,0.264 -0.91,0.493 -1.475,0.687c-1.517,0.521 -3.5,0.787 -5.473,0.787c-1.973,0 -3.957,-0.267 -5.473,-0.787c-0.565,-0.194 -1.065,-0.423 -1.475,-0.687c-0.21,-0.135 -0.397,-0.28 -0.557,-0.433v3.578c0.003,0.003 0.007,0.007 0.011,0.01c1.315,1.25 4.419,1.897 7.495,1.897c3.076,0 6.18,-0.647 7.495,-1.897c0.001,0 0.001,-0.001 0.002,-0.001v-3.578C19.441,16.067 19.257,16.209 19.051,16.341z"/>
<path android:fillColor="#FF1313" android:pathData="M13.709,13.832l1.886,-1.886c0.081,-0.081 0.081,-0.213 0,-0.294l-1.372,-1.372c-0.078,-0.078 -0.216,-0.078 -0.294,0l-1.886,1.886l-1.886,-1.886c-0.078,-0.078 -0.216,-0.078 -0.294,0l-1.372,1.372c-0.039,0.039 -0.061,0.092 -0.061,0.147c0,0.055 0.022,0.108 0.061,0.147l1.886,1.886l-1.886,1.886c-0.039,0.039 -0.061,0.092 -0.061,0.147c0,0.055 0.022,0.108 0.061,0.147l1.372,1.372c0.041,0.04 0.094,0.061 0.147,0.061s0.106,-0.02 0.147,-0.061l1.886,-1.886l1.886,1.886c0.04,0.04 0.093,0.061 0.147,0.061s0.106,-0.02 0.147,-0.061l1.371,-1.371c0.081,-0.081 0.081,-0.213 0,-0.294L13.709,13.832z"/>
</vector>

View file

@ -0,0 +1,8 @@
<vector android:height="48dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorControlNormal" android:pathData="M7.014,8.802h9.973c0.133,0 0.241,-0.107 0.241,-0.241s-0.108,-0.241 -0.241,-0.241H7.014c-0.133,0 -0.241,0.107 -0.241,0.241S6.88,8.802 7.014,8.802z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M7.014,6.89h9.973c0.133,0 0.241,-0.107 0.241,-0.241s-0.108,-0.241 -0.241,-0.241H7.014c-0.133,0 -0.241,0.107 -0.241,0.241S6.88,6.89 7.014,6.89z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M7.014,12.627h9.973c0.133,0 0.241,-0.108 0.241,-0.241c0,-0.133 -0.108,-0.241 -0.241,-0.241H7.014c-0.133,0 -0.241,0.107 -0.241,0.241C6.773,12.519 6.88,12.627 7.014,12.627z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M7.014,10.714h9.973c0.133,0 0.241,-0.107 0.241,-0.241s-0.108,-0.241 -0.241,-0.241H7.014c-0.133,0 -0.241,0.107 -0.241,0.241S6.88,10.714 7.014,10.714z"/>
<path android:fillColor="?attr/colorControlNormal" android:pathData="M20.848,16.305l0.003,-5.737c0,-0.015 -0.014,-0.026 -0.017,-0.041c-0.008,-0.037 -0.019,-0.071 -0.042,-0.1c-0.007,-0.009 -0.004,-0.022 -0.012,-0.03L18.84,8.462V5.019c0,-0.133 -0.108,-0.241 -0.241,-0.241H15.16l-2.99,-2.99c-0.094,-0.094 -0.247,-0.094 -0.341,0l-2.991,2.99H5.401c-0.133,0 -0.241,0.107 -0.241,0.241v3.437l-1.94,1.94c-0.006,0.007 -0.004,0.017 -0.01,0.025c-0.026,0.033 -0.041,0.071 -0.047,0.114c-0.002,0.012 -0.013,0.02 -0.013,0.032v11.476c0,0.008 0.008,0.012 0.008,0.02c0,0.006 0.003,0.01 0.004,0.016c0.001,0.009 -0.004,0.017 -0.002,0.026c0.002,0.009 0.011,0.013 0.014,0.021c0.009,0.023 0.02,0.043 0.035,0.062c0.01,0.012 0.016,0.022 0.028,0.032c0.007,0.007 0.014,0.012 0.022,0.018c0.005,0.003 0.007,0.01 0.013,0.013c0.035,0.021 0.074,0.029 0.112,0.031c0.002,0 0.003,0.002 0.006,0.002h0.003h17.21h0.003c0.042,0 0.084,-0.011 0.121,-0.033c0.005,-0.003 0.008,-0.009 0.013,-0.013c0.009,-0.006 0.016,-0.013 0.024,-0.021c0.007,-0.006 0.01,-0.012 0.016,-0.019c0.02,-0.022 0.035,-0.046 0.046,-0.074c0.003,-0.008 0.011,-0.012 0.013,-0.02c0.002,-0.008 -0.003,-0.015 -0.002,-0.023c0.002,-0.013 0.01,-0.025 0.01,-0.038V16.305zM5.227,12.742c0.005,0.005 0.008,0.009 0.013,0.013l5.059,5.058l-4.125,2.361l-2.539,1.453V11.149L5.227,12.742zM20.365,11.155v5.079l-0.003,5.39l-5.153,-2.948l-1.504,-0.861L20.365,11.155zM10.791,17.625l-1.174,-1.174h4.771l-1.176,1.176L10.791,17.625zM14.871,15.969H9.135l-1.43,-1.43h8.596L14.871,15.969zM5.915,20.877l4.841,-2.769l2.491,0.002l3.115,1.782l3.338,1.91H4.3L5.915,20.877zM20.27,10.57L18.84,12V9.142L20.27,10.57zM12,2.299l2.479,2.479H9.521L12,2.299zM18.357,5.259v7.223l-1.574,1.574h-9.56l-1.581,-1.581V8.557c0,-0.001 0,-0.001 0,-0.002V5.259H18.357zM5.161,11.994l-1.429,-1.429l1.429,-1.428V11.994z"/>
</vector>

View file

@ -1,115 +1,237 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingTop="2dp" android:paddingTop="2dp"
tools:context=".plugins.general.maintenance.MaintenanceFragment"> tools:context=".plugins.general.maintenance.MaintenanceFragment">
<com.google.android.material.button.MaterialButton
android:id="@+id/unlock"
style="@style/GrayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/unlock_settings" />
<LinearLayout <LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/nav_logsettings" android:id="@+id/unlock"
style="@style/GrayButton" style="@style/GrayButton"
android:layout_width="fill_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_gravity="center"
android:layout_marginTop="3dp" android:text="@string/unlock_settings" />
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_logsettings"
android:textColor="?attr/treatmentButton" />
<com.google.android.material.button.MaterialButton <LinearLayout
android:id="@+id/log_send" android:id="@+id/main_layout"
style="@style/GrayButton" android:layout_width="match_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:orientation="vertical">
android:layout_marginTop="3dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/send_all_logs"
android:textColor="?attr/treatmentButton" />
<com.google.android.material.button.MaterialButton <com.google.android.material.card.MaterialCardView
android:id="@+id/log_delete" android:id="@+id/log"
style="@style/GrayButton" style="@style/Widget.MaterialComponents.CardView"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="4dp"
android:layout_marginTop="3dp" android:layout_marginEnd="4dp"
android:layout_marginEnd="10dp" android:layout_marginTop="4dp"
android:layout_marginBottom="3dp" app:cardCornerRadius="4dp"
android:layout_weight="0.5" app:contentPadding="2dp"
android:text="@string/delete_logs" app:cardElevation="2dp"
android:textColor="?attr/treatmentButton" /> app:cardUseCompatPadding="false"
android:layout_gravity="center">
<com.google.android.material.button.MaterialButton <TextView
android:id="@+id/nav_export" android:layout_width="match_parent"
style="@style/GrayButton" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:paddingStart="15dp"
android:layout_height="wrap_content" android:paddingEnd="15dp"
android:layout_marginStart="10dp" android:layout_marginBottom="10dp"
android:layout_marginTop="3dp" android:text="@string/log_files" />
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_export"
android:textColor="?attr/treatmentButton" />
<com.google.android.material.button.MaterialButton <androidx.gridlayout.widget.GridLayout
android:id="@+id/nav_import" android:layout_width="match_parent"
style="@style/GrayButton" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_marginTop="10dp"
android:layout_height="wrap_content" android:padding="10dip"
android:layout_marginStart="10dp" app:columnCount="2">
android:layout_marginTop="3dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="3dp"
android:layout_weight="0.5"
android:text="@string/nav_import"
android:textColor="?attr/treatmentButton" />
<com.google.android.material.button.MaterialButton <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/export_csv" android:id="@+id/nav_logsettings"
style="@style/GrayButton" style="@style/GrayButton"
android:layout_width="fill_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:drawableTop="@drawable/ic_log_settings"
android:layout_marginTop="3dp" android:paddingStart="0dp"
android:layout_marginEnd="10dp" android:paddingEnd="0dp"
android:layout_marginBottom="3dp" android:text="@string/nav_logsettings"
android:layout_weight="0.5" android:textSize="11sp"
android:text="@string/ue_export_to_csv" app:layout_column="0"
android:textColor="?attr/treatmentButton" /> app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
<com.google.android.material.button.MaterialButton <info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/nav_resetdb" android:id="@+id/log_send"
style="@style/GrayButton" style="@style/GrayButton"
android:layout_width="fill_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:drawableTop="@drawable/ic_send_log"
android:layout_marginTop="3dp" android:paddingStart="0dp"
android:layout_marginEnd="10dp" android:paddingEnd="0dp"
android:layout_marginBottom="3dp" android:text="@string/send_all_logs"
android:layout_weight="0.5" android:textSize="11sp"
android:text="@string/nav_resetdb" app:layout_column="1"
android:textColor="?attr/treatmentButton" /> app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/log_delete"
style="@style/GrayButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_log_delete"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/delete_logs"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="1" />
</androidx.gridlayout.widget.GridLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/nav"
style="@style/Widget.MaterialComponents.CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="4dp"
app:contentPadding="2dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="false"
android:layout_gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:layout_marginBottom="10dp"
android:text="@string/settings" />
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="10dip"
app:columnCount="2">
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/nav_export"
style="@style/GrayButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_export_settings"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/nav_export"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/nav_import"
style="@style/GrayButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_import_settings"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/nav_import"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
</androidx.gridlayout.widget.GridLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/misc"
style="@style/Widget.MaterialComponents.CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="4dp"
app:contentPadding="2dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="false"
android:layout_gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:layout_marginBottom="10dp"
android:text="@string/miscellaneous" />
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="10dip"
app:columnCount="2">
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/export_csv"
style="@style/GrayButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_excel"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/ue_export_to_csv"
android:textSize="11sp"
app:layout_column="0"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
<info.nightscout.androidaps.utils.ui.SingleClickButton
android:id="@+id/nav_resetdb"
style="@style/GrayButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_reset_database"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/nav_resetdb"
android:textSize="11sp"
app:layout_column="1"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_row="0" />
</androidx.gridlayout.widget.GridLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</LinearLayout> </LinearLayout>
</FrameLayout> </androidx.core.widget.NestedScrollView>

View file

@ -681,6 +681,8 @@
<string name="error_adding_treatment_message">Ošetření (inzulín: %1$.2f, sacharidy: %2$d, čas: %3$s) nelze přidat. Zkontrolujte a podle potřeby ručně přidejte záznam.</string> <string name="error_adding_treatment_message">Ošetření (inzulín: %1$.2f, sacharidy: %2$d, čas: %3$s) nelze přidat. Zkontrolujte a podle potřeby ručně přidejte záznam.</string>
<string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), zpoždění: %3$d m</string> <string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), zpoždění: %3$d m</string>
<string name="openaps_noasdata">Nedostupná data o glykémiích</string> <string name="openaps_noasdata">Nedostupná data o glykémiích</string>
<string name="log_files">Soubory protokolu</string>
<string name="miscellaneous">Různé</string>
<string name="nav_logsettings">Nastavení logování</string> <string name="nav_logsettings">Nastavení logování</string>
<string name="resettodefaults">Obnovit výchozí</string> <string name="resettodefaults">Obnovit výchozí</string>
<string name="nsmalfunction">Chyba NSClienta. Zvažte restart NS a NSClienta.</string> <string name="nsmalfunction">Chyba NSClienta. Zvažte restart NS a NSClienta.</string>

View file

@ -681,6 +681,8 @@
<string name="error_adding_treatment_message">Un tratamiento (insulina: %1$.2f, carbs: %2$d, at: %3$s) no ha podido ser añadido a tratamientos. Por favor compruebe y añada manualmente el registro apropiadamente.</string> <string name="error_adding_treatment_message">Un tratamiento (insulina: %1$.2f, carbs: %2$d, at: %3$s) no ha podido ser añadido a tratamientos. Por favor compruebe y añada manualmente el registro apropiadamente.</string>
<string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), retraso: %3$d m</string> <string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), retraso: %3$d m</string>
<string name="openaps_noasdata">Sin datos autosens disponibles</string> <string name="openaps_noasdata">Sin datos autosens disponibles</string>
<string name="log_files">Archivos de registro</string>
<string name="miscellaneous">Misceláneo</string>
<string name="nav_logsettings">Ajustes de registros</string> <string name="nav_logsettings">Ajustes de registros</string>
<string name="resettodefaults">Restablecer valores predeterminados</string> <string name="resettodefaults">Restablecer valores predeterminados</string>
<string name="nsmalfunction">NSClient fallando. Considera reiniciar NS y NSClient.</string> <string name="nsmalfunction">NSClient fallando. Considera reiniciar NS y NSClient.</string>
@ -773,8 +775,8 @@
<string name="invalidpct">Entrada % inválida</string> <string name="invalidpct">Entrada % inválida</string>
<string name="average">Promedio</string> <string name="average">Promedio</string>
<string name="tir">Tiempo en rango</string> <string name="tir">Tiempo en rango</string>
<string name="day_tir">TIR (Día)</string> <string name="day_tir">TIR Diurno</string>
<string name="night_tir">TIR (Noche)</string> <string name="night_tir">TIR Nocturno</string>
<string name="detailed_14_days">Datos detallados de 14 días</string> <string name="detailed_14_days">Datos detallados de 14 días</string>
<string name="std_deviation">Desviación estándar: %1$s</string> <string name="std_deviation">Desviación estándar: %1$s</string>
<string name="hba1c">HbA1c: </string> <string name="hba1c">HbA1c: </string>

View file

@ -733,13 +733,17 @@
<string name="secondcarbsincrement">Second carbs increment</string> <string name="secondcarbsincrement">Second carbs increment</string>
<string name="thirdcarbsincrement">Third carbs increment</string> <string name="thirdcarbsincrement">Third carbs increment</string>
<string name="cgm">CGM</string> <string name="cgm">CGM</string>
<string name="key_ns_wifionly" translatable="false">ns_wifionly</string> <string name="key_ns_cellular" translatable="false">ns_cellular</string>
<string name="key_ns_wifi" translatable="false">ns_wifi</string>
<string name="key_ns_wifi_ssids" translatable="false">ns_wifi_ssids</string> <string name="key_ns_wifi_ssids" translatable="false">ns_wifi_ssids</string>
<string name="key_ns_allowroaming" translatable="false">ns_allowroaming</string> <string name="key_ns_allow_roaming" translatable="false">ns_allowroaming</string>
<string name="key_ns_chargingonly" translatable="false">ns_chargingonly</string> <string name="key_ns_battery" translatable="false">ns_battery</string>
<string name="ns_wifionly">Use WiFi connection only</string> <string name="key_ns_charging" translatable="false">ns_charging</string>
<string name="ns_cellular">Use Cellular connection</string>
<string name="ns_wifi">Use WiFi connection</string>
<string name="ns_wifi_ssids">WiFi SSID</string> <string name="ns_wifi_ssids">WiFi SSID</string>
<string name="ns_chargingonly">Only if charging</string> <string name="ns_charging">During charging</string>
<string name="ns_battery">On battery</string>
<string name="connectionsettings_title">Connection settings</string> <string name="connectionsettings_title">Connection settings</string>
<string name="ns_wifi_allowedssids">Allowed SSIDs (semicolon separated)</string> <string name="ns_wifi_allowedssids">Allowed SSIDs (semicolon separated)</string>
<string name="ns_allowroaming">Allow connection in roaming</string> <string name="ns_allowroaming">Allow connection in roaming</string>
@ -830,6 +834,8 @@
<string name="error_adding_treatment_message">A treatment (insulin: %1$.2f, carbs: %2$d, at: %3$s) could not be added to treatments. Please check and manually add a record as appropriate.</string> <string name="error_adding_treatment_message">A treatment (insulin: %1$.2f, carbs: %2$d, at: %3$s) could not be added to treatments. Please check and manually add a record as appropriate.</string>
<string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), delay: %3$d m</string> <string name="generated_ecarbs_note">eCarbs: %1$d g (%2$d h), delay: %3$d m</string>
<string name="openaps_noasdata">No autosens data available</string> <string name="openaps_noasdata">No autosens data available</string>
<string name="log_files">Log files</string>
<string name="miscellaneous">Miscellaneous</string>
<string name="nav_logsettings">Log settings</string> <string name="nav_logsettings">Log settings</string>
<string name="resettodefaults">Reset to defaults</string> <string name="resettodefaults">Reset to defaults</string>
<string name="nsmalfunction">NSClient malfunction. Consider NS and NSClient restart.</string> <string name="nsmalfunction">NSClient malfunction. Consider NS and NSClient restart.</string>
@ -1238,6 +1244,8 @@
<string name="aidex">GlucoRx Aidex</string> <string name="aidex">GlucoRx Aidex</string>
<string name="aidex_short">Aidex</string> <string name="aidex_short">Aidex</string>
<string name="description_source_aidex">Receive BG values from GlucoRx Aidex CGMS.</string> <string name="description_source_aidex">Receive BG values from GlucoRx Aidex CGMS.</string>
<string name="blocked_by_charging">Blocked by charging options</string>
<string name="blocked_by_connectivity">Blocked by connectivity options</string>
</resources> </resources>

View file

@ -138,26 +138,36 @@
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:disableDependentsState="true" android:key="@string/key_ns_cellular"
android:key="@string/key_ns_wifionly" android:title="@string/ns_cellular" />
android:title="@string/ns_wifionly" />
<SwitchPreference
android:defaultValue="true"
android:dependency="@string/key_ns_cellular"
android:key="@string/key_ns_allow_roaming"
android:title="@string/ns_allowroaming" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_ns_wifi"
android:title="@string/ns_wifi" />
<EditTextPreference <EditTextPreference
android:dialogMessage="@string/ns_wifi_allowedssids" android:dialogMessage="@string/ns_wifi_allowedssids"
android:dependency="@string/key_ns_wifi"
android:inputType="text" android:inputType="text"
android:key="@string/key_ns_wifi_ssids" android:key="@string/key_ns_wifi_ssids"
android:title="@string/ns_wifi_ssids" /> android:title="@string/ns_wifi_ssids" />
<SwitchPreference <SwitchPreference
android:defaultValue="true" android:defaultValue="true"
android:dependency="@string/key_ns_wifionly" android:key="@string/key_ns_battery"
android:key="@string/key_ns_allowroaming" android:title="@string/ns_battery" />
android:title="@string/ns_allowroaming" />
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="true"
android:key="@string/key_ns_chargingonly" android:key="@string/key_ns_charging"
android:title="@string/ns_chargingonly" /> android:title="@string/ns_charging" />
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

View file

@ -5,17 +5,13 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.events.EventChargingState import info.nightscout.androidaps.events.EventChargingState
import info.nightscout.androidaps.events.EventNetworkChange import info.nightscout.androidaps.events.EventNetworkChange
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.receivers.ReceiverStatusStore import info.nightscout.androidaps.receivers.ReceiverStatusStore
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
@ -24,98 +20,71 @@ class NsClientReceiverDelegateTest : TestBase() {
@Mock lateinit var context: Context @Mock lateinit var context: Context
@Mock lateinit var sp: SP @Mock lateinit var sp: SP
@Mock lateinit var rh: ResourceHelper @Mock lateinit var rh: ResourceHelper
lateinit var receiverStatusStore: ReceiverStatusStore
val rxBus = RxBus(aapsSchedulers, aapsLogger) val rxBus = RxBus(aapsSchedulers, aapsLogger)
private var sut: NsClientReceiverDelegate? = null private lateinit var receiverStatusStore: ReceiverStatusStore
private lateinit var sut: NsClientReceiverDelegate
@Before fun prepare() {
@Before
fun prepare() {
receiverStatusStore = ReceiverStatusStore(context, rxBus) receiverStatusStore = ReceiverStatusStore(context, rxBus)
`when`(sp.getLong(anyInt(), anyLong())).thenReturn(0L)
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false)
`when`(sp.getInt(anyInt(), anyInt())).thenReturn(0)
`when`(sp.getString(anyInt(), anyString())).thenReturn("")
sut = NsClientReceiverDelegate(rxBus, rh, sp, receiverStatusStore) sut = NsClientReceiverDelegate(rxBus, rh, sp, receiverStatusStore)
} }
@Test fun testCalculateStatusChargingState() { @Test
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false) fun testCalculateStatusChargingState() {
var ev = EventChargingState(true, 0) `when`(sp.getBoolean(R.string.key_ns_battery, true)).thenReturn(true)
Assert.assertTrue(sut!!.calculateStatus(ev)) `when`(sp.getBoolean(R.string.key_ns_charging, true)).thenReturn(false)
ev = EventChargingState(false, 0) Assert.assertTrue(sut.calculateStatus(EventChargingState(false, 0)))
Assert.assertTrue(sut!!.calculateStatus(ev)) Assert.assertFalse(sut.calculateStatus(EventChargingState(true, 0)))
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(true) `when`(sp.getBoolean(R.string.key_ns_battery, true)).thenReturn(false)
ev = EventChargingState(true, 0) `when`(sp.getBoolean(R.string.key_ns_charging, true)).thenReturn(true)
Assert.assertTrue(sut!!.calculateStatus(ev)) Assert.assertTrue(sut.calculateStatus(EventChargingState(true, 0)))
ev = EventChargingState(false, 0) Assert.assertFalse(sut.calculateStatus(EventChargingState(false, 0)))
Assert.assertTrue(!sut!!.calculateStatus(ev))
} }
@Test fun testCalculateStatusNetworkState() { @Test
// wifiOnly = false fun testCalculateStatusNetworkState() {
// allowRoaming = false as well `when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false) `when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
`when`(sp.getString(anyInt(), anyString())).thenReturn("") `when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
val ev = EventNetworkChange() `when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
ev.ssid = "<unknown ssid>" Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = true)))
ev.mobileConnected = true Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = false)))
ev.wifiConnected = true Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = true, wifiConnected = true)))
Assert.assertTrue(sut!!.calculateStatus(ev)) Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = false, wifiConnected = true)))
ev.ssid = "test" Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
`when`(sp.getString(anyInt(), anyString())).thenReturn("test")
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.ssid = "test"
Assert.assertTrue(sut!!.calculateStatus(ev))
ev.wifiConnected = false
Assert.assertTrue(sut!!.calculateStatus(ev))
// wifiOnly = true `when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("test")
// allowRoaming = true as well Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = true)))
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(true) Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, wifiConnected = false, roaming = false)))
ev.wifiConnected = true Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = true, wifiConnected = true)))
Assert.assertTrue(sut!!.calculateStatus(ev)) Assert.assertFalse(sut.calculateStatus(EventNetworkChange(ssid = "<unknown ssid>", mobileConnected = false, wifiConnected = true)))
ev.wifiConnected = false Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "test", mobileConnected = true, wifiConnected = true)))
Assert.assertTrue(!sut!!.calculateStatus(ev)) Assert.assertTrue(sut.calculateStatus(EventNetworkChange(ssid = "test", mobileConnected = false, wifiConnected = true)))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
// wifiOnly = false `when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(false)
// allowRoaming = false as well `when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(anyInt(), anyBoolean())).thenReturn(false) `when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
ev.wifiConnected = false `when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
ev.roaming = true Assert.assertTrue(sut.calculateStatus(EventNetworkChange(wifiConnected = true)))
Assert.assertTrue(!sut!!.calculateStatus(ev)) Assert.assertFalse(sut.calculateStatus(EventNetworkChange()))
Assert.assertFalse(sut.calculateStatus(EventNetworkChange(mobileConnected = true)))
// wifiOnly = false `when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
// allowRoaming = true `when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(false) `when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true) `when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
ev.wifiConnected = false Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = false)))
ev.roaming = true Assert.assertFalse(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = true)))
Assert.assertTrue(sut!!.calculateStatus(ev))
// wifiOnly = true `when`(sp.getBoolean(R.string.key_ns_cellular, true)).thenReturn(true)
// allowRoaming = true `when`(sp.getBoolean(R.string.key_ns_wifi, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(true) `when`(sp.getBoolean(R.string.key_ns_allow_roaming, true)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true) `when`(sp.getString(R.string.key_ns_wifi_ssids, "")).thenReturn("")
ev.wifiConnected = false Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = false)))
ev.roaming = true Assert.assertTrue(sut.calculateStatus(EventNetworkChange(mobileConnected = true, roaming = true)))
Assert.assertTrue(!sut!!.calculateStatus(ev))
// wifiOnly = true
// allowRoaming = true
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(true)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(true)
ev.wifiConnected = true
ev.roaming = true
Assert.assertTrue(sut!!.calculateStatus(ev))
// wifiOnly = false
// allowRoaming = false
`when`(sp.getBoolean(R.string.key_ns_wifionly, false)).thenReturn(false)
`when`(sp.getBoolean(R.string.key_ns_allowroaming, true)).thenReturn(false)
ev.wifiConnected = true
ev.roaming = true
Assert.assertTrue(sut!!.calculateStatus(ev))
} }
} }

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.TimerUtil import info.nightscout.androidaps.utils.TimerUtil
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +39,7 @@ class ActionAlarm(injector: HasAndroidInjector) : Action(injector) {
override fun doAction(callback: Callback) { override fun doAction(callback: Callback) {
timerUtil.scheduleReminder(10, text.value.takeIf { it.isNotBlank() } timerUtil.scheduleReminder(10, text.value.takeIf { it.isNotBlank() }
?: rh.gs(R.string.app_name)) ?: rh.gs(R.string.app_name))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} }
override fun toJSON(): String { override fun toJSON(): String {

View file

@ -33,9 +33,9 @@ class ActionLoopEnable(injector: HasAndroidInjector) : Action(injector) {
configBuilder.storeSettings("ActionLoopEnable") configBuilder.storeSettings("ActionLoopEnable")
rxBus.send(EventRefreshOverview("ActionLoopEnable")) rxBus.send(EventRefreshOverview("ActionLoopEnable"))
uel.log(UserEntry.Action.LOOP_ENABLED, Sources.Automation, title) uel.log(UserEntry.Action.LOOP_ENABLED, Sources.Automation, title)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else { } else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyenabled))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyenabled)).run()
} }
} }

View file

@ -45,9 +45,9 @@ class ActionLoopResume(injector: HasAndroidInjector) : Action(injector) {
}) })
rxBus.send(EventRefreshOverview("ActionLoopResume")) rxBus.send(EventRefreshOverview("ActionLoopResume"))
uel.log(UserEntry.Action.RESUME, Sources.Automation, title) uel.log(UserEntry.Action.RESUME, Sources.Automation, title)
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else { } else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.notsuspended))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.notsuspended)).run()
} }
} }

View file

@ -40,9 +40,9 @@ class ActionLoopSuspend(injector: HasAndroidInjector) : Action(injector) {
UserEntry.Action.SUSPEND, Sources.Automation, title + ": " + rh.gs(R.string.suspendloopforXmin, minutes.getMinutes()), UserEntry.Action.SUSPEND, Sources.Automation, title + ": " + rh.gs(R.string.suspendloopforXmin, minutes.getMinutes()),
ValueWithUnit.Minute(minutes.getMinutes()) ValueWithUnit.Minute(minutes.getMinutes())
) )
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else { } else {
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadysuspended))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadysuspended)).run()
} }
} }

View file

@ -39,7 +39,7 @@ class ActionNotification(injector: HasAndroidInjector) : Action(injector) {
rxBus.send(EventNewNotification(notification)) rxBus.send(EventNewNotification(notification))
disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(text.value)).subscribe() disposable += repository.runTransaction(InsertTherapyEventAnnouncementTransaction(text.value)).subscribe()
rxBus.send(EventRefreshOverview("ActionNotification")) rxBus.send(EventRefreshOverview("ActionNotification"))
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} }
override fun toJSON(): String { override fun toJSON(): String {

View file

@ -10,7 +10,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.automation.elements.InputProfileName import info.nightscout.androidaps.plugins.general.automation.elements.InputProfileName
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement
@ -18,6 +17,7 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.shared.logging.LTag
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
@ -39,23 +39,23 @@ class ActionProfileSwitch(injector: HasAndroidInjector) : Action(injector) {
//Check for uninitialized profileName //Check for uninitialized profileName
if (inputProfileName.value == "") { if (inputProfileName.value == "") {
aapsLogger.error(LTag.AUTOMATION, "Selected profile not initialized") aapsLogger.error(LTag.AUTOMATION, "Selected profile not initialized")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error_field_must_not_be_empty))?.run() callback.result(PumpEnactResult(injector).success(false).comment(R.string.error_field_must_not_be_empty)).run()
return return
} }
if (profileFunction.getProfile() == null) { if (profileFunction.getProfile() == null) {
aapsLogger.error(LTag.AUTOMATION, "ProfileFunctions not initialized") aapsLogger.error(LTag.AUTOMATION, "ProfileFunctions not initialized")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.noprofile))?.run() callback.result(PumpEnactResult(injector).success(false).comment(R.string.noprofile)).run()
return return
} }
if (inputProfileName.value == activeProfileName) { if (inputProfileName.value == activeProfileName) {
aapsLogger.debug(LTag.AUTOMATION, "Profile is already switched") aapsLogger.debug(LTag.AUTOMATION, "Profile is already switched")
callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyset))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.alreadyset)).run()
return return
} }
val profileStore = activePlugin.activeProfileSource.profile ?: return val profileStore = activePlugin.activeProfileSource.profile ?: return
if (profileStore.getSpecificProfile(inputProfileName.value) == null) { if (profileStore.getSpecificProfile(inputProfileName.value) == null) {
aapsLogger.error(LTag.AUTOMATION, "Selected profile does not exist! - ${inputProfileName.value}") aapsLogger.error(LTag.AUTOMATION, "Selected profile does not exist! - ${inputProfileName.value}")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.notexists))?.run() callback.result(PumpEnactResult(injector).success(false).comment(R.string.notexists)).run()
return return
} }
uel.log( uel.log(
@ -64,7 +64,7 @@ class ActionProfileSwitch(injector: HasAndroidInjector) : Action(injector) {
ValueWithUnit.Percent(100) ValueWithUnit.Percent(100)
) )
val result = profileFunction.createProfileSwitch(profileStore, inputProfileName.value, 0, 100, 0, dateUtil.now()) val result = profileFunction.createProfileSwitch(profileStore, inputProfileName.value, 0, 100, 0, dateUtil.now())
callback.result(PumpEnactResult(injector).success(result).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(result).comment(R.string.ok)).run()
} }
override fun generateDialog(root: LinearLayout) { override fun generateDialog(root: LinearLayout) {

View file

@ -9,7 +9,6 @@ import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.entities.ValueWithUnit
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
@ -19,6 +18,7 @@ import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuil
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerProfilePercent import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerProfilePercent
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.shared.logging.LTag
import org.json.JSONObject import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
@ -50,10 +50,10 @@ class ActionProfileSwitchPercent(injector: HasAndroidInjector) : Action(injector
ValueWithUnit.Percent(pct.value.toInt()), ValueWithUnit.Percent(pct.value.toInt()),
ValueWithUnit.Minute(duration.value) ValueWithUnit.Minute(duration.value)
) )
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} else { } else {
aapsLogger.error(LTag.AUTOMATION, "Final profile not valid") aapsLogger.error(LTag.AUTOMATION, "Final profile not valid")
callback.result(PumpEnactResult(injector).success(false).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(false).comment(R.string.ok)).run()
} }
} }

View file

@ -22,6 +22,7 @@ import org.json.JSONObject
import javax.inject.Inject import javax.inject.Inject
class ActionRunAutotune(injector: HasAndroidInjector) : Action(injector) { class ActionRunAutotune(injector: HasAndroidInjector) : Action(injector) {
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var autotunePlugin: Autotune @Inject lateinit var autotunePlugin: Autotune
@Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var profileFunction: ProfileFunction
@ -48,7 +49,7 @@ class ActionRunAutotune(injector: HasAndroidInjector) : Action(injector) {
message = R.string.autotune_run_with_error message = R.string.autotune_run_with_error
aapsLogger.error(LTag.AUTOMATION, "Error during Autotune Run") aapsLogger.error(LTag.AUTOMATION, "Error during Autotune Run")
} }
callback.result(PumpEnactResult(injector).success(autotunePlugin.lastRunSuccess).comment(message))?.run() callback.result(PumpEnactResult(injector).success(autotunePlugin.lastRunSuccess).comment(message)).run()
}.start() }.start()
return return
} }

View file

@ -25,7 +25,7 @@ class ActionSendSMS(injector: HasAndroidInjector) : Action(injector) {
override fun doAction(callback: Callback) { override fun doAction(callback: Callback) {
val result = smsCommunicatorPlugin.sendNotificationToAllNumbers(text.value) val result = smsCommunicatorPlugin.sendNotificationToAllNumbers(text.value)
callback.result(PumpEnactResult(injector).success(result).comment(if (result) R.string.ok else R.string.error))?.run() callback.result(PumpEnactResult(injector).success(result).comment(if (result) R.string.ok else R.string.error)).run()
} }
override fun isValid(): Boolean = text.value.isNotEmpty() override fun isValid(): Boolean = text.value.isNotEmpty()

View file

@ -17,7 +17,6 @@ import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration
@ -29,6 +28,7 @@ import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble import info.nightscout.androidaps.utils.JsonHelper.safeGetDouble
import info.nightscout.shared.logging.LTag
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import org.json.JSONObject import org.json.JSONObject
@ -59,18 +59,20 @@ class ActionStartTempTarget(injector: HasAndroidInjector) : Action(injector) {
override fun doAction(callback: Callback) { override fun doAction(callback: Callback) {
disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(tt())) disposable += repository.runTransactionForResult(InsertAndCancelCurrentTemporaryTargetTransaction(tt()))
.subscribe({ result -> .subscribe({ result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temp target $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temp target $it") }
uel.log(UserEntry.Action.TT, Sources.Automation, title, uel.log(
ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.AUTOMATION), UserEntry.Action.TT, Sources.Automation, title,
ValueWithUnit.Mgdl(tt().lowTarget), ValueWithUnit.TherapyEventTTReason(TemporaryTarget.Reason.AUTOMATION),
ValueWithUnit.Mgdl(tt().highTarget).takeIf { tt().lowTarget != tt().highTarget }, ValueWithUnit.Mgdl(tt().lowTarget),
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt().duration).toInt())) ValueWithUnit.Mgdl(tt().highTarget).takeIf { tt().lowTarget != tt().highTarget },
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt().duration).toInt())
}, { )
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error))?.run() }, {
}) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
callback.result(PumpEnactResult(injector).success(false).comment(R.string.error)).run()
})
} }
override fun generateDialog(root: LinearLayout) { override fun generateDialog(root: LinearLayout) {

View file

@ -7,10 +7,10 @@ import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.entities.UserEntry import info.nightscout.androidaps.database.entities.UserEntry
import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.UserEntry.Sources
import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction import info.nightscout.androidaps.database.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.shared.logging.LTag
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject import javax.inject.Inject
@ -35,7 +35,7 @@ class ActionStopTempTarget(injector: HasAndroidInjector) : Action(injector) {
}, { }, {
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
}) })
callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok))?.run() callback.result(PumpEnactResult(injector).success(true).comment(R.string.ok)).run()
} }
override fun isValid(): Boolean = true override fun isValid(): Boolean = true

View file

@ -10,7 +10,7 @@ buildscript {
room_version = '2.4.2' room_version = '2.4.2'
lifecycle_version = '2.4.1' lifecycle_version = '2.4.1'
dagger_version = '2.42' dagger_version = '2.42'
coroutines_version = '1.6.1' coroutines_version = '1.6.2'
activity_version = '1.4.0' activity_version = '1.4.0'
fragmentktx_version = '1.4.1' fragmentktx_version = '1.4.1'
ormLite_version = '4.46' ormLite_version = '4.46'

View file

@ -1,12 +1,10 @@
package info.nightscout.androidaps.events package info.nightscout.androidaps.events
class EventNetworkChange : Event() { class EventNetworkChange(
var mobileConnected: Boolean = false,
var mobileConnected = false var wifiConnected: Boolean = false,
var wifiConnected = false var vpnConnected: Boolean = false,
var vpnConnected = false var ssid: String = "",
var roaming: Boolean = false,
var ssid = "" var metered: Boolean = false
var roaming = false ) : Event()
var metered = false
}

View file

@ -96,6 +96,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
* @param isSecondScale whether it is the second scale * @param isSecondScale whether it is the second scale
*/ */
@Override @Override
@SuppressWarnings({"deprecation"})
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) { public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
// Convert the sp to pixels // Convert the sp to pixels
float scaledTextSize = spSize * graphView.getContext().getResources().getDisplayMetrics().scaledDensity; float scaledTextSize = spSize * graphView.getContext().getResources().getDisplayMetrics().scaledDensity;

View file

@ -4,6 +4,7 @@ import java.math.BigDecimal
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.round
import kotlin.math.roundToLong import kotlin.math.roundToLong
/** /**

22
icons/excel.svg Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="Excel">
<g>
<rect x="12.375" y="4.563" fill="#FFFFFF" width="8.688" height="14.188"/>
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" d="M20.634,4.168h-6.852V2.553L2.52,4.292v15.237l11.263,1.94
v-2.393h6.852c0.456,0,0.825-0.332,0.825-0.741V4.909C21.459,4.5,21.09,4.168,20.634,4.168z M20.743,18.458H13.76l-0.011-1.278
h1.682v-1.488h-1.695l-0.008-0.88h1.703v-1.488h-1.716l-0.008-0.88h1.724v-1.488h-1.73v-0.88h1.73V8.588h-1.73v-0.88h1.73V6.22
h-1.73V4.868h7.042V18.458z"/>
<rect x="16.377" y="6.22" fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" width="2.924" height="1.488"/>
<rect x="16.377" y="8.588" fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" width="2.924" height="1.488"/>
<rect x="16.377" y="10.956" fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" width="2.924" height="1.488"/>
<rect x="16.377" y="13.324" fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" width="2.924" height="1.488"/>
<rect x="16.377" y="15.692" fill-rule="evenodd" clip-rule="evenodd" fill="#20744A" width="2.924" height="1.488"/>
</g>
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" points="5.46,8.407 6.912,8.324 7.824,10.833 8.902,8.221
10.354,8.138 8.591,11.7 10.354,15.271 8.819,15.167 7.783,12.445 6.746,15.063 5.336,14.939 6.974,11.785 "/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

18
icons/export_settings.svg Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="Export_Settings">
<path fill="#FFFFFF" d="M13.548,12.645c0.028-0.206,0.041-0.42,0.041-0.647c0-0.22-0.014-0.44-0.048-0.647l1.396-1.087
c0.124-0.096,0.158-0.282,0.083-0.42l-1.321-2.284c-0.083-0.151-0.255-0.199-0.406-0.151l-1.644,0.66
c-0.344-0.261-0.709-0.482-1.114-0.647l-0.248-1.747c-0.028-0.165-0.165-0.282-0.33-0.282H7.315c-0.165,0-0.296,0.117-0.323,0.282
L6.744,7.424C6.338,7.589,5.967,7.816,5.63,8.07L3.986,7.41c-0.151-0.055-0.323,0-0.406,0.151L2.266,9.845
c-0.083,0.144-0.055,0.323,0.083,0.42l1.396,1.087c-0.034,0.206-0.062,0.433-0.062,0.647s0.014,0.44,0.048,0.647l-1.396,1.087
c-0.124,0.096-0.158,0.282-0.083,0.42l1.321,2.284c0.083,0.151,0.255,0.199,0.406,0.151l1.644-0.66
c0.344,0.261,0.709,0.482,1.114,0.647l0.248,1.747c0.034,0.165,0.165,0.282,0.33,0.282h2.642c0.165,0,0.303-0.117,0.323-0.282
l0.248-1.747c0.406-0.165,0.777-0.385,1.114-0.647l1.644,0.66c0.151,0.055,0.323,0,0.406-0.151l1.321-2.284
c0.083-0.151,0.048-0.323-0.083-0.42L13.548,12.645z M8.636,14.475c-1.362,0-2.476-1.114-2.476-2.476s1.114-2.476,2.476-2.476
s2.476,1.114,2.476,2.476S9.998,14.475,8.636,14.475z"/>
<polygon fill="#6AE86D" points="21.788,11.998 16.813,9.868 16.813,11.123 8.917,11.123 8.917,12.873 16.813,12.873 16.813,14.128
"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

18
icons/import_settings.svg Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="Import_Settings">
<path fill="#FFFFFF" d="M20.264,12.645c0.028-0.206,0.041-0.42,0.041-0.647c0-0.22-0.014-0.44-0.048-0.647l1.396-1.087
c0.124-0.096,0.158-0.282,0.083-0.42l-1.321-2.284c-0.083-0.151-0.255-0.199-0.406-0.151l-1.644,0.66
c-0.344-0.261-0.709-0.482-1.114-0.647l-0.248-1.747c-0.028-0.165-0.165-0.282-0.33-0.282h-2.642c-0.165,0-0.296,0.117-0.323,0.282
L13.46,7.424c-0.406,0.165-0.777,0.392-1.114,0.647l-1.644-0.66c-0.151-0.055-0.323,0-0.406,0.151L8.982,9.845
c-0.083,0.144-0.055,0.323,0.083,0.42l1.396,1.087c-0.034,0.206-0.062,0.433-0.062,0.647s0.014,0.44,0.048,0.647l-1.396,1.087
c-0.124,0.096-0.158,0.282-0.083,0.42l1.321,2.284c0.083,0.151,0.255,0.199,0.406,0.151l1.644-0.66
c0.344,0.261,0.709,0.482,1.114,0.647l0.248,1.747c0.034,0.165,0.165,0.282,0.33,0.282h2.642c0.165,0,0.303-0.117,0.323-0.282
l0.248-1.747c0.406-0.165,0.777-0.385,1.114-0.647l1.644,0.66c0.151,0.055,0.323,0,0.406-0.151l1.321-2.284
c0.083-0.151,0.048-0.323-0.083-0.42L20.264,12.645z M15.352,14.475c-1.362,0-2.476-1.114-2.476-2.476s1.114-2.476,2.476-2.476
s2.476,1.114,2.476,2.476S16.714,14.475,15.352,14.475z"/>
<polygon fill="#6AE86D" points="15.038,11.998 10.063,9.868 10.063,11.123 2.167,11.123 2.167,12.873 10.063,12.873 10.063,14.128
"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

33
icons/log_delete.svg Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="LogDelete">
<g>
<rect x="5.401" y="4.061" fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linejoin="round" stroke-miterlimit="10" width="13.198" height="16.65"/>
<g>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="5.692" x2="16.986" y2="5.692"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="7.604" x2="16.986" y2="7.604"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="11.428" x2="16.986" y2="11.428"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="9.516" x2="16.986" y2="9.516"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="13.341" x2="16.986" y2="13.341"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="15.253" x2="16.986" y2="15.253"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="19.077" x2="16.986" y2="19.077"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="7.014" y1="17.165" x2="16.986" y2="17.165"/>
</g>
</g>
<path fill="#FF1313" d="M13.665,12.385l1.886-1.886c0.081-0.081,0.081-0.213,0-0.294L14.18,8.833c-0.078-0.078-0.216-0.078-0.294,0
L12,10.719l-1.886-1.886c-0.078-0.078-0.216-0.078-0.294,0l-1.372,1.372c-0.039,0.039-0.061,0.092-0.061,0.147
c0,0.055,0.022,0.108,0.061,0.147l1.886,1.886l-1.886,1.886c-0.039,0.039-0.061,0.092-0.061,0.147c0,0.055,0.022,0.108,0.061,0.147
l1.372,1.372c0.041,0.04,0.094,0.061,0.147,0.061s0.106-0.02,0.147-0.061L12,14.05l1.886,1.886c0.04,0.04,0.093,0.061,0.147,0.061
s0.106-0.02,0.147-0.061l1.371-1.371c0.081-0.081,0.081-0.213,0-0.294L13.665,12.385z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

38
icons/log_settings.svg Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="LogSettings">
<path fill="#FFFFFF" d="M22.016,5.822c0.014-0.103,0.021-0.209,0.021-0.322c0-0.109-0.007-0.219-0.024-0.322l0.695-0.541
c0.062-0.048,0.079-0.14,0.041-0.209l-0.657-1.136c-0.041-0.075-0.127-0.099-0.202-0.075l-0.818,0.328
c-0.171-0.13-0.352-0.239-0.554-0.322l-0.123-0.869c-0.014-0.082-0.082-0.14-0.164-0.14h-1.314c-0.082,0-0.147,0.058-0.161,0.14
l-0.123,0.869c-0.202,0.082-0.387,0.195-0.554,0.322L17.26,3.218c-0.075-0.027-0.161,0-0.202,0.075L16.405,4.43
c-0.041,0.072-0.027,0.161,0.041,0.209l0.695,0.541c-0.017,0.103-0.031,0.216-0.031,0.322c0,0.106,0.007,0.219,0.024,0.322
l-0.695,0.541c-0.062,0.048-0.079,0.14-0.041,0.209l0.657,1.136c0.041,0.075,0.127,0.099,0.202,0.075l0.818-0.328
c0.171,0.13,0.352,0.239,0.554,0.322l0.123,0.869c0.017,0.082,0.082,0.14,0.164,0.14h1.314c0.082,0,0.151-0.058,0.161-0.14
l0.123-0.869c0.202-0.082,0.387-0.192,0.554-0.322l0.818,0.328c0.075,0.027,0.161,0,0.202-0.075l0.657-1.136
c0.041-0.075,0.024-0.161-0.041-0.209L22.016,5.822z M19.573,6.732c-0.677,0-1.232-0.554-1.232-1.232s0.554-1.232,1.232-1.232
c0.677,0,1.232,0.554,1.232,1.232S20.25,6.732,19.573,6.732z"/>
<g>
<rect x="2.219" y="4.061" fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linejoin="round" stroke-miterlimit="10" width="13.198" height="16.65"/>
<g>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="5.692" x2="13.804" y2="5.692"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="7.604" x2="13.804" y2="7.604"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="11.428" x2="13.804" y2="11.428"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="9.516" x2="13.804" y2="9.516"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="13.341" x2="13.804" y2="13.341"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="15.253" x2="13.804" y2="15.253"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="19.077" x2="13.804" y2="19.077"/>
<line fill="none" stroke="#FFFFFF" stroke-width="0.4819" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.831" y1="17.165" x2="13.804" y2="17.165"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

27
icons/reset_database.svg Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="Reset_Database">
<g>
<ellipse fill="#FFFFFF" cx="12.103" cy="5.728" rx="7.505" ry="2.62"/>
<path fill="#FFFFFF" d="M19.051,7.533c-0.41,0.264-0.91,0.493-1.475,0.687c-1.517,0.521-3.5,0.787-5.473,0.787
c-1.973,0-3.957-0.267-5.473-0.787C6.065,8.026,5.565,7.797,5.155,7.533C4.945,7.398,4.757,7.254,4.598,7.1v3.578
c0.003,0.003,0.007,0.007,0.011,0.01c1.315,1.25,4.419,1.897,7.495,1.897c3.076,0,6.18-0.647,7.495-1.897
c0.001,0,0.001-0.001,0.002-0.001V7.109C19.441,7.259,19.257,7.4,19.051,7.533z"/>
<path fill="#FFFFFF" d="M19.051,11.937c-0.41,0.264-0.91,0.493-1.475,0.687c-1.517,0.521-3.5,0.787-5.473,0.787
c-1.973,0-3.957-0.267-5.473-0.787c-0.565-0.194-1.065-0.423-1.475-0.687c-0.21-0.135-0.397-0.28-0.557-0.433v3.578
c0.003,0.003,0.007,0.007,0.011,0.01c1.315,1.25,4.419,1.897,7.495,1.897c3.076,0,6.18-0.647,7.495-1.897
c0.001,0,0.001-0.001,0.002-0.001v-3.578C19.441,11.663,19.257,11.804,19.051,11.937z"/>
<path fill="#FFFFFF" d="M19.051,16.341c-0.41,0.264-0.91,0.493-1.475,0.687c-1.517,0.521-3.5,0.787-5.473,0.787
c-1.973,0-3.957-0.267-5.473-0.787c-0.565-0.194-1.065-0.423-1.475-0.687c-0.21-0.135-0.397-0.28-0.557-0.433v3.578
c0.003,0.003,0.007,0.007,0.011,0.01c1.315,1.25,4.419,1.897,7.495,1.897c3.076,0,6.18-0.647,7.495-1.897
c0.001,0,0.001-0.001,0.002-0.001v-3.578C19.441,16.067,19.257,16.209,19.051,16.341z"/>
</g>
<path fill="#FF1313" d="M13.709,13.832l1.886-1.886c0.081-0.081,0.081-0.213,0-0.294l-1.372-1.372
c-0.078-0.078-0.216-0.078-0.294,0l-1.886,1.886l-1.886-1.886c-0.078-0.078-0.216-0.078-0.294,0l-1.372,1.372
c-0.039,0.039-0.061,0.092-0.061,0.147c0,0.055,0.022,0.108,0.061,0.147l1.886,1.886l-1.886,1.886
c-0.039,0.039-0.061,0.092-0.061,0.147c0,0.055,0.022,0.108,0.061,0.147l1.372,1.372c0.041,0.04,0.094,0.061,0.147,0.061
s0.106-0.02,0.147-0.061l1.886-1.886l1.886,1.886c0.04,0.04,0.093,0.061,0.147,0.061s0.106-0.02,0.147-0.061l1.371-1.371
c0.081-0.081,0.081-0.213,0-0.294L13.709,13.832z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

47
icons/send_log.svg Normal file
View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="SendLog">
<g>
<polygon fill="none" points="9.135,15.969 14.871,15.969 16.301,14.539 7.705,14.539 "/>
<polygon fill="none" points="12,2.299 9.521,4.778 14.479,4.778 "/>
<polygon fill="none" points="16.362,19.891 13.247,18.109 10.756,18.107 5.915,20.877 4.3,21.801 19.699,21.801 "/>
<polygon fill="none" points="14.389,16.451 9.617,16.451 10.791,17.625 13.213,17.627 "/>
<polygon fill="none" points="3.634,21.627 6.173,20.174 10.299,17.813 5.24,12.755 5.227,12.742 3.634,11.149 "/>
<polygon fill="none" points="13.705,17.815 15.209,18.676 20.362,21.625 20.365,16.234 20.365,11.155 "/>
<polygon fill="none" points="20.27,10.57 18.84,9.142 18.84,12 "/>
<polygon fill="none" points="5.161,11.994 5.161,9.137 3.732,10.565 "/>
<path fill="none" d="M5.642,8.557v3.919l1.581,1.581h9.56l1.574-1.574V5.259H5.642v3.296C5.642,8.555,5.642,8.556,5.642,8.557z
M7.308,6.409h9.384c0.133,0,0.241,0.107,0.241,0.241S16.824,6.89,16.691,6.89H7.308c-0.133,0-0.241-0.107-0.241-0.241
S7.174,6.409,7.308,6.409z M7.014,8.321h9.973c0.133,0,0.241,0.107,0.241,0.241s-0.108,0.241-0.241,0.241H7.014
c-0.133,0-0.241-0.107-0.241-0.241S6.88,8.321,7.014,8.321z M7.014,10.233h9.973c0.133,0,0.241,0.107,0.241,0.241
s-0.108,0.241-0.241,0.241H7.014c-0.133,0-0.241-0.107-0.241-0.241S6.88,10.233,7.014,10.233z M7.014,12.145h9.973
c0.133,0,0.241,0.107,0.241,0.241c0,0.133-0.108,0.241-0.241,0.241H7.014c-0.133,0-0.241-0.108-0.241-0.241
C6.773,12.252,6.88,12.145,7.014,12.145z"/>
<path fill="#FFFFFF" d="M7.014,8.802h9.973c0.133,0,0.241-0.107,0.241-0.241s-0.108-0.241-0.241-0.241H7.014
c-0.133,0-0.241,0.107-0.241,0.241S6.88,8.802,7.014,8.802z"/>
<path fill="#FFFFFF" d="M7.014,6.89h9.973c0.133,0,0.241-0.107,0.241-0.241s-0.108-0.241-0.241-0.241H7.014
c-0.133,0-0.241,0.107-0.241,0.241S6.88,6.89,7.014,6.89z"/>
<path fill="#FFFFFF" d="M7.014,12.627h9.973c0.133,0,0.241-0.108,0.241-0.241c0-0.133-0.108-0.241-0.241-0.241H7.014
c-0.133,0-0.241,0.107-0.241,0.241C6.773,12.519,6.88,12.627,7.014,12.627z"/>
<path fill="#FFFFFF" d="M7.014,10.714h9.973c0.133,0,0.241-0.107,0.241-0.241s-0.108-0.241-0.241-0.241H7.014
c-0.133,0-0.241,0.107-0.241,0.241S6.88,10.714,7.014,10.714z"/>
<path fill="#FFFFFF" d="M20.848,16.305l0.003-5.737c0-0.015-0.014-0.026-0.017-0.041c-0.008-0.037-0.019-0.071-0.042-0.1
c-0.007-0.009-0.004-0.022-0.012-0.03L18.84,8.462V5.019c0-0.133-0.108-0.241-0.241-0.241H15.16l-2.99-2.99
c-0.094-0.094-0.247-0.094-0.341,0l-2.991,2.99H5.401c-0.133,0-0.241,0.107-0.241,0.241v3.437l-1.94,1.94
c-0.006,0.007-0.004,0.017-0.01,0.025c-0.026,0.033-0.041,0.071-0.047,0.114c-0.002,0.012-0.013,0.02-0.013,0.032v11.476
c0,0.008,0.008,0.012,0.008,0.02c0,0.006,0.003,0.01,0.004,0.016c0.001,0.009-0.004,0.017-0.002,0.026
c0.002,0.009,0.011,0.013,0.014,0.021c0.009,0.023,0.02,0.043,0.035,0.062c0.01,0.012,0.016,0.022,0.028,0.032
c0.007,0.007,0.014,0.012,0.022,0.018c0.005,0.003,0.007,0.01,0.013,0.013c0.035,0.021,0.074,0.029,0.112,0.031
c0.002,0,0.003,0.002,0.006,0.002h0.003h17.21h0.003c0.042,0,0.084-0.011,0.121-0.033c0.005-0.003,0.008-0.009,0.013-0.013
c0.009-0.006,0.016-0.013,0.024-0.021c0.007-0.006,0.01-0.012,0.016-0.019c0.02-0.022,0.035-0.046,0.046-0.074
c0.003-0.008,0.011-0.012,0.013-0.02c0.002-0.008-0.003-0.015-0.002-0.023c0.002-0.013,0.01-0.025,0.01-0.038V16.305z
M5.227,12.742c0.005,0.005,0.008,0.009,0.013,0.013l5.059,5.058l-4.125,2.361l-2.539,1.453V11.149L5.227,12.742z M20.365,11.155
v5.079l-0.003,5.39l-5.153-2.948l-1.504-0.861L20.365,11.155z M10.791,17.625l-1.174-1.174h4.771l-1.176,1.176L10.791,17.625z
M14.871,15.969H9.135l-1.43-1.43h8.596L14.871,15.969z M5.915,20.877l4.841-2.769l2.491,0.002l3.115,1.782l3.338,1.91H4.3
L5.915,20.877z M20.27,10.57L18.84,12V9.142L20.27,10.57z M12,2.299l2.479,2.479H9.521L12,2.299z M18.357,5.259v7.223
l-1.574,1.574h-9.56l-1.581-1.581V8.557c0-0.001,0-0.001,0-0.002V5.259H18.357z M5.161,11.994l-1.429-1.429l1.429-1.428V11.994z"
/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -8,7 +8,7 @@
android:title="@string/medtronic_name" android:title="@string/medtronic_name"
app:initialExpandedChildrenCount="0"> app:initialExpandedChildrenCount="0">
<EditTextPreference <info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
android:defaultValue="000000" android:defaultValue="000000"
android:key="@string/key_medtronic_serial" android:key="@string/key_medtronic_serial"
android:selectAllOnFocus="true" android:selectAllOnFocus="true"
@ -33,7 +33,7 @@
android:selectable="true" android:selectable="true"
android:title="@string/medtronic_pump_frequency" /> android:title="@string/medtronic_pump_frequency" />
<EditTextPreference <info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
android:defaultValue="35" android:defaultValue="35"
android:digits="0123456789." android:digits="0123456789."
android:inputType="number" android:inputType="number"
@ -45,7 +45,7 @@
validate:minNumber="1" validate:minNumber="1"
validate:testType="numericRange" /> validate:testType="numericRange" />
<EditTextPreference <info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
android:defaultValue="25" android:defaultValue="25"
android:digits="0123456789." android:digits="0123456789."
android:inputType="number" android:inputType="number"

View file

@ -1,14 +1,14 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data package info.nightscout.androidaps.plugins.pump.medtronic.data
import java.lang.reflect.Type
import com.google.gson.reflect.TypeToken
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.internal.LinkedTreeMap import com.google.gson.internal.LinkedTreeMap
// import dagger.android.AndroidInjector import com.google.gson.reflect.TypeToken
// import dagger.android.HasAndroidInjector import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder
@ -16,13 +16,12 @@ import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpH
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.sharedPreferences.SP import info.nightscout.shared.sharedPreferences.SP
import org.junit.Test import org.junit.Test
import org.mockito.Mock import org.mockito.Mock
import java.lang.reflect.Type
class MedtronicHistoryDataUTest : TestBase() { @Suppress("UNCHECKED_CAST") class MedtronicHistoryDataUTest : TestBase() {
//@Mock lateinit var activePlugin: ActivePlugin //@Mock lateinit var activePlugin: ActivePlugin
//@Mock lateinit var medtronicUtil: MedtronicUtil //@Mock lateinit var medtronicUtil: MedtronicUtil
@ -39,15 +38,16 @@ class MedtronicHistoryDataUTest : TestBase() {
// } // }
// } // }
@Test @Test
fun createTBRProcessList() { fun createTBRProcessList() {
var unitToTest = MedtronicHistoryData(packetInjector, aapsLogger, sp, rh, rxBus, activePlugin, val unitToTest = MedtronicHistoryData(
medtronicUtil, decoder, packetInjector, aapsLogger, sp, rh, rxBus, activePlugin,
medtronicPumpStatus, medtronicUtil, decoder,
pumpSync, medtronicPumpStatus,
pumpSyncStorage) pumpSync,
pumpSyncStorage
)
val gson = Gson() val gson = Gson()
@ -57,26 +57,26 @@ class MedtronicHistoryDataUTest : TestBase() {
val yourClassList: MutableList<PumpHistoryEntry> = gson.fromJson(fileText, listType) val yourClassList: MutableList<PumpHistoryEntry> = gson.fromJson(fileText, listType)
for (pumpHistoryEntry in yourClassList) { for (pumpHistoryEntry in yourClassList) {
val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap<String,Object> val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap<String, Any>
val rate : Double = stringObject.get("insulinRate") as Double val rate: Double = stringObject["insulinRate"] as Double
val durationMinutes: Double = stringObject.get("durationMinutes") as Double val durationMinutes: Double = stringObject["durationMinutes"] as Double
val durationMinutesInt : Int = durationMinutes.toInt() val durationMinutesInt: Int = durationMinutes.toInt()
var tmbPair = TempBasalPair(rate, false, durationMinutesInt) val tmbPair = TempBasalPair(rate, false, durationMinutesInt)
pumpHistoryEntry.decodedData.remove("Object") pumpHistoryEntry.decodedData.remove("Object")
pumpHistoryEntry.addDecodedData("Object", tmbPair) pumpHistoryEntry.addDecodedData("Object", tmbPair)
} }
System.out.println("TBR Pre-Process List: " + gson.toJson(yourClassList)) println("TBR Pre-Process List: " + gson.toJson(yourClassList))
val createTBRProcessList = unitToTest.createTBRProcessList(yourClassList, mutableListOf()) val createTBRProcessList = unitToTest.createTBRProcessList(yourClassList, mutableListOf())
System.out.println("TBR Process List: " + createTBRProcessList.size) println("TBR Process List: " + createTBRProcessList.size)
for (tempBasalProcessDTO in createTBRProcessList) { for (tempBasalProcessDTO in createTBRProcessList) {
System.out.println(tempBasalProcessDTO.toTreatmentString()) println(tempBasalProcessDTO.toTreatmentString())
} }
} }
@ -84,11 +84,13 @@ class MedtronicHistoryDataUTest : TestBase() {
@Test @Test
fun createTBRProcessList_SpecialCase() { fun createTBRProcessList_SpecialCase() {
var unitToTest = MedtronicHistoryData(packetInjector, aapsLogger, sp, rh, rxBus, activePlugin, val unitToTest = MedtronicHistoryData(
medtronicUtil, decoder, packetInjector, aapsLogger, sp, rh, rxBus, activePlugin,
medtronicPumpStatus, medtronicUtil, decoder,
pumpSync, medtronicPumpStatus,
pumpSyncStorage) pumpSync,
pumpSyncStorage
)
val gson = Gson() val gson = Gson()
@ -98,26 +100,26 @@ class MedtronicHistoryDataUTest : TestBase() {
val yourClassList: MutableList<PumpHistoryEntry> = gson.fromJson(fileText, listType) val yourClassList: MutableList<PumpHistoryEntry> = gson.fromJson(fileText, listType)
for (pumpHistoryEntry in yourClassList) { for (pumpHistoryEntry in yourClassList) {
val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap<String,Object> val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap<String, Any>
val rate : Double = stringObject.get("insulinRate") as Double val rate: Double = stringObject["insulinRate"] as Double
val durationMinutes: Double = stringObject.get("durationMinutes") as Double val durationMinutes: Double = stringObject["durationMinutes"] as Double
val durationMinutesInt : Int = durationMinutes.toInt() val durationMinutesInt: Int = durationMinutes.toInt()
var tmbPair = TempBasalPair(rate, false, durationMinutesInt) val tmbPair = TempBasalPair(rate, false, durationMinutesInt)
pumpHistoryEntry.decodedData.remove("Object") pumpHistoryEntry.decodedData.remove("Object")
pumpHistoryEntry.addDecodedData("Object", tmbPair) pumpHistoryEntry.addDecodedData("Object", tmbPair)
} }
System.out.println("TBR Pre-Process List (Special): " + gson.toJson(yourClassList)) println("TBR Pre-Process List (Special): " + gson.toJson(yourClassList))
val createTBRProcessList = unitToTest.createTBRProcessList(yourClassList, mutableListOf()) val createTBRProcessList = unitToTest.createTBRProcessList(yourClassList, mutableListOf())
System.out.println("TBR Process List (Special): " + createTBRProcessList.size) println("TBR Process List (Special): " + createTBRProcessList.size)
for (tempBasalProcessDTO in createTBRProcessList) { for (tempBasalProcessDTO in createTBRProcessList) {
System.out.println(tempBasalProcessDTO.toTreatmentString()) println(tempBasalProcessDTO.toTreatmentString())
} }
} }

View file

@ -10,7 +10,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.Das
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao 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.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper
import info.nightscout.shared.logging.AAPSLoggerTest import info.nightscout.shared.logging.AAPSLoggerTest
import io.reactivex.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
@ -44,9 +44,9 @@ class DashHistoryTest {
assertValue { it.isEmpty() } assertValue { it.isEmpty() }
} }
dashHistory.createRecord(commandType = OmnipodCommandType.CANCEL_BOLUS, 0L).test().apply { // dashHistory.createRecord(commandType = OmnipodCommandType.CANCEL_BOLUS, 0L).test().apply {
assertValue { ULID.isValid(it) } // assertValue { ULID.isValid(it) }
} // }
dashHistory.getRecords().test().apply { dashHistory.getRecords().test().apply {
assertValue { it.size == 1 } assertValue { it.size == 1 }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.history package info.nightscout.androidaps.plugins.pump.omnipod.dash.history
import io.reactivex.Scheduler import io.reactivex.rxjava3.android.plugins.RxAndroidPlugins
import io.reactivex.android.plugins.RxAndroidPlugins import io.reactivex.rxjava3.core.Scheduler
import io.reactivex.plugins.RxJavaPlugins import io.reactivex.rxjava3.plugins.RxJavaPlugins
import org.junit.rules.TestRule import org.junit.rules.TestRule
import org.junit.runner.Description import org.junit.runner.Description
import org.junit.runners.model.Statement import org.junit.runners.model.Statement

View file

@ -16,7 +16,6 @@ class MessagePacketTest {
) )
@Test fun testParseMessagePacket() { @Test fun testParseMessagePacket() {
val aapsLogger = AAPSLoggerTest()
val msg = MessagePacket.parse(Hex.decode(payload)) val msg = MessagePacket.parse(Hex.decode(payload))
assertEquals(msg.type, MessageType.ENCRYPTED) assertEquals(msg.type, MessageType.ENCRYPTED)
assertEquals(msg.source, Id.fromLong(136326824)) assertEquals(msg.source, Id.fromLong(136326824))

View file

@ -8,6 +8,7 @@ import org.junit.Assert
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
@Suppress("DEPRECATION")
class ProgramBasalCommandTest { class ProgramBasalCommandTest {
@Test @Throws(DecoderException::class) fun testProgramBasalCommand() { @Test @Throws(DecoderException::class) fun testProgramBasalCommand() {

View file

@ -44,11 +44,11 @@ class ErosHistoryTest {
history = erosHistory.getAllErosHistoryRecordsFromTimestamp(0L) history = erosHistory.getAllErosHistoryRecordsFromTimestamp(0L)
assert(history.size == 2) assert(history.size == 2)
assert(type.equals(history.first().podEntryTypeCode)) assert(type == history.first().podEntryTypeCode)
val returnedEntity = erosHistory.findErosHistoryRecordByPumpId(entity.pumpId) val returnedEntity = erosHistory.findErosHistoryRecordByPumpId(entity.pumpId)
assertNotNull(returnedEntity) assertNotNull(returnedEntity)
assert(type.equals(returnedEntity.podEntryTypeCode)) assert(type == returnedEntity?.podEntryTypeCode)
} }
@After @After

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.message.defs.schedule; package info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.message.defs.schedule;
import static org.junit.Assert.assertEquals;
import org.junit.Test; import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.schedule.BasalTableEntry; import info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.schedule.BasalTableEntry;
import static junit.framework.Assert.assertEquals;
public class BasalTableEntryTest { public class BasalTableEntryTest {
@Test @Test
public void testChecksum() { public void testChecksum() {

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.message.response.podinfo; package info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.communication.message.response.podinfo;
import org.junit.Assert;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
@ -12,9 +13,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
public class PodInfoResponseTest { public class PodInfoResponseTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test @Test
public void testRawData() { public void testRawData() {
byte[] encodedData = ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d"); byte[] encodedData = ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d");
@ -51,7 +49,8 @@ public class PodInfoResponseTest {
assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType()); assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType());
thrown.expect(ClassCastException.class); Assert.assertThrows("Expect throw", ClassCastException.class, () -> {
PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo(); PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo();
});
} }
} }

View file

@ -85,10 +85,12 @@ private val allowedKeys = """
nsalarm_staledatavalue nsalarm_staledatavalue
nsalarm_urgent_staledata nsalarm_urgent_staledata
nsalarm_urgent_staledatavalue nsalarm_urgent_staledatavalue
ns_wifionly
ns_wifi_ssids ns_wifi_ssids
ns_allowroaming ns_cellular
ns_chargingonly ns_wifi
ns_allow_roaming
ns_battery
ns_charging
ns_autobackfill ns_autobackfill
ns_create_announcements_from_errors ns_create_announcements_from_errors
nsclient_localbroadcasts nsclient_localbroadcasts

View file

@ -187,8 +187,7 @@ public class PlusMinusEditText implements View.OnKeyListener,
public boolean onKey(View v, int keyCode, KeyEvent event) { public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER; boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER;
boolean isReleased = event.getAction() == KeyEvent.ACTION_UP; boolean isReleased = event.getAction() == KeyEvent.ACTION_UP;
boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN;
&& event.getAction() != KeyEvent.ACTION_MULTIPLE;
if (isKeyOfInterest && isReleased) { if (isKeyOfInterest && isReleased) {
stopUpdating(); stopUpdating();

View file

@ -1,14 +1,9 @@
package info.nightscout.androidaps.testing.mockers package info.nightscout.androidaps.testing.mockers
import android.os.Bundle
import com.google.android.gms.wearable.Asset
import com.google.android.gms.wearable.DataMap
import info.nightscout.androidaps.interaction.utils.Constants import info.nightscout.androidaps.interaction.utils.Constants
import info.nightscout.androidaps.interaction.utils.WearUtil import info.nightscout.androidaps.interaction.utils.WearUtil
import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers
import org.mockito.Mockito import org.mockito.Mockito
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
class WearUtilMocker(private val wearUtil: WearUtil) { class WearUtilMocker(private val wearUtil: WearUtil) {
@ -23,11 +18,11 @@ class WearUtilMocker(private val wearUtil: WearUtil) {
fun prepareMockNoReal() { fun prepareMockNoReal() {
resetClock() resetClock()
Mockito.doAnswer { invocation: InvocationOnMock? -> REF_NOW + clockMsDiff }.`when`(wearUtil).timestamp() Mockito.doAnswer { REF_NOW + clockMsDiff }.`when`(wearUtil).timestamp()
Mockito.doReturn(null).`when`(wearUtil).getWakeLock(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()) Mockito.doReturn(null).`when`(wearUtil).getWakeLock(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())
} }
fun resetClock() { private fun resetClock() {
clockMsDiff = 0L clockMsDiff = 0L
} }
@ -35,50 +30,10 @@ class WearUtilMocker(private val wearUtil: WearUtil) {
clockMsDiff += byMilliseconds clockMsDiff += byMilliseconds
} }
fun setClock(atMillisecondsSinceEpoch: Long) {
clockMsDiff = atMillisecondsSinceEpoch - REF_NOW
}
fun backInTime(d: Int, h: Int, m: Int, s: Int): Long { fun backInTime(d: Int, h: Int, m: Int, s: Int): Long {
return REF_NOW - (Constants.DAY_IN_MS * d + Constants.HOUR_IN_MS * h + Constants.MINUTE_IN_MS * m + Constants.SECOND_IN_MS * s) return REF_NOW - (Constants.DAY_IN_MS * d + Constants.HOUR_IN_MS * h + Constants.MINUTE_IN_MS * m + Constants.SECOND_IN_MS * s)
} }
@Suppress("UNCHECKED_CAST")
private val bundleToDataMapMock: Answer<*> = Answer { invocation: InvocationOnMock ->
val map = DataMap()
val bundle = invocation.getArgument<Bundle>(0)
for (key in bundle.keySet()) {
val v = bundle[key]
if (v is Asset) map.putAsset(key, v)
if (v is Boolean) map.putBoolean(key, v)
if (v is Byte) map.putByte(key, (v as Byte?)!!)
if (v is ByteArray) map.putByteArray(key, v)
if (v is DataMap) map.putDataMap(key, v)
if (v is Double) map.putDouble(key, v)
if (v is Float) map.putFloat(key, (v as Float))
if (v is FloatArray) map.putFloatArray(key, v)
if (v is Int) map.putInt(key, v)
if (v is Long) map.putLong(key, v)
if (v is LongArray) map.putLongArray(key, v)
if (v is String) map.putString(key, v)
if (v is Array<*>) map.putStringArray(key, v as Array<String>)
if (v is ArrayList<*>) {
if (v.isNotEmpty()) {
if (v[0] is Int) {
map.putIntegerArrayList(key, v as ArrayList<Int>)
}
if (v[0] is String) {
map.putStringArrayList(key, v as ArrayList<String>)
}
if (v[0] is DataMap) {
map.putDataMapArrayList(key, v as ArrayList<DataMap>)
}
}
}
}
map
}
companion object { companion object {
const val REF_NOW = 1572610530000L const val REF_NOW = 1572610530000L