Merge branch 'nightscout:dev' into dev
This commit is contained in:
commit
a3577304ba
280 changed files with 6165 additions and 877 deletions
|
@ -5,7 +5,7 @@ version: 2.1
|
|||
# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
|
||||
orbs:
|
||||
android: circleci/android@1.0.3
|
||||
codecov: codecov/codecov@1.2.0
|
||||
codecov: codecov/codecov@3.2.4
|
||||
|
||||
jobs:
|
||||
# Below is the definition of your job to build and test your app, you can rename and customize it as you want.
|
||||
|
@ -45,4 +45,4 @@ workflows:
|
|||
# For more details on extending your workflow, see the configuration docs: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
||||
dotests:
|
||||
jobs:
|
||||
- build-and-test
|
||||
- build-and-test
|
||||
|
|
|
@ -3,6 +3,7 @@ package info.nightscout.rx.weardata
|
|||
import info.nightscout.rx.events.Event
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.joda.time.DateTime
|
||||
import java.util.Objects
|
||||
|
||||
@Serializable
|
||||
|
@ -90,6 +91,16 @@ sealed class EventData : Event() {
|
|||
@Serializable
|
||||
data class ActionQuickWizardPreCheck(val guid: String) : EventData()
|
||||
|
||||
@Serializable
|
||||
data class ActionHeartRate(
|
||||
val duration: Long,
|
||||
val timestamp: Long,
|
||||
val beatsPerMinute: Double,
|
||||
val device: String): EventData() {
|
||||
override fun toString() =
|
||||
"HR ${beatsPerMinute.toInt()} at ${DateTime(timestamp)} for ${duration / 1000.0}sec $device"
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ActionTempTargetPreCheck(
|
||||
val command: TempTargetCommand,
|
||||
|
|
|
@ -16,8 +16,12 @@ fun PackageManager.safeGetInstalledPackages(flags: Int): List<PackageInfo> =
|
|||
* Safe version of queryBroadcastReceivers depending on Android version running
|
||||
*/
|
||||
fun PackageManager.safeQueryBroadcastReceivers(intent: Intent, flags: Int): List<ResolveInfo> =
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) queryBroadcastReceivers(intent, PackageManager.ResolveInfoFlags.of(flags.toLong()))
|
||||
else @Suppress("DEPRECATION") queryBroadcastReceivers(intent, flags)
|
||||
try {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) queryBroadcastReceivers(intent, PackageManager.ResolveInfoFlags.of(flags.toLong()))
|
||||
else @Suppress("DEPRECATION") queryBroadcastReceivers(intent, flags)
|
||||
} catch (ignored: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe version of getPackageInfo depending on Android version running
|
||||
|
|
|
@ -16,8 +16,6 @@ import androidx.annotation.RawRes
|
|||
import androidx.annotation.StringRes
|
||||
|
||||
interface ResourceHelper {
|
||||
fun updateContext(ctx: Context?)
|
||||
|
||||
fun gs(@StringRes id: Int): String
|
||||
fun gs(@StringRes id: Int, vararg args: Any?): String
|
||||
fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String
|
||||
|
|
|
@ -111,7 +111,7 @@ android {
|
|||
defaultConfig {
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "3.2.0-dev-i"
|
||||
version "3.2.0-dev-j"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.widget.TextView
|
|||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
|
@ -302,7 +303,7 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
menu.setGroupDividerEnabled(true)
|
||||
MenuCompat.setGroupDividerEnabled(menu, true)
|
||||
this.menu = menu
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
||||
|
@ -477,4 +478,4 @@ class MainActivity : DaggerAppCompatActivityWithResult() {
|
|||
ToastUtils.okToast(context, context.getString(info.nightscout.core.ui.R.string.password_set))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,9 +11,9 @@ import android.widget.TextView
|
|||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import dagger.android.HasAndroidInjector
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.androidaps.databinding.ActivityHistorybrowseBinding
|
||||
import info.nightscout.core.events.EventIobCalculationProgress
|
||||
import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.core.workflow.CalculationWorkflow
|
||||
import info.nightscout.interfaces.Config
|
||||
|
@ -42,7 +42,7 @@ import java.util.GregorianCalendar
|
|||
import javax.inject.Inject
|
||||
import kotlin.math.min
|
||||
|
||||
class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
||||
class HistoryBrowseActivity : TranslatedDaggerAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var historyBrowserData: HistoryBrowserData
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
|
@ -327,6 +327,7 @@ class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
|||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useBGIForScale = false
|
||||
var useHRForScale = false
|
||||
when {
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
|
@ -335,6 +336,7 @@ class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] -> useHRForScale = true
|
||||
}
|
||||
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||
|
||||
|
@ -345,6 +347,7 @@ class HistoryBrowseActivity : DaggerAppCompatActivity() {
|
|||
if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(useRatioForScale, if (useRatioForScale) 1.0 else 0.8)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && config.isDev()) secondGraphData.addDeviationSlope(useDSForScale, 1.0)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] && config.isDev()) secondGraphData.addHeartRate(useHRForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(historyBrowserData.overviewData.fromTime, historyBrowserData.overviewData.endTime)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
|
@ -10,7 +9,6 @@ import androidx.preference.PreferenceScreen
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.databinding.ActivityPreferencesBinding
|
||||
import info.nightscout.configuration.activities.DaggerAppCompatActivityWithResult
|
||||
import info.nightscout.core.ui.locale.LocaleHelper
|
||||
|
||||
class PreferencesActivity : DaggerAppCompatActivityWithResult(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
|
||||
|
||||
|
@ -66,10 +64,6 @@ class PreferencesActivity : DaggerAppCompatActivityWithResult(), PreferenceFragm
|
|||
return true
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
|
|
|
@ -191,7 +191,7 @@ class KeepAliveWorker(
|
|||
}
|
||||
if (loop.isDisconnected) {
|
||||
// do nothing if pump is disconnected
|
||||
} else if (runningProfile == null || ((!pump.isThisProfileSet(requestedProfile) || !requestedProfile.isEqual(runningProfile)) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE))) {
|
||||
} else if (runningProfile == null || ((!pump.isThisProfileSet(requestedProfile) || !requestedProfile.isEqual(runningProfile) || (runningProfile is ProfileSealed.EPS && runningProfile.value.originalEnd < dateUtil.now())) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE))) {
|
||||
rxBus.send(EventProfileSwitchChanged())
|
||||
} else if (isStatusOutdated && !pump.isBusy()) {
|
||||
lastReadStatus = now
|
||||
|
|
40
build.gradle
40
build.gradle
|
@ -2,40 +2,40 @@
|
|||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.8.10'
|
||||
core_version = '1.9.0'
|
||||
kotlin_version = '1.8.22'
|
||||
core_version = '1.10.1'
|
||||
rxjava_version = '3.1.6'
|
||||
rxandroid_version = '3.0.2'
|
||||
rxkotlin_version = '3.0.1'
|
||||
room_version = '2.5.0'
|
||||
lifecycle_version = '2.5.1'
|
||||
dagger_version = '2.45'
|
||||
coroutines_version = '1.6.4'
|
||||
activity_version = '1.6.1'
|
||||
fragmentktx_version = '1.5.5'
|
||||
room_version = '2.5.2'
|
||||
lifecycle_version = '2.6.1'
|
||||
dagger_version = '2.46.1'
|
||||
coroutines_version = '1.7.1'
|
||||
activity_version = '1.7.2'
|
||||
fragmentktx_version = '1.6.0'
|
||||
ormLite_version = '4.46'
|
||||
gson_version = '2.10.1'
|
||||
nav_version = '2.5.3'
|
||||
nav_version = '2.6.0'
|
||||
appcompat_version = '1.6.1'
|
||||
material_version = '1.8.0'
|
||||
material_version = '1.9.0'
|
||||
gridlayout_version = '1.0.0'
|
||||
constraintlayout_version = '2.1.4'
|
||||
preferencektx_version = '1.2.0'
|
||||
commonslang3_version = '3.12.0'
|
||||
commonscodec_version = '1.15'
|
||||
commonscodec_version = '1.16.0'
|
||||
jodatime_version = '2.10.14'
|
||||
work_version = '2.8.0'
|
||||
tink_version = '1.8.0'
|
||||
work_version = '2.8.1'
|
||||
tink_version = '1.9.0'
|
||||
json_version = '20220320'
|
||||
joda_version = '2.12.1.1'
|
||||
joda_version = '2.12.5'
|
||||
swipe_version = '1.1.0'
|
||||
|
||||
junit_version = '4.13.2'
|
||||
junit_jupiter_version = '5.9.2'
|
||||
junit_jupiter_version = '5.9.3'
|
||||
mockito_version = '4.6.1'
|
||||
dexmaker_version = '1.2'
|
||||
retrofit2_version = '2.9.0'
|
||||
okhttp3_version = '4.10.0'
|
||||
okhttp3_version = '4.11.0'
|
||||
byteBuddy_version = '1.12.8'
|
||||
|
||||
androidx_junit_version = '1.1.4'
|
||||
|
@ -49,7 +49,7 @@ buildscript {
|
|||
play_services_location_version = '21.0.1'
|
||||
|
||||
kotlinx_datetime_version = '0.4.0'
|
||||
kotlinx_serialization_version = '1.5.0'
|
||||
kotlinx_serialization_version = '1.5.1'
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
|
@ -58,8 +58,8 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
classpath 'com.google.gms:google-services:4.3.14'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.4'
|
||||
classpath 'com.google.gms:google-services:4.3.15'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.6'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
@ -75,7 +75,7 @@ buildscript {
|
|||
plugins {
|
||||
// Test Gradle build, keep disabled under normal circumstances
|
||||
// id "com.osacky.doctor" version "0.8.1"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.3.1"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "11.4.2"
|
||||
id 'org.barfuin.gradle.jacocolog' version '3.1.0'
|
||||
id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
|
||||
}
|
||||
|
|
|
@ -150,4 +150,7 @@ interface OverviewData {
|
|||
val dsMinScale: Scale
|
||||
var dsMaxSeries: LineGraphSeries<ScaledDataPoint>
|
||||
var dsMinSeries: LineGraphSeries<ScaledDataPoint>
|
||||
}
|
||||
var heartRateScale: Scale
|
||||
var heartRateGraphSeries: LineGraphSeries<DataPointWithLabelInterface>
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
||||
class HeartRateDataPoint(
|
||||
private val data: HeartRate,
|
||||
private val rh: ResourceHelper,
|
||||
) : DataPointWithLabelInterface {
|
||||
|
||||
override fun getX(): Double = (data.timestamp - data.duration).toDouble()
|
||||
override fun getY(): Double = data.beatsPerMinute
|
||||
override fun setY(y: Double) {}
|
||||
|
||||
override val label: String = ""
|
||||
override val duration = data.duration
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.HEARTRATE
|
||||
override val size = 1f
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL
|
||||
|
||||
override fun color(context: Context?): Int = rh.gac(context, info.nightscout.core.ui.R.attr.heartRateColor)
|
||||
}
|
|
@ -54,7 +54,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
GENERAL_WITH_DURATION,
|
||||
COB_FAIL_OVER,
|
||||
IOB_PREDICTION,
|
||||
BUCKETED_BG
|
||||
BUCKETED_BG,
|
||||
HEARTRATE,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,6 +325,10 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
mPaint.setStrokeWidth(5);
|
||||
canvas.drawRect(endX - 3, bounds.top + py - 3, xPlusLength + 3, bounds.bottom + py + 3, mPaint);
|
||||
}
|
||||
} else if (value.getShape() == Shape.HEARTRATE) {
|
||||
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, 1F, mPaint);
|
||||
}
|
||||
// set values above point
|
||||
}
|
||||
|
|
|
@ -7,5 +7,6 @@ interface APS {
|
|||
var lastDetermineBasalAdapter: DetermineBasalAdapter?
|
||||
var lastAutosensResult: AutosensResult
|
||||
|
||||
operator fun invoke(initiator: String, tempBasalFallback: Boolean)
|
||||
fun isEnabled(): Boolean
|
||||
fun invoke(initiator: String, tempBasalFallback: Boolean)
|
||||
}
|
|
@ -15,7 +15,8 @@ interface OverviewMenus {
|
|||
BGI,
|
||||
SEN,
|
||||
ACT,
|
||||
DEVSLOPE
|
||||
DEVSLOPE,
|
||||
HR,
|
||||
}
|
||||
|
||||
val setting: List<Array<Boolean>>
|
||||
|
@ -23,4 +24,4 @@ interface OverviewMenus {
|
|||
fun setupChartMenu(context: Context, chartButton: ImageButton)
|
||||
fun enabledTypes(graph: Int): String
|
||||
fun isEnabledIn(type: CharType): Int
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ interface CommandQueue {
|
|||
fun extendedBolus(insulin: Double, durationInMinutes: Int, callback: Callback?): Boolean
|
||||
fun cancelTempBasal(enforceNew: Boolean, callback: Callback?): Boolean
|
||||
fun cancelExtended(callback: Callback?): Boolean
|
||||
fun setProfile(profile: Profile, hasNsId: Boolean, callback: Callback?): Boolean
|
||||
fun readStatus(reason: String, callback: Callback?): Boolean
|
||||
fun statusInQueue(): Boolean
|
||||
fun loadHistory(type: Byte, callback: Callback?): Boolean
|
||||
|
|
|
@ -23,7 +23,7 @@ dependencies {
|
|||
|
||||
api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
||||
api 'com.google.guava:guava:31.1-jre'
|
||||
api 'com.google.guava:guava:32.0.1-jre'
|
||||
|
||||
api "androidx.activity:activity-ktx:$activity_version"
|
||||
api "androidx.appcompat:appcompat:$appcompat_version"
|
||||
|
|
|
@ -292,14 +292,11 @@ class NSAndroidClientImpl(
|
|||
lastModified = response.body()?.lastModified
|
||||
)
|
||||
} else throw UnknownResponseNightscoutException()
|
||||
} else if (response.code() in 400..499) {
|
||||
return@callWrapper CreateUpdateResponse(
|
||||
response = response.code(),
|
||||
identifier = null,
|
||||
errorResponse = response.errorBody()?.string() ?: response.message()
|
||||
)
|
||||
} else
|
||||
throw UnsuccessfullNightscoutException(response.errorBody()?.string() ?: response.message())
|
||||
} else return@callWrapper CreateUpdateResponse(
|
||||
response = response.code(),
|
||||
identifier = null,
|
||||
errorResponse = response.errorBody()?.string() ?: response.message()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
|
||||
|
|
|
@ -45,7 +45,7 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? {
|
|||
subject = this.subject,
|
||||
isReadOnly = this.isReadOnly ?: false,
|
||||
isValid = this.isValid ?: true,
|
||||
eventType = this.eventType,
|
||||
eventType = this.eventType ?: EventType.MEAL_BOLUS,
|
||||
notes = this.notes,
|
||||
pumpId = this.pumpId,
|
||||
endId = this.endId,
|
||||
|
@ -68,7 +68,7 @@ internal fun RemoteTreatment.toTreatment(): NSTreatment? {
|
|||
subject = this.subject,
|
||||
isReadOnly = this.isReadOnly ?: false,
|
||||
isValid = this.isValid ?: true,
|
||||
eventType = this.eventType,
|
||||
eventType = this.eventType ?: EventType.CARBS_CORRECTION,
|
||||
notes = this.notes,
|
||||
pumpId = this.pumpId,
|
||||
endId = this.endId,
|
||||
|
|
|
@ -29,7 +29,7 @@ internal data class RemoteTreatment(
|
|||
@SerializedName("modifiedBy") val modifiedBy: String? = null, // string Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server.
|
||||
@SerializedName("isValid") val isValid: Boolean? = null, // boolean A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value)
|
||||
@SerializedName("isReadOnly") val isReadOnly: Boolean? = null, // boolean A flag set by client that locks the document from any changes. Every document marked with isReadOnly=true is forever immutable and cannot even be deleted.
|
||||
@SerializedName("eventType") val eventType: EventType, // string "BG Check", "Snack Bolus", "Meal Bolus", "Correction Bolus", "Carb Correction", "Combo Bolus", "Announcement", "Note", "Question", "Exercise", "Site Change", "Sensor Start", "Sensor Change", "Pump Battery Change", "Insulin Change", "Temp Basal", "Profile Switch", "D.A.D. Alert", "Temporary Target", "OpenAPS Offline", "Bolus Wizard"
|
||||
@SerializedName("eventType") val eventType: EventType?, // string "BG Check", "Snack Bolus", "Meal Bolus", "Correction Bolus", "Carb Correction", "Combo Bolus", "Announcement", "Note", "Question", "Exercise", "Site Change", "Sensor Start", "Sensor Change", "Pump Battery Change", "Insulin Change", "Temp Basal", "Profile Switch", "D.A.D. Alert", "Temporary Target", "OpenAPS Offline", "Bolus Wizard"
|
||||
@SerializedName("glucose") val glucose: Double? = null, // double Current glucose
|
||||
@SerializedName("glucoseType") val glucoseType: String? = null, // string example: "Sensor", "Finger", "Manual"
|
||||
@SerializedName("units") val units: String? = null, // string The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field.
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.core.ui.locale.LocaleHelper
|
||||
|
||||
open class DialogAppCompatActivity : DaggerAppCompatActivity() {
|
||||
open class TranslatedDaggerAppCompatActivity : DaggerAppCompatActivity() {
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
|
@ -2,19 +2,21 @@ package info.nightscout.core.ui.locale
|
|||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.res.Configuration
|
||||
import android.os.LocaleList
|
||||
import androidx.preference.PreferenceManager
|
||||
import info.nightscout.core.ui.R
|
||||
import java.util.Locale
|
||||
|
||||
object LocaleHelper {
|
||||
|
||||
private fun selectedLanguage(context: Context): String =
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.key_language), "default")
|
||||
?: "default"
|
||||
// injection not possible because of use in attachBaseContext
|
||||
//SP.getString(R.string.key_language, Locale.getDefault().language)
|
||||
|
||||
private fun currentLocale(context: Context): Locale {
|
||||
fun currentLocale(context: Context): Locale {
|
||||
val language = selectedLanguage(context)
|
||||
if (language == "default") return Locale.getDefault()
|
||||
|
||||
|
@ -34,18 +36,13 @@ object LocaleHelper {
|
|||
|
||||
val locale = currentLocale(context)
|
||||
Locale.setDefault(locale)
|
||||
val resources = context.resources
|
||||
val configuration = resources.configuration
|
||||
context.createConfigurationContext(configuration)
|
||||
configuration.setLocale(locale)
|
||||
}
|
||||
|
||||
fun wrap(ctx: Context): Context {
|
||||
// no action for system default language
|
||||
if (selectedLanguage(ctx) == "default") return ctx
|
||||
|
||||
val res = ctx.resources
|
||||
val configuration = res.configuration
|
||||
val configuration = Configuration()
|
||||
val newLocale = currentLocale(ctx)
|
||||
configuration.setLocale(newLocale)
|
||||
val localeList = LocaleList(newLocale)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<string name="mgdl">mg/dl</string>
|
||||
<string name="mmol">mmol/l</string>
|
||||
<string name="save">Išsaugoti</string>
|
||||
<string name="snooze">Snausti</string>
|
||||
<string name="snooze">Nutildyti</string>
|
||||
<string name="virtual_pump">Virtuali pompa</string>
|
||||
<string name="constraints">Apribojimai</string>
|
||||
<string name="superbolus">Superbolus</string>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<string name="bluetooth">Bluetooth</string>
|
||||
<string name="btwatchdog_title">BT Watchdog</string>
|
||||
<string name="btwatchdog_summary">Vienai sekundei išjungia telefono bluetooth, jei ryšys su pompa nutrūksta. Gali būti veiksminga kai kuriems telefonų modeliams, turintiems BT problemų.</string>
|
||||
<string name="virtualpump_resultok">Gerai</string>
|
||||
<string name="virtualpump_resultok">OK</string>
|
||||
<string name="pump_time_updated">Pompos laikas pakeistas</string>
|
||||
<string name="exit">Išeiti</string>
|
||||
<string name="removerecord">Ištrinti įrašą</string>
|
||||
|
@ -232,7 +232,7 @@
|
|||
<string name="hypo">Hipo</string>
|
||||
<string name="activity">Aktyvumas</string>
|
||||
<string name="wear">Išmanieji laikrodžiai</string>
|
||||
<string name="automation">Automatiškai</string>
|
||||
<string name="automation">Automatizacija</string>
|
||||
<string name="custom">Pasirinktinis</string>
|
||||
<string name="loop">Ciklas</string>
|
||||
<string name="ns">NS</string>
|
||||
|
@ -525,7 +525,7 @@
|
|||
<!-- Dialogs-->
|
||||
<string name="confirmation">Patvirtinimas</string>
|
||||
<string name="message">Pranešimas</string>
|
||||
<string name="ok">Gerai</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Atšaukti</string>
|
||||
<string name="dismiss">ATMESTI</string>
|
||||
<string name="yes">Taip</string>
|
||||
|
|
|
@ -216,6 +216,7 @@
|
|||
<item name="inRangeBackground">@color/inRangeBackground</item>
|
||||
<item name="devSlopePosColor">@color/devSlopePos</item>
|
||||
<item name="devSlopeNegColor">@color/devSlopeNeg</item>
|
||||
<item name="heartRateColor">@color/heartRate</item>
|
||||
<item name="deviationGreyColor">@color/deviationGrey</item>
|
||||
<item name="deviationBlackColor">@color/deviationBlack</item>
|
||||
<item name="deviationGreenColor">@color/deviationGreen</item>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="biometric_title">Требуется авторизация</string>
|
||||
<string name="biometric_description">Поместите палец на устройство считывания отпечатков, чтобы подтвердить свою идентичность</string>
|
||||
<string name="biometric_description">Поместите палец на устройство считывания отпечатков, чтобы подтвердить свою личность</string>
|
||||
<string name="settings_protection">Защита настроек</string>
|
||||
<string name="application_protection">Защита приложения</string>
|
||||
<string name="bolus_protection">Защита болюсов</string>
|
||||
<string name="settings_password">Пароль параметров</string>
|
||||
<string name="settings_pin">ПИН-код настроек</string>
|
||||
<string name="application_password">Пароль приложения</string>
|
||||
<string name="application_pin">PIN-код приложения</string>
|
||||
<string name="bolus_password">Пароль болюсов</string>
|
||||
<string name="bolus_pin">Пин-код болюса</string>
|
||||
<string name="protection_timeout_title">Тайм-аут удержания пароля и пин-кода [s]</string>
|
||||
<string name="settings_password">Пароль для настроек</string>
|
||||
<string name="settings_pin">ПИН для настроек</string>
|
||||
<string name="application_password">Пароль для приложения</string>
|
||||
<string name="application_pin">ПИН для приложения</string>
|
||||
<string name="bolus_password">Пароль для болюсов</string>
|
||||
<string name="bolus_pin">ПИН для болюсов</string>
|
||||
<string name="protection_timeout_title">Тайм-аут удержания пароля и ПИН-кода [s]</string>
|
||||
<string name="protection_timeout_summary">Время до ввода пароля или PIN-кода</string>
|
||||
<string name="biometric">Биометрия</string>
|
||||
<string name="custom_password">Настраиваемый пароль</string>
|
||||
|
@ -20,12 +20,12 @@
|
|||
<string name="unsecure_fallback_biometric">Небезопасный резервный вход</string>
|
||||
<string name="unsecure_fallback_descriotion_biometric">Биометрической защите требуется главный пароль для безопасности.\n\n Установите главный пароль!</string>
|
||||
<string name="password_set">Пароль задан!</string>
|
||||
<string name="pin_set">PIN-код установлен!</string>
|
||||
<string name="pin_set">ПИН установлен!</string>
|
||||
<string name="password_not_set">Пароль не задан</string>
|
||||
<string name="pin_not_set">PIN-код не задан</string>
|
||||
<string name="pin_not_set">ПИН не задан</string>
|
||||
<string name="password_not_changed">Пароль не был изменён</string>
|
||||
<string name="pin_not_changed">PIN-код не изменён</string>
|
||||
<string name="pin_cleared">PIN-код очищен!</string>
|
||||
<string name="pin_not_changed">ПИН не изменён</string>
|
||||
<string name="pin_cleared">ПИН очищен!</string>
|
||||
<string name="password_hint">Введите пароль здесь</string>
|
||||
<string name="pin_hint">Введите PIN-код здесь</string>
|
||||
<string name="pin_hint">Введите ПИН здесь</string>
|
||||
</resources>
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
<string name="profile_set_ok">базальный профиль помпы обновлен</string>
|
||||
<string name="invalid_input">введенные данные неверны</string>
|
||||
<string name="bolus_delivering">Подается болюс %1$.2f ед</string>
|
||||
<string name="constraint_applied">применено ограничение!</string>
|
||||
<string name="constraint_applied">Применено ограничение!</string>
|
||||
<string name="tempbasals_iobtotal_label_string">Общий IOB:</string>
|
||||
<string name="tt_label">Врем цель (TT)</string>
|
||||
<string name="tt_label">ВЦ</string>
|
||||
<string name="pump_unreachable">Помпа недоступна</string>
|
||||
<string name="insulin_unit_shortname">Ед</string>
|
||||
<string name="pump_base_basal_rate">%1$.2f ед/ч</string>
|
||||
|
@ -25,12 +25,12 @@
|
|||
<string name="save">Сохранить</string>
|
||||
<string name="snooze">Отложить</string>
|
||||
<string name="virtual_pump">Виртуальная помпа</string>
|
||||
<string name="constraints">ограничения</string>
|
||||
<string name="constraints">Ограничения</string>
|
||||
<string name="superbolus">Суперболюс</string>
|
||||
<string name="pump_paused">Помпа приостановлена</string>
|
||||
<string name="and">И</string>
|
||||
<string name="patient_name_default" comment="This is default patient display name, when user does not provide real one">Пользователь</string>
|
||||
<string name="result">результат</string>
|
||||
<string name="result">Результат</string>
|
||||
<string name="settings">Настройки</string>
|
||||
<string name="statuslights">Индикаторы состояния</string>
|
||||
<string name="do_ns_upload_title">Выгружать (передавать данные) ГК в Nightscout</string>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<string name="ue_export_to_csv">Экспорт пользовательских записей в Excel (csv)</string>
|
||||
<string name="confirm">Подтверждаю</string>
|
||||
<string name="pump">Помпа</string>
|
||||
<string name="missed_bg_readings">Пропущенные данные СК</string>
|
||||
<string name="missed_bg_readings">Пропущенные данные ГК</string>
|
||||
<string name="treatments_iob_label_string">IOB акт инс:</string>
|
||||
<string name="mute5min">Отключить уведомления на 5 минут</string>
|
||||
<string name="mute">Отключить звук</string>
|
||||
|
@ -49,10 +49,10 @@
|
|||
<string name="extendedbolusdeliveryerror">Ошибка подачи пролонгированного болюса</string>
|
||||
<string name="aps_mode_title">Режим APS</string>
|
||||
<string name="extended_bolus">Пролонгированный болюс</string>
|
||||
<string name="paused">на паузе</string>
|
||||
<string name="paused">На паузе</string>
|
||||
<string name="tdd_total">Суммарный суточный инсулин TDD</string>
|
||||
<string name="goingtodeliver">Будет подано %1$.2f ед инс</string>
|
||||
<string name="waitingforpump">ожидание помпы</string>
|
||||
<string name="waitingforpump">Ожидание помпы</string>
|
||||
<string name="androidaps_start">AAPS запущен</string>
|
||||
<string name="formatsignedinsulinunits">%1$+.2f ед</string>
|
||||
<string name="format_carbs">%1$d гр</string>
|
||||
|
@ -60,18 +60,18 @@
|
|||
<string name="format_mins">%1$d мин</string>
|
||||
<string name="objectives">Цели</string>
|
||||
<string name="please_wait">Подождите…</string>
|
||||
<string name="stop">стоп</string>
|
||||
<string name="stop">Стоп</string>
|
||||
<string name="carbs">Углеводы</string>
|
||||
<string name="invalid_profile">Недопустимый профиль!</string>
|
||||
<string name="no_profile_set">ПРОФИЛЬ НЕ ЗАДАН</string>
|
||||
<string name="active"><![CDATA[Активен]]></string>
|
||||
<string name="date">дата</string>
|
||||
<string name="date">Дата</string>
|
||||
<string name="units_label">единицы</string>
|
||||
<string name="dia_label">DIA (время действия инсулина)</string>
|
||||
<string name="ic_label">Углеводный коэффициент IC (ГУ/ед. инс)</string>
|
||||
<string name="isf_label">ISF (чувствительность к инсулину)</string>
|
||||
<string name="basal_label">базал</string>
|
||||
<string name="target_label">Целевое значение СК:</string>
|
||||
<string name="target_label">Целевое значение ГК:</string>
|
||||
<string name="dia_long_label">Продолжительность действия инсулина</string>
|
||||
<string name="ic_long_label">Углеводный коэффициент IC (ГУ/ед. инс.)</string>
|
||||
<string name="isf_long_label">Фактор Чувствительности к Инсулину (ISF)</string>
|
||||
|
@ -86,10 +86,10 @@
|
|||
<string name="pump_time_updated">Время на помпе обновлено</string>
|
||||
<string name="exit">Выйти</string>
|
||||
<string name="removerecord">Удалить запись</string>
|
||||
<string name="loopisdisabled">Зцикл не работает</string>
|
||||
<string name="loopisdisabled">Цикл не работает</string>
|
||||
<string name="alarm">Оповещения об опасности</string>
|
||||
<string name="disableloop">Деактивировать цикличность</string>
|
||||
<string name="enableloop">Активировать цикличность</string>
|
||||
<string name="disableloop">Деактивировать цикл</string>
|
||||
<string name="enableloop">Активировать цикл</string>
|
||||
<string name="resumeloop">Возобновить цикл</string>
|
||||
<string name="suspendloop">Приостановить цикл</string>
|
||||
<string name="duration_min_label">Длительность (мин)</string>
|
||||
|
@ -98,8 +98,8 @@
|
|||
<string name="exists">существует</string>
|
||||
<string name="notexists">не существует</string>
|
||||
<string name="glucose">Гликемия</string>
|
||||
<string name="iob">IOB акт инс</string>
|
||||
<string name="cob">АктУгл COB</string>
|
||||
<string name="iob">IOB (актИнс)</string>
|
||||
<string name="cob">COB (актУгл)</string>
|
||||
<string name="name_short">Имя:</string>
|
||||
<string name="time">Время</string>
|
||||
<string name="ns_wifi_ssids">SSID для Wi-Fi</string>
|
||||
|
@ -117,7 +117,7 @@
|
|||
<string name="duration_label">Длительность действия</string>
|
||||
<string name="shortgramm">грамм</string>
|
||||
<string name="pumpsuspended">Работа помпы остановлена</string>
|
||||
<string name="notconfigured">Не сконфигурировано</string>
|
||||
<string name="notconfigured">Не настроено</string>
|
||||
<string name="loopsuspended">ЗЦ остановлен</string>
|
||||
<string name="trend_arrow">Стрелка тренда</string>
|
||||
<string name="a11y_autosens_label">Auto sens</string>
|
||||
|
@ -157,7 +157,7 @@
|
|||
<string name="overview_insulin_label">Инсулин</string>
|
||||
<string name="stoptemptarget">Остановить врем цель</string>
|
||||
<string name="closedloop">Замкнутый цикл</string>
|
||||
<string name="openloop">открытый цикл</string>
|
||||
<string name="openloop">Открытый цикл</string>
|
||||
<string name="lowglucosesuspend">Приостановка помпы на низкой ГК</string>
|
||||
<string name="dia">Время действия инсулина DIA</string>
|
||||
<string name="ic_short">IC углкоэф ГУ/инс</string>
|
||||
|
|
|
@ -181,6 +181,7 @@
|
|||
<attr name="bolusDataPointColor" format="reference|color" />
|
||||
<attr name="profileSwitchColor" format="reference|color" />
|
||||
<attr name="originalBgValueColor" format="reference|color" />
|
||||
<attr name="heartRateColor" format="reference|color" />
|
||||
<attr name="therapyEvent_NS_MBG" format="reference|color" />
|
||||
<attr name="therapyEvent_FINGER_STICK_BG_VALUE" format="reference|color" />
|
||||
<attr name="therapyEvent_EXERCISE" format="reference|color" />
|
||||
|
@ -221,4 +222,4 @@
|
|||
<attr name="crossTargetColor" format="reference|color" />
|
||||
<!---Custom button -->
|
||||
<attr name="customBtnStyle" format="reference"/>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
<color name="bgi">#00EEEE</color>
|
||||
<color name="devSlopePos">#FFFFFF00</color>
|
||||
<color name="devSlopeNeg">#FFFF00FF</color>
|
||||
<color name="heartRate">#FFFFFF66</color>
|
||||
<color name="actionsConfirm">#F6CE22</color>
|
||||
<color name="deviations">#FF0000</color>
|
||||
<color name="cobAlert">#7484E2</color>
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
<item name="inRangeBackground">@color/inRangeBackground</item>
|
||||
<item name="devSlopePosColor">@color/devSlopePos</item>
|
||||
<item name="devSlopeNegColor">@color/devSlopeNeg</item>
|
||||
<item name="heartRateColor">@color/heartRate</item>
|
||||
<item name="deviationGreyColor">@color/deviationGrey</item>
|
||||
<item name="deviationBlackColor">@color/deviationBlack</item>
|
||||
<item name="deviationGreenColor">@color/deviationGreen</item>
|
||||
|
|
|
@ -22,7 +22,7 @@ dependencies {
|
|||
implementation project(':app-wear-shared:shared')
|
||||
|
||||
//Firebase
|
||||
api platform('com.google.firebase:firebase-bom:31.2.3')
|
||||
api platform('com.google.firebase:firebase-bom:32.1.1')
|
||||
api "com.google.firebase:firebase-analytics-ktx"
|
||||
api "com.google.firebase:firebase-crashlytics-ktx"
|
||||
// StatsActivity not in use now
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.view.ActionMode
|
|||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
@ -68,7 +69,7 @@ class ActionModeHelper<T>(val rh: ResourceHelper, val activity: FragmentActivity
|
|||
} else if (fragment?.isResumed == true) {
|
||||
menu.add(Menu.FIRST, R.id.nav_remove_items, 0, rh.gs(R.string.remove_items)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.add(Menu.FIRST, R.id.nav_sort_items, 0, rh.gs(R.string.sort_items)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.setGroupDividerEnabled(true)
|
||||
MenuCompat.setGroupDividerEnabled(menu, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="count_selected">%1$d выбрано</string>
|
||||
<string name="count_selected">Выбрано: %1$d</string>
|
||||
<string name="remove_items">Удалить элементы</string>
|
||||
<string name="sort_items">Сортировать элементы</string>
|
||||
<string name="remove_selected_items">Удалить выбранные элементы</string>
|
||||
|
|
|
@ -53,6 +53,8 @@ files:
|
|||
translation: /pump/pump-core/src/main/res/values-%android_code%/strings.xml
|
||||
- source: /pump/eopatch/src/main/res/values/strings.xml
|
||||
translation: /pump/eopatch/src/main/res/values-%android_code%/strings.xml
|
||||
- source: /pump/eopatch/src/main/res/values/strings_alarm.xml
|
||||
translation: /pump/eopatch/src/main/res/values-%android_code%/strings_alarm.xml
|
||||
- source: /pump/diaconn/src/main/res/values/strings.xml
|
||||
translation: /pump/diaconn/src/main/res/values-%android_code%/strings.xml
|
||||
- source: /pump/pump-common/src/main/res/values/strings.xml
|
||||
|
|
|
@ -7,6 +7,7 @@ plugins {
|
|||
}
|
||||
|
||||
apply from: "${project.rootDir}/core/main/android_dependencies.gradle"
|
||||
apply from: "${project.rootDir}/core/main/test_dependencies.gradle"
|
||||
|
||||
android {
|
||||
|
||||
|
@ -30,4 +31,4 @@ dependencies {
|
|||
allOpen {
|
||||
// allows mocking for classes w/o directly opening them for release builds
|
||||
annotation 'info.nightscout.database.annotations.DbOpenForTesting'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package info.nightscout.database.entities
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import info.nightscout.database.entities.embedments.InterfaceIDs
|
||||
import info.nightscout.database.entities.interfaces.DBEntryWithTimeAndDuration
|
||||
import info.nightscout.database.entities.interfaces.TraceableDBEntry
|
||||
import java.util.*
|
||||
|
||||
/** Heart rate values measured by a user smart watch or the like. */
|
||||
@Entity(
|
||||
tableName = TABLE_HEART_RATE,
|
||||
indices = [Index("id"), Index("timestamp")]
|
||||
)
|
||||
data class HeartRate(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
override var id: Long = 0,
|
||||
/** Duration milliseconds */
|
||||
override var duration: Long,
|
||||
/** Milliseconds since the epoch. End of the sampling period, i.e. the value is
|
||||
* sampled from timestamp-duration to timestamp. */
|
||||
override var timestamp: Long,
|
||||
var beatsPerMinute: Double,
|
||||
/** Source device that measured the heart rate. */
|
||||
var device: String,
|
||||
override var utcOffset: Long = TimeZone.getDefault().getOffset(timestamp).toLong(),
|
||||
override var version: Int = 0,
|
||||
override var dateCreated: Long = -1,
|
||||
override var isValid: Boolean = true,
|
||||
override var referenceId: Long? = null,
|
||||
@Embedded
|
||||
override var interfaceIDs_backing: InterfaceIDs? = null
|
||||
) : TraceableDBEntry, DBEntryWithTimeAndDuration {
|
||||
|
||||
fun contentEqualsTo(other: HeartRate): Boolean {
|
||||
return this === other || (
|
||||
duration == other.duration &&
|
||||
timestamp == other.timestamp &&
|
||||
beatsPerMinute == other.beatsPerMinute &&
|
||||
isValid == other.isValid)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ const val TABLE_CARBS = "carbs"
|
|||
const val TABLE_DEVICE_STATUS = "deviceStatus"
|
||||
const val TABLE_EFFECTIVE_PROFILE_SWITCHES = "effectiveProfileSwitches"
|
||||
const val TABLE_EXTENDED_BOLUSES = "extendedBoluses"
|
||||
const val TABLE_HEART_RATE = "heartRate"
|
||||
const val TABLE_GLUCOSE_VALUES = "glucoseValues"
|
||||
const val TABLE_FOODS = "foods"
|
||||
const val TABLE_MULTIWAVE_BOLUS_LINKS = "multiwaveBolusLinks"
|
||||
|
|
|
@ -8,6 +8,7 @@ import info.nightscout.database.entities.Carbs
|
|||
import info.nightscout.database.entities.EffectiveProfileSwitch
|
||||
import info.nightscout.database.entities.ExtendedBolus
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.MultiwaveBolusLink
|
||||
import info.nightscout.database.entities.OfflineEvent
|
||||
import info.nightscout.database.entities.PreferenceChange
|
||||
|
@ -35,5 +36,6 @@ data class NewEntries(
|
|||
val temporaryTarget: List<TemporaryTarget>,
|
||||
val therapyEvents: List<TherapyEvent>,
|
||||
val totalDailyDoses: List<TotalDailyDose>,
|
||||
val versionChanges: List<VersionChange>
|
||||
)
|
||||
val versionChanges: List<VersionChange>,
|
||||
val heartRates: List<HeartRate>,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package info.nightscout.database.entities
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class HeartRateTest {
|
||||
@Test
|
||||
fun contentEqualsTo_equals() {
|
||||
val hr1 = createHeartRate()
|
||||
assertTrue(hr1.contentEqualsTo(hr1))
|
||||
assertTrue(hr1.contentEqualsTo(hr1.copy()))
|
||||
assertTrue(hr1.contentEqualsTo(hr1.copy (id = 2, version = 2, dateCreated = 1L, referenceId = 4L)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun contentEqualsTo_notEquals() {
|
||||
val hr1 = createHeartRate()
|
||||
assertFalse(hr1.contentEqualsTo(hr1.copy(duration = 60_001L)))
|
||||
assertFalse(hr1.contentEqualsTo(hr1.copy(timestamp = 2L)))
|
||||
assertFalse(hr1.contentEqualsTo(hr1.copy(duration = 60_001L)))
|
||||
assertFalse(hr1.contentEqualsTo(hr1.copy(beatsPerMinute = 100.0)))
|
||||
assertFalse(hr1.contentEqualsTo(hr1.copy(isValid = false)))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun createHeartRate(timestamp: Long? = null, beatsPerMinute: Double = 80.0) =
|
||||
HeartRate(
|
||||
timestamp = timestamp ?: System.currentTimeMillis(),
|
||||
duration = 60_0000L,
|
||||
beatsPerMinute = beatsPerMinute,
|
||||
device = "T",
|
||||
)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ plugins {
|
|||
|
||||
apply from: "${project.rootDir}/core/main/android_dependencies.gradle"
|
||||
apply from: "${project.rootDir}/core/main/android_module_dependencies.gradle"
|
||||
apply from: "${project.rootDir}/core/main/test_dependencies.gradle"
|
||||
apply from: "${project.rootDir}/core/main/jacoco_global.gradle"
|
||||
|
||||
android {
|
||||
|
||||
|
@ -20,6 +22,9 @@ android {
|
|||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
androidTest.assets.srcDirs += files("$projectDir/schemas")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -44,9 +49,11 @@ dependencies {
|
|||
|
||||
api "com.google.dagger:dagger-android:$dagger_version"
|
||||
api "com.google.dagger:dagger-android-support:$dagger_version"
|
||||
|
||||
androidTestImplementation "androidx.room:room-testing:$room_version"
|
||||
}
|
||||
|
||||
allOpen {
|
||||
// allows mocking for classes w/o directly opening them for release builds
|
||||
annotation 'info.nightscout.database.annotations.DbOpenForTesting'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 23,
|
||||
"identityHash": "173734db5f4f35f6295ed953d8124794",
|
||||
"identityHash": "a3ee37800b6cda170d0ea64799ed7876",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "apsResults",
|
||||
|
@ -3689,12 +3689,153 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "heartRate",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `duration` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `beatsPerMinute` REAL NOT NULL, `device` TEXT NOT NULL, `utcOffset` INTEGER NOT NULL, `version` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `isValid` INTEGER NOT NULL, `referenceId` INTEGER, `nightscoutSystemId` TEXT, `nightscoutId` TEXT, `pumpType` TEXT, `pumpSerial` TEXT, `temporaryId` INTEGER, `pumpId` INTEGER, `startId` INTEGER, `endId` INTEGER)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "duration",
|
||||
"columnName": "duration",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timestamp",
|
||||
"columnName": "timestamp",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "beatsPerMinute",
|
||||
"columnName": "beatsPerMinute",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "device",
|
||||
"columnName": "device",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "utcOffset",
|
||||
"columnName": "utcOffset",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "version",
|
||||
"columnName": "version",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "dateCreated",
|
||||
"columnName": "dateCreated",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isValid",
|
||||
"columnName": "isValid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "referenceId",
|
||||
"columnName": "referenceId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.nightscoutSystemId",
|
||||
"columnName": "nightscoutSystemId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.nightscoutId",
|
||||
"columnName": "nightscoutId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.pumpType",
|
||||
"columnName": "pumpType",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.pumpSerial",
|
||||
"columnName": "pumpSerial",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.temporaryId",
|
||||
"columnName": "temporaryId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.pumpId",
|
||||
"columnName": "pumpId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.startId",
|
||||
"columnName": "startId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "interfaceIDs_backing.endId",
|
||||
"columnName": "endId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_heartRate_id",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_heartRate_id` ON `${TABLE_NAME}` (`id`)"
|
||||
},
|
||||
{
|
||||
"name": "index_heartRate_timestamp",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"timestamp"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_heartRate_timestamp` ON `${TABLE_NAME}` (`timestamp`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '173734db5f4f35f6295ed953d8124794')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a3ee37800b6cda170d0ea64799ed7876')"
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,126 @@
|
|||
package info.nightscout.database.impl
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import androidx.room.testing.MigrationTestHelper
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.TABLE_HEART_RATE
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
internal class HeartRateDaoTest {
|
||||
|
||||
private val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
private fun createDatabase() =
|
||||
Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
|
||||
|
||||
private fun getDbObjects(supportDb: SupportSQLiteDatabase, type: String): Set<String> {
|
||||
val names = mutableSetOf<String>()
|
||||
supportDb.query("SELECT name FROM sqlite_master WHERE type = '$type'").use { c ->
|
||||
while (c.moveToNext()) names.add(c.getString(0))
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
private fun getTableNames(db: SupportSQLiteDatabase) = getDbObjects(db, "table")
|
||||
private fun getIndexNames(db: SupportSQLiteDatabase) = getDbObjects(db, "index")
|
||||
|
||||
private fun insertAndFind(database: AppDatabase) {
|
||||
val hr1 = createHeartRate()
|
||||
val id = database.heartRateDao.insert(hr1)
|
||||
val hr2 = database.heartRateDao.findById(id)
|
||||
assertTrue(hr1.contentEqualsTo(hr2!!))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun new_insertAndFind() {
|
||||
createDatabase().use { db -> insertAndFind(db) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrate_createsTableAndIndices() {
|
||||
val helper = MigrationTestHelper(
|
||||
InstrumentationRegistry.getInstrumentation(),
|
||||
AppDatabase::class.java
|
||||
)
|
||||
val startVersion = 22
|
||||
val supportDb = helper.createDatabase(TEST_DB_NAME, startVersion)
|
||||
assertFalse(getTableNames(supportDb).contains(TABLE_HEART_RATE))
|
||||
DatabaseModule().migrations.filter { m -> m.startVersion >= startVersion }.forEach { m -> m.migrate(supportDb) }
|
||||
assertTrue(getTableNames(supportDb).contains(TABLE_HEART_RATE))
|
||||
assertTrue(getIndexNames(supportDb).contains("index_heartRate_id"))
|
||||
assertTrue(getIndexNames(supportDb).contains("index_heartRate_timestamp"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrate_insertAndFind() {
|
||||
val helper = MigrationTestHelper(
|
||||
InstrumentationRegistry.getInstrumentation(),
|
||||
AppDatabase::class.java
|
||||
)
|
||||
// Create the database for version 22 (that's missing the heartRate table).
|
||||
// helper.createDatabase removes the db file if it already exists.
|
||||
val supportDb = helper.createDatabase(TEST_DB_NAME, 22)
|
||||
assertFalse(getTableNames(supportDb).contains(TABLE_HEART_RATE))
|
||||
// Room.databaseBuilder will use the previously created db file that has version 22.
|
||||
Room.databaseBuilder(ApplicationProvider.getApplicationContext(), AppDatabase::class.java, TEST_DB_NAME)
|
||||
.addMigrations(*DatabaseModule().migrations)
|
||||
.build().use { db -> insertAndFind(db) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFromTime() {
|
||||
createDatabase().use { db ->
|
||||
val dao = db.heartRateDao
|
||||
val timestamp = System.currentTimeMillis()
|
||||
val hr1 = createHeartRate(timestamp = timestamp, beatsPerMinute = 80.0)
|
||||
val hr2 = createHeartRate(timestamp = timestamp + 1, beatsPerMinute = 150.0)
|
||||
dao.insertNewEntry(hr1)
|
||||
dao.insertNewEntry(hr2)
|
||||
|
||||
assertEquals(listOf(hr1, hr2), dao.getFromTime(timestamp))
|
||||
assertEquals(listOf(hr2), dao.getFromTime(timestamp + 1))
|
||||
assertTrue(dao.getFromTime(timestamp + 2).isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFromTimeToTime() {
|
||||
createDatabase().use { db ->
|
||||
val dao = db.heartRateDao
|
||||
val timestamp = System.currentTimeMillis()
|
||||
val hr1 = createHeartRate(timestamp = timestamp, beatsPerMinute = 80.0)
|
||||
val hr2 = createHeartRate(timestamp = timestamp + 1, beatsPerMinute = 150.0)
|
||||
val hr3 = createHeartRate(timestamp = timestamp + 2, beatsPerMinute = 160.0)
|
||||
dao.insertNewEntry(hr1)
|
||||
dao.insertNewEntry(hr2)
|
||||
dao.insertNewEntry(hr3)
|
||||
|
||||
assertEquals(listOf(hr1, hr2, hr3), dao.getFromTimeToTime(timestamp, timestamp + 2))
|
||||
assertEquals(listOf(hr1, hr2), dao.getFromTimeToTime(timestamp, timestamp + 1))
|
||||
assertEquals(listOf(hr2), dao.getFromTimeToTime(timestamp + 1, timestamp + 1))
|
||||
assertTrue(dao.getFromTimeToTime(timestamp + 3, timestamp + 10).isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TEST_DB_NAME = "testDatabase"
|
||||
|
||||
fun createHeartRate(timestamp: Long? = null, beatsPerMinute: Double = 80.0) =
|
||||
HeartRate(
|
||||
timestamp = timestamp ?: System.currentTimeMillis(),
|
||||
duration = 60_0000L,
|
||||
beatsPerMinute = beatsPerMinute,
|
||||
device = "T",
|
||||
)
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package info.nightscout.database.impl.transactions
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import info.nightscout.database.impl.AppDatabase
|
||||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.database.impl.HeartRateDaoTest
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class InsertOrUpdateHeartRateTransactionTest {
|
||||
|
||||
private val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
private lateinit var db: AppDatabase
|
||||
private lateinit var repo: AppRepository
|
||||
|
||||
@Before
|
||||
fun setupUp() {
|
||||
db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
|
||||
repo = AppRepository(db)
|
||||
}
|
||||
|
||||
@After
|
||||
fun shutdown() {
|
||||
db.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createNewEntry() {
|
||||
val hr1 = HeartRateDaoTest.createHeartRate()
|
||||
val result = repo.runTransactionForResult(InsertOrUpdateHeartRateTransaction(hr1)).blockingGet()
|
||||
assertEquals(listOf(hr1), result.inserted)
|
||||
assertTrue(result.updated.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateEntry() {
|
||||
val hr1 = HeartRateDaoTest.createHeartRate()
|
||||
val id = db.heartRateDao.insertNewEntry(hr1)
|
||||
assertNotEquals(0, id)
|
||||
val hr2 = hr1.copy(id = id, beatsPerMinute = 181.0)
|
||||
val result = repo.runTransactionForResult(InsertOrUpdateHeartRateTransaction(hr2)).blockingGet()
|
||||
assertEquals(listOf(hr2), result.updated)
|
||||
assertTrue(result.inserted.isEmpty())
|
||||
|
||||
val hr3 = db.heartRateDao.findById(id)!!
|
||||
assertTrue(hr2.contentEqualsTo(hr3))
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ import info.nightscout.database.entities.EffectiveProfileSwitch
|
|||
import info.nightscout.database.entities.ExtendedBolus
|
||||
import info.nightscout.database.entities.Food
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.MultiwaveBolusLink
|
||||
import info.nightscout.database.entities.OfflineEvent
|
||||
import info.nightscout.database.entities.PreferenceChange
|
||||
|
@ -43,18 +44,20 @@ import info.nightscout.database.entities.TherapyEvent
|
|||
import info.nightscout.database.entities.TotalDailyDose
|
||||
import info.nightscout.database.entities.UserEntry
|
||||
import info.nightscout.database.entities.VersionChange
|
||||
import info.nightscout.database.impl.daos.HeartRateDao
|
||||
import java.io.Closeable
|
||||
|
||||
const val DATABASE_VERSION = 23
|
||||
const val DATABASE_VERSION = 24
|
||||
|
||||
@Database(version = DATABASE_VERSION,
|
||||
entities = [APSResult::class, Bolus::class, BolusCalculatorResult::class, Carbs::class,
|
||||
EffectiveProfileSwitch::class, ExtendedBolus::class, GlucoseValue::class, ProfileSwitch::class,
|
||||
TemporaryBasal::class, TemporaryTarget::class, TherapyEvent::class, TotalDailyDose::class, APSResultLink::class,
|
||||
MultiwaveBolusLink::class, PreferenceChange::class, VersionChange::class, UserEntry::class,
|
||||
Food::class, DeviceStatus::class, OfflineEvent::class],
|
||||
Food::class, DeviceStatus::class, OfflineEvent::class, HeartRate::class],
|
||||
exportSchema = true)
|
||||
@TypeConverters(Converters::class)
|
||||
internal abstract class AppDatabase : RoomDatabase() {
|
||||
internal abstract class AppDatabase : Closeable, RoomDatabase() {
|
||||
|
||||
abstract val glucoseValueDao: GlucoseValueDao
|
||||
|
||||
|
@ -96,4 +99,5 @@ internal abstract class AppDatabase : RoomDatabase() {
|
|||
|
||||
abstract val offlineEventDao: OfflineEventDao
|
||||
|
||||
}
|
||||
abstract val heartRateDao: HeartRateDao
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ import kotlin.math.roundToInt
|
|||
//database.foodDao.deleteOlderThan(than)
|
||||
removed.add(Pair("DeviceStatus", database.deviceStatusDao.deleteOlderThan(than)))
|
||||
removed.add(Pair("OfflineEvent", database.offlineEventDao.deleteOlderThan(than)))
|
||||
removed.add(Pair("HeartRate", database.heartRateDao.deleteOlderThan(than)))
|
||||
|
||||
if (deleteTrackedChanges) {
|
||||
removed.add(Pair("GlucoseValue", database.glucoseValueDao.deleteTrackedChanges()))
|
||||
|
@ -119,6 +120,7 @@ import kotlin.math.roundToInt
|
|||
removed.add(Pair("ApsResult", database.apsResultDao.deleteTrackedChanges()))
|
||||
//database.foodDao.deleteHistory()
|
||||
removed.add(Pair("OfflineEvent", database.offlineEventDao.deleteTrackedChanges()))
|
||||
removed.add(Pair("HeartRate", database.heartRateDao.deleteTrackedChanges()))
|
||||
}
|
||||
val ret = StringBuilder()
|
||||
removed
|
||||
|
@ -930,6 +932,11 @@ import kotlin.math.roundToInt
|
|||
fun getLastOfflineEventId(): Long? =
|
||||
database.offlineEventDao.getLastId()
|
||||
|
||||
fun getHeartRatesFromTime(timeMillis: Long) = database.heartRateDao.getFromTime(timeMillis)
|
||||
|
||||
fun getHeartRatesFromTimeToTime(startMillis: Long, endMillis: Long) =
|
||||
database.heartRateDao.getFromTimeToTime(startMillis, endMillis)
|
||||
|
||||
suspend fun collectNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int) = NewEntries(
|
||||
apsResults = database.apsResultDao.getNewEntriesSince(since, until, limit, offset),
|
||||
apsResultLinks = database.apsResultLinkDao.getNewEntriesSince(since, until, limit, offset),
|
||||
|
@ -948,6 +955,7 @@ import kotlin.math.roundToInt
|
|||
therapyEvents = database.therapyEventDao.getNewEntriesSince(since, until, limit, offset),
|
||||
totalDailyDoses = database.totalDailyDoseDao.getNewEntriesSince(since, until, limit, offset),
|
||||
versionChanges = database.versionChangeDao.getNewEntriesSince(since, until, limit, offset),
|
||||
heartRates = database.heartRateDao.getNewEntriesSince(since, until, limit, offset),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -956,4 +964,3 @@ inline fun <reified T : Any> Maybe<T>.toWrappedSingle(): Single<ValueWrapper<T>>
|
|||
this.map { ValueWrapper.Existing(it) as ValueWrapper<T> }
|
||||
.switchIfEmpty(Maybe.just(ValueWrapper.Absent()))
|
||||
.toSingle()
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package info.nightscout.database.impl
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase.Callback
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import info.nightscout.database.entities.TABLE_HEART_RATE
|
||||
import javax.inject.Qualifier
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
@ -22,13 +24,7 @@ open class DatabaseModule {
|
|||
internal fun provideAppDatabase(context: Context, @DbFileName fileName: String) =
|
||||
Room
|
||||
.databaseBuilder(context, AppDatabase::class.java, fileName)
|
||||
// .addMigrations(migration5to6)
|
||||
// .addMigrations(migration6to7)
|
||||
// .addMigrations(migration7to8)
|
||||
// .addMigrations(migration11to12)
|
||||
.addMigrations(migration20to21)
|
||||
.addMigrations(migration21to22)
|
||||
.addMigrations(migration22to23)
|
||||
.addMigrations(*migrations)
|
||||
.addCallback(object : Callback() {
|
||||
override fun onOpen(db: SupportSQLiteDatabase) {
|
||||
super.onOpen(db)
|
||||
|
@ -89,4 +85,36 @@ open class DatabaseModule {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
private val migration23to24 = object : Migration(23, 24) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"""CREATE TABLE IF NOT EXISTS `$TABLE_HEART_RATE` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`duration` INTEGER NOT NULL,
|
||||
`timestamp` INTEGER NOT NULL,
|
||||
`beatsPerMinute` REAL NOT NULL,
|
||||
`device` TEXT NOT NULL,
|
||||
`utcOffset` INTEGER NOT NULL,
|
||||
`version` INTEGER NOT NULL,
|
||||
`dateCreated` INTEGER NOT NULL,
|
||||
`isValid` INTEGER NOT NULL,
|
||||
`referenceId` INTEGER,
|
||||
`nightscoutSystemId` TEXT,
|
||||
`nightscoutId` TEXT,
|
||||
`pumpType` TEXT,
|
||||
`pumpSerial` TEXT,
|
||||
`temporaryId` INTEGER,
|
||||
`pumpId` INTEGER, `startId` INTEGER,
|
||||
`endId` INTEGER)""".trimIndent()
|
||||
)
|
||||
database.execSQL("""CREATE INDEX IF NOT EXISTS `index_heartRate_id` ON `$TABLE_HEART_RATE` (`id`)""")
|
||||
database.execSQL("""CREATE INDEX IF NOT EXISTS `index_heartRate_timestamp` ON `$TABLE_HEART_RATE` (`timestamp`)""")
|
||||
// Custom indexes must be dropped on migration to pass room schema checking after upgrade
|
||||
dropCustomIndexes(database)
|
||||
}
|
||||
}
|
||||
|
||||
/** List of all migrations for easy reply in tests. */
|
||||
@VisibleForTesting
|
||||
internal val migrations = arrayOf(migration20to21, migration21to22, migration22to23, migration23to24)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ import info.nightscout.database.impl.daos.delegated.DelegatedTotalDailyDoseDao
|
|||
import info.nightscout.database.impl.daos.delegated.DelegatedUserEntryDao
|
||||
import info.nightscout.database.impl.daos.delegated.DelegatedVersionChangeDao
|
||||
import info.nightscout.database.entities.interfaces.DBEntry
|
||||
import info.nightscout.database.impl.daos.HeartRateDao
|
||||
import info.nightscout.database.impl.daos.delegated.DelegatedHeartRateDao
|
||||
|
||||
internal class DelegatedAppDatabase(val changes: MutableList<DBEntry>, val database: AppDatabase) {
|
||||
|
||||
|
@ -64,5 +66,6 @@ internal class DelegatedAppDatabase(val changes: MutableList<DBEntry>, val datab
|
|||
val foodDao: FoodDao = DelegatedFoodDao(changes, database.foodDao)
|
||||
val deviceStatusDao: DeviceStatusDao = DelegatedDeviceStatusDao(changes, database.deviceStatusDao)
|
||||
val offlineEventDao: OfflineEventDao = DelegatedOfflineEventDao(changes, database.offlineEventDao)
|
||||
val heartRateDao: HeartRateDao = DelegatedHeartRateDao(changes, database.heartRateDao)
|
||||
fun clearAllTables() = database.clearAllTables()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.database.impl.daos
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.TABLE_HEART_RATE
|
||||
|
||||
@Dao
|
||||
internal interface HeartRateDao : TraceableDao<HeartRate> {
|
||||
|
||||
@Query("SELECT * FROM $TABLE_HEART_RATE WHERE id = :id")
|
||||
override fun findById(id: Long): HeartRate?
|
||||
|
||||
@Query("DELETE FROM $TABLE_HEART_RATE")
|
||||
override fun deleteAllEntries()
|
||||
|
||||
@Query("DELETE FROM $TABLE_HEART_RATE WHERE timestamp < :than")
|
||||
override fun deleteOlderThan(than: Long): Int
|
||||
|
||||
@Query("DELETE FROM $TABLE_HEART_RATE WHERE referenceId IS NOT NULL")
|
||||
override fun deleteTrackedChanges(): Int
|
||||
|
||||
@Query("SELECT * FROM $TABLE_HEART_RATE WHERE timestamp >= :timestamp ORDER BY timestamp")
|
||||
fun getFromTime(timestamp: Long): List<HeartRate>
|
||||
|
||||
@Query("SELECT * FROM $TABLE_HEART_RATE WHERE timestamp BETWEEN :startMillis AND :endMillis ORDER BY timestamp")
|
||||
fun getFromTimeToTime(startMillis: Long, endMillis: Long): List<HeartRate>
|
||||
|
||||
@Query("SELECT * FROM $TABLE_HEART_RATE WHERE timestamp > :since AND timestamp <= :until LIMIT :limit OFFSET :offset")
|
||||
fun getNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int): List<HeartRate>
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.database.impl.daos.delegated
|
||||
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.interfaces.DBEntry
|
||||
import info.nightscout.database.impl.daos.HeartRateDao
|
||||
|
||||
internal class DelegatedHeartRateDao(
|
||||
changes: MutableList<DBEntry>,
|
||||
private val dao:HeartRateDao): DelegatedDao(changes), HeartRateDao by dao {
|
||||
|
||||
override fun insertNewEntry(entry: HeartRate): Long {
|
||||
changes.add(entry)
|
||||
return dao.insertNewEntry(entry)
|
||||
}
|
||||
|
||||
override fun updateExistingEntry(entry: HeartRate): Long {
|
||||
changes.add(entry)
|
||||
return dao.updateExistingEntry(entry)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.database.impl.transactions
|
||||
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
|
||||
class InsertOrUpdateHeartRateTransaction(private val heartRate: HeartRate):
|
||||
Transaction<InsertOrUpdateHeartRateTransaction.TransactionResult>() {
|
||||
|
||||
override fun run(): TransactionResult {
|
||||
val existing = if (heartRate.id == 0L) null else database.heartRateDao.findById(heartRate.id)
|
||||
return if (existing == null) {
|
||||
database.heartRateDao.insertNewEntry(heartRate).let {
|
||||
TransactionResult(listOf(heartRate), emptyList()) }
|
||||
} else {
|
||||
database.heartRateDao.updateExistingEntry(heartRate)
|
||||
TransactionResult(emptyList(), listOf(heartRate))
|
||||
}
|
||||
}
|
||||
|
||||
data class TransactionResult(val inserted: List<HeartRate>, val updated: List<HeartRate>)
|
||||
}
|
|
@ -24,3 +24,11 @@ android.useAndroidX=true
|
|||
android.nonTransitiveRClass=true
|
||||
# Cache is causeing issues with CircleCI nad maybe Studio 2021
|
||||
# org.gradle.unsafe.configuration-cache=true
|
||||
|
||||
# After migration to kotlin 1.8.21
|
||||
#e: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during psi2ir
|
||||
# File being compiled: (37,18) in /home/circleci/project/core/interfaces/src/main/java/info/nightscout/interfaces/pump/defs/PumpCapability.kt
|
||||
# The root cause org.jetbrains.kotlin.psi2ir.generators.ErrorExpressionException was thrown at: org.jetbrains.kotlin.psi2ir.generators.ErrorExpressionGenerator.generateErrorCall(ErrorExpressionGenerator.kt:100)
|
||||
# null: KtCallExpression
|
||||
# https://youtrack.jetbrains.com/issue/KT-58027
|
||||
kapt.use.jvm.ir=false
|
||||
|
|
|
@ -87,6 +87,7 @@ class OverviewDataImpl @Inject constructor(
|
|||
dsMinSeries = LineGraphSeries()
|
||||
treatmentsSeries = PointsWithLabelGraphSeries()
|
||||
epsSeries = PointsWithLabelGraphSeries()
|
||||
heartRateGraphSeries = LineGraphSeries()
|
||||
}
|
||||
|
||||
override fun initRange() {
|
||||
|
@ -322,4 +323,6 @@ class OverviewDataImpl @Inject constructor(
|
|||
override val dsMinScale = Scale()
|
||||
override var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
override var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
override var heartRateScale = Scale()
|
||||
override var heartRateGraphSeries: LineGraphSeries<DataPointWithLabelInterface> = LineGraphSeries()
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class ProfileFunctionImpl @Inject constructor(
|
|||
override fun getProfileNameWithRemainingTime(): String =
|
||||
getProfileName(System.currentTimeMillis(), customized = true, showRemainingTime = true)
|
||||
|
||||
fun getProfileName(time: Long, customized: Boolean, showRemainingTime: Boolean): String {
|
||||
private fun getProfileName(time: Long, customized: Boolean, showRemainingTime: Boolean): String {
|
||||
var profileName = rh.gs(info.nightscout.core.ui.R.string.no_profile_set)
|
||||
|
||||
val profileSwitch = repository.getEffectiveProfileSwitchActiveAt(time).blockingGet()
|
||||
|
|
|
@ -113,12 +113,13 @@ class CommandQueueImplementation @Inject constructor(
|
|||
return@subscribe
|
||||
}
|
||||
aapsLogger.debug(LTag.PROFILE, "onEventProfileSwitchChanged")
|
||||
val effective = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet()
|
||||
profileFunction.getRequestedProfile()?.let {
|
||||
setProfile(ProfileSealed.PS(it), it.interfaceIDs.nightscoutId != null, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
uiInteraction.runAlarm(result.comment, rh.gs(info.nightscout.core.ui.R.string.failed_update_basal_profile), info.nightscout.core.ui.R.raw.boluserror)
|
||||
} else if (result.enacted) {
|
||||
} else if (result.enacted || effective is ValueWrapper.Existing && effective.value.originalEnd < dateUtil.now() && effective.value.originalDuration != 0L) {
|
||||
val nonCustomized = ProfileSealed.PS(it).convertToNonCustomizedProfile(dateUtil)
|
||||
EffectiveProfileSwitch(
|
||||
timestamp = dateUtil.now(),
|
||||
|
@ -421,7 +422,7 @@ class CommandQueueImplementation @Inject constructor(
|
|||
}
|
||||
|
||||
// returns true if command is queued
|
||||
override fun setProfile(profile: Profile, hasNsId: Boolean, callback: Callback?): Boolean {
|
||||
fun setProfile(profile: ProfileSealed, hasNsId: Boolean, callback: Callback?): Boolean {
|
||||
if (isRunning(CommandType.BASAL_PROFILE)) {
|
||||
aapsLogger.debug(LTag.PUMPQUEUE, "Command is already executed")
|
||||
callback?.result(PumpEnactResult(injector).success(true).enacted(false))?.run()
|
||||
|
|
|
@ -19,6 +19,7 @@ import androidx.appcompat.app.AppCompatDelegate
|
|||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.content.ContextCompat
|
||||
import info.nightscout.core.ui.getThemeColor
|
||||
import info.nightscout.core.ui.locale.LocaleHelper
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import java.util.Locale
|
||||
|
@ -29,15 +30,12 @@ import javax.inject.Inject
|
|||
*/
|
||||
class ResourceHelperImpl @Inject constructor(var context: Context, private val fabricPrivacy: FabricPrivacy) : ResourceHelper {
|
||||
|
||||
override fun updateContext(ctx: Context?) {
|
||||
ctx?.let { context = it }
|
||||
}
|
||||
|
||||
override fun gs(@StringRes id: Int): String = context.getString(id)
|
||||
override fun gs(@StringRes id: Int): String =
|
||||
context.createConfigurationContext(Configuration().apply { setLocale(LocaleHelper.currentLocale(context)) }).resources.getString(id)
|
||||
|
||||
override fun gs(@StringRes id: Int, vararg args: Any?): String {
|
||||
return try {
|
||||
context.getString(id, *args)
|
||||
context.createConfigurationContext(Configuration().apply { setLocale(LocaleHelper.currentLocale(context)) }).resources.getString(id, *args)
|
||||
} catch (exception: Exception) {
|
||||
val resourceName = context.resources.getResourceEntryName(id)
|
||||
val resourceValue = context.getString(id)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<string name="alert_r7_description"><![CDATA[Kiekis: <b>%1$d%%</b>\nTrukmė: <b>%2$s h</b>]]></string>
|
||||
<string name="alert_w31_description"><![CDATA[Rezervuaro tūris: <b>%1$s U</b>]]></string>
|
||||
<string name="alert_w32_description">Pakeiskite bateriją.</string>
|
||||
<string name="alert_w33_description">Nustatykite laiką/datą.</string>
|
||||
<string name="alert_w33_description">Nustatyti laiką/datą.</string>
|
||||
<string name="alert_w34_description">Kreipkitės į Accu-Chek palaikymo tarnybą.</string>
|
||||
<string name="alert_w36_description"><![CDATA[Kiekis: <b>%1$d%%</b><br/>Trukmė: <b>%2$s h</b>]]></string>
|
||||
<string name="alert_w38_description"><![CDATA[Suprogramuota: <b>%1$s U</b><br/>Suleista: <b>%2$s U</b>]]></string>
|
||||
|
@ -16,8 +16,8 @@
|
|||
<string name="alert_m26_description">Pakeiskite rezervuarą.</string>
|
||||
<string name="alert_m27_description">Iš naujo paleiskite duomenų atsisiuntimą.</string>
|
||||
<string name="alert_m28_description">Patikrinkite pompos statusą.</string>
|
||||
<string name="alert_m29_description">Nustatykite baterijos tipą.</string>
|
||||
<string name="alert_m30_description">Nustatykite rezervuaro tipą.</string>
|
||||
<string name="alert_m29_description">Nustatyti baterijos tipą.</string>
|
||||
<string name="alert_m30_description">Nustatyti rezervuaro tipą.</string>
|
||||
<string name="alert_e6_description">Pakeiskite bateriją ir rezervuarą.</string>
|
||||
<string name="alert_e10_description">Pakeiskite rezervuarą.</string>
|
||||
<string name="alert_e13_description">Pakeiskite kalbą.</string>
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.view.MenuInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import dagger.android.support.DaggerFragment
|
||||
|
@ -72,7 +73,7 @@ class OpenAPSFragment : DaggerFragment(), MenuProvider {
|
|||
|
||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||
menu.add(Menu.FIRST, ID_MENU_RUN, 0, rh.gs(R.string.openapsma_run)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.setGroupDividerEnabled(true)
|
||||
MenuCompat.setGroupDividerEnabled(menu, true)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean =
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.view.MenuInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import dagger.android.support.DaggerFragment
|
||||
|
@ -74,7 +75,7 @@ class LoopFragment : DaggerFragment(), MenuProvider {
|
|||
|
||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||
menu.add(Menu.FIRST, ID_MENU_RUN, 0, rh.gs(R.string.run_now)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.setGroupDividerEnabled(true)
|
||||
MenuCompat.setGroupDividerEnabled(menu, true)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean =
|
||||
|
@ -169,4 +170,4 @@ class LoopFragment : DaggerFragment(), MenuProvider {
|
|||
binding.smbsetbypump.text = ""
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -218,7 +218,7 @@ class LoopPlugin @Inject constructor(
|
|||
val start = dateUtil.now()
|
||||
while (start + T.mins(maxMinutes).msecs() > dateUtil.now()) {
|
||||
if (commandQueue.size() == 0 && commandQueue.performing() == null) return true
|
||||
SystemClock.sleep(100)
|
||||
SystemClock.sleep(1000)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -247,10 +247,16 @@ class LoopPlugin @Inject constructor(
|
|||
return
|
||||
}
|
||||
|
||||
if (!isEmptyQueue()) {
|
||||
aapsLogger.debug(LTag.APS, rh.gs(info.nightscout.core.ui.R.string.pump_busy))
|
||||
rxBus.send(EventLoopSetLastRunGui(rh.gs(info.nightscout.core.ui.R.string.pump_busy)))
|
||||
return
|
||||
}
|
||||
|
||||
// Check if pump info is loaded
|
||||
if (pump.baseBasalRate < 0.01) return
|
||||
val usedAPS = activePlugin.activeAPS
|
||||
if ((usedAPS as PluginBase).isEnabled()) {
|
||||
if (usedAPS.isEnabled()) {
|
||||
usedAPS.invoke(initiator, tempBasalFallback)
|
||||
apsResult = usedAPS.lastAPSResult
|
||||
}
|
||||
|
@ -261,12 +267,6 @@ class LoopPlugin @Inject constructor(
|
|||
return
|
||||
}
|
||||
|
||||
if (!isEmptyQueue()) {
|
||||
aapsLogger.debug(LTag.APS, rh.gs(info.nightscout.core.ui.R.string.pump_busy))
|
||||
rxBus.send(EventLoopSetLastRunGui(rh.gs(info.nightscout.core.ui.R.string.pump_busy)))
|
||||
return
|
||||
}
|
||||
|
||||
// Prepare for pumps using % basals
|
||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) {
|
||||
apsResult.usePercent = true
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<string name="description_ama">2017 m. algoritmas</string>
|
||||
<string name="description_smb">Naujausias algoritmas patyrusiems vartotojams</string>
|
||||
<string name="description_smb_dynamic_isf">Naujausias algoritmas patyrusiems naudotojams su dinaminiu/automatiniu JIF</string>
|
||||
<string name="openapsama_bolus_snooze_dia_divisor">Boluso snaudimo daliklis</string>
|
||||
<string name="openapsama_bolus_snooze_dia_divisor">Atidėjimo po boluso IVT daliklis</string>
|
||||
<string name="openapsma_run">Paleisti dabar</string>
|
||||
<string name="openapsma_last_run_label">Paskutinis veiksmas</string>
|
||||
<string name="openapsma_input_parameters_label">Įvesties parametrai</string>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<string name="openapsama_min_5m_carb_impact_summary">Numatytoji reikšmė: 3.0 (AMA) arba 8.0 (SMB). Tai parametras, nurodantis angliavandenių poveikį glikemijai kas 5 minutes nuo jų suvartojimo. Numatytoji reikšmė yra 3 mg/dl per 5min. Šis skaičius turi įtakos apskaičiavimams, kaip greitai mažės AAO, kokia bus glikemijos kitimo prognozė, ypač kai ji krenta daugiau nei tikėtasi, arba nedidėja tiek, kiek tikėtasi.</string>
|
||||
<string name="openapsama_max_daily_safety_multiplier_summary">Numatytoji reikšmė: 3 tai pagrindinis OpenAPS saugiklis. Jis apriboja Jūsų valandinę bazę iki trigubos maksimalios valandinės bazės (standartiniu atveju). Jums greičiausiai neprireiks šios reikšmės keisti, tačiau turėtumėte žinoti, kad ji naudojama kaip saugiklis apskaičiuojant \"3x maksimali dienos bazė; 4x dabartinė valandinė bazė\".</string>
|
||||
<string name="openapsama_current_basal_safety_multiplier_summary">Numatytoji reikšmė: 4 tai antras pagrindinis OpenAPS saugiklis, apskaičiuojant \"3x maksimali dienos bazė; 4x dabartinė valandinė bazė\". Jis reiškia, kad jūsų valandinė bazė, nepriklausomai nuo to, kokia maksimali valandinė bazė suprogramuota pompoje, negali būti didesnė, nei keturguba dabartinė valandinė bazė. Tai apsaugo Jus nuo pavojingų situacijų, kai nustatoma pernelyg didelė valandinė bazė, pilnai nesuprantant, kaip veikia algoritmas. Numatytoji reikšmė yra 4x; daugumai vartotojų niekada neprireikia šio skaičiaus keisti, o pajutus, kad \"atsitrenkiama\" į saugiklį, rekomenduojama peržiūrėti kitus nustatymus.</string>
|
||||
<string name="openapsama_bolus_snooze_dia_divisor_summary">Numatytoji reikšmė: 2\nBoluso snaudimas aktyvuojamas iškart po to, kai susileidžiate bolusą maistui. Ši funkcija neleidžia sistemai nustatyti mažų LBD iškart po valgio. Pvz.: jei IVT yra 3 val, tai boluso snaudimas pamažu deaktyvuojamas per 1,5 val (3 val. / 2).</string>
|
||||
<string name="openapsama_bolus_snooze_dia_divisor_summary">Numatytoji reikšmė: 2\nAtidėjimas po boluso aktyvuojamas iškart po to, kai susileidžiate bolusą maistui. Ši funkcija neleidžia sistemai nustatyti mažų laikinų bazių iškart po valgio. Pvz.: jei IVT yra 3 val, tai atidėjimas po boluso pamažu deaktyvuojamas per 1,5 val (3 val. / 2).</string>
|
||||
<string name="openapsama_link_to_preference_json_doc_txt">Dėmesio!\nPaprastai neturėtumėte keisti šių, žemiau esančių, reikšmių. Prašome PASPAUSTI ČIA ir PERSKAITYKITE tekstą ir įsitikinkite, kad SUPRANTATE prieš keisdami bet kurią iš šių verčių.</string>
|
||||
<string name="always_use_short_avg">Visada naudoti trumpo laikotarpio vidutinį pokyti vietoj paprasto pokyčio</string>
|
||||
<string name="always_use_short_avg_summary">Naudinga, kai duomenys, gaunami iš nefiltruoto šaltinio, tokio kaip xDrip+, tampa nestabilūs.</string>
|
||||
|
|
|
@ -16,6 +16,7 @@ import android.widget.ImageView
|
|||
import android.widget.LinearLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.util.forEach
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
|
@ -97,7 +98,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener, MenuProvider {
|
|||
actionHelper.onCreateOptionsMenu(menu, inflater)
|
||||
menu.add(Menu.FIRST, ID_MENU_ADD, 0, rh.gs(R.string.add_automation)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.add(Menu.FIRST, ID_MENU_RUN, 0, rh.gs(R.string.run_automations)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
menu.setGroupDividerEnabled(true)
|
||||
MenuCompat.setGroupDividerEnabled(menu, true)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean =
|
||||
|
@ -309,4 +310,4 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener, MenuProvider {
|
|||
}
|
||||
}.show(childFragmentManager, "EditEventDialog")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,13 +27,13 @@
|
|||
<string name="sendsmsactionlabel">Siųsti SMS: %1$s</string>
|
||||
<string name="sendsmsactiondescription">Siųsti SMS į visus numerius</string>
|
||||
<string name="sendsmsactiontext">Išsiųsti SMS žinutę su tekstu</string>
|
||||
<string name="starttemptarget">Nustatykite laikiną tikslą</string>
|
||||
<string name="islesser">mažesnis nei</string>
|
||||
<string name="isequalorlesser">lygus arba mažesnis nei</string>
|
||||
<string name="isequal">yra lygus</string>
|
||||
<string name="isequalorgreater">yra lygus arba didesnis nei</string>
|
||||
<string name="isgreater">didesnis nei</string>
|
||||
<string name="isnotavailable">negalimas</string>
|
||||
<string name="starttemptarget">Pradėti laikiną tikslą</string>
|
||||
<string name="islesser">mažiau nei</string>
|
||||
<string name="isequalorlesser">lygu arba mažiau nei</string>
|
||||
<string name="isequal">lygu</string>
|
||||
<string name="isequalorgreater">lygu arba daugiau nei</string>
|
||||
<string name="isgreater">daugiau nei</string>
|
||||
<string name="isnotavailable">nėra duomenų</string>
|
||||
<string name="glucoseisnotavailable">Glikemija nepasiekiama</string>
|
||||
<string name="glucosecomparedmgdl">Glikemija %1$s %2$.0f %3$s</string>
|
||||
<string name="glucosecomparedmmol">Glikemija %1$s %2$.1f %3$s</string>
|
||||
|
|
|
@ -22,16 +22,16 @@ class TriggerWifiSsidTest : TriggerTestBase() {
|
|||
@Test fun shouldRunTest() {
|
||||
val e = EventNetworkChange()
|
||||
`when`(receiverStatusStore.lastNetworkEvent).thenReturn(e)
|
||||
var t: TriggerWifiSsid = TriggerWifiSsid(injector).setValue("aSSID").comparator(Comparator.Compare.IS_EQUAL)
|
||||
var t: TriggerWifiSsid = TriggerWifiSsid(injector).setValue("aSSID 1").comparator(Comparator.Compare.IS_EQUAL)
|
||||
e.wifiConnected = false
|
||||
Assert.assertFalse(t.shouldRun())
|
||||
e.wifiConnected = true
|
||||
e.ssid = "otherSSID"
|
||||
Assert.assertFalse(t.shouldRun())
|
||||
e.wifiConnected = true
|
||||
e.ssid = "aSSID"
|
||||
e.ssid = "aSSID 1"
|
||||
Assert.assertTrue(t.shouldRun())
|
||||
t = TriggerWifiSsid(injector).setValue("aSSID").comparator(Comparator.Compare.IS_NOT_AVAILABLE)
|
||||
t = TriggerWifiSsid(injector).setValue("aSSID 1").comparator(Comparator.Compare.IS_NOT_AVAILABLE)
|
||||
e.wifiConnected = false
|
||||
Assert.assertTrue(t.shouldRun())
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() {
|
|||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setTheme(info.nightscout.core.ui.R.style.AppTheme_NoActionBar)
|
||||
rh.updateContext(this)
|
||||
|
||||
compositeDisposable.add(rxBus.toObservable(EventThemeSwitch::class.java).subscribe {
|
||||
recreate()
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package info.nightscout.configuration.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import info.nightscout.configuration.R
|
||||
import info.nightscout.core.ui.locale.LocaleHelper
|
||||
import info.nightscout.interfaces.plugin.ActivePlugin
|
||||
import info.nightscout.interfaces.plugin.PluginBase
|
||||
import info.nightscout.interfaces.protection.ProtectionCheck
|
||||
|
@ -60,8 +58,4 @@ class SingleFragmentActivity : DaggerAppCompatActivityWithResult() {
|
|||
if (plugin?.preferencesId != -1) menuInflater.inflate(R.menu.menu_single_fragment, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -5,14 +5,14 @@ import android.view.View
|
|||
import android.widget.CheckBox
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.configuration.R
|
||||
import info.nightscout.configuration.databinding.ActivityLogsettingBinding
|
||||
import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity
|
||||
import info.nightscout.rx.interfaces.L
|
||||
import info.nightscout.rx.interfaces.LogElement
|
||||
import javax.inject.Inject
|
||||
|
||||
class LogSettingActivity : DaggerAppCompatActivity() {
|
||||
class LogSettingActivity : TranslatedDaggerAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var l: L
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.configuration.maintenance.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
@ -10,12 +9,11 @@ import android.view.ViewGroup
|
|||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.configuration.R
|
||||
import info.nightscout.configuration.databinding.MaintenanceImportListActivityBinding
|
||||
import info.nightscout.configuration.databinding.MaintenanceImportListItemBinding
|
||||
import info.nightscout.configuration.maintenance.PrefsFileContract
|
||||
import info.nightscout.core.ui.locale.LocaleHelper
|
||||
import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity
|
||||
import info.nightscout.interfaces.maintenance.PrefFileListProvider
|
||||
import info.nightscout.interfaces.maintenance.PrefsFile
|
||||
import info.nightscout.interfaces.maintenance.PrefsMetadataKey
|
||||
|
@ -23,7 +21,7 @@ import info.nightscout.interfaces.maintenance.PrefsStatus
|
|||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class PrefImportListActivity : DaggerAppCompatActivity() {
|
||||
class PrefImportListActivity : TranslatedDaggerAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var prefFileListProvider: PrefFileListProvider
|
||||
|
@ -116,8 +114,4 @@ class PrefImportListActivity : DaggerAppCompatActivity() {
|
|||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import android.widget.TextView
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.configuration.setupwizard.SWNumberValidator
|
||||
import info.nightscout.core.ui.elements.NumberPicker
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.GlucoseUnit
|
||||
import info.nightscout.interfaces.profile.Profile
|
||||
import info.nightscout.interfaces.profile.ProfileFunction
|
||||
|
@ -16,12 +17,15 @@ import info.nightscout.shared.SafeParse
|
|||
import java.text.DecimalFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
class SWEditNumberWithUnits(injector: HasAndroidInjector, private val init: Double, private val min: Double, private val max: Double) : SWItem(injector, Type.UNIT_NUMBER) {
|
||||
class SWEditNumberWithUnits(injector: HasAndroidInjector, private val init: Double, private val minMmol: Double, private val maxMmol: Double) : SWItem(injector, Type.UNIT_NUMBER) {
|
||||
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
|
||||
private val validator: SWNumberValidator =
|
||||
SWNumberValidator { value -> value in min..max }
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MMOL)
|
||||
SWNumberValidator { value -> value in minMmol..maxMmol }
|
||||
else
|
||||
SWNumberValidator { value -> value in minMmol * Constants.MMOLL_TO_MGDL..maxMmol * Constants.MMOLL_TO_MGDL }
|
||||
private var updateDelay = 0
|
||||
|
||||
override fun generateDialog(layout: LinearLayout) {
|
||||
|
@ -44,7 +48,10 @@ class SWEditNumberWithUnits(injector: HasAndroidInjector, private val init: Doub
|
|||
var initValue = sp.getDouble(preferenceId, init)
|
||||
initValue = Profile.toCurrentUnits(profileFunction.getUnits(), initValue)
|
||||
val numberPicker = NumberPicker(context)
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MMOL) numberPicker.setParams(initValue, min, max, 0.1, DecimalFormat("0.0"), false, null, watcher) else numberPicker.setParams(initValue, min * 18, max * 18, 1.0, DecimalFormat("0"), false, null, watcher)
|
||||
if (profileFunction.getUnits() == GlucoseUnit.MMOL)
|
||||
numberPicker.setParams(initValue, minMmol, maxMmol, 0.1, DecimalFormat("0.0"), false, null, watcher)
|
||||
else
|
||||
numberPicker.setParams(initValue, minMmol * Constants.MMOLL_TO_MGDL, maxMmol * Constants.MMOLL_TO_MGDL, 1.0, DecimalFormat("0"), false, null, watcher)
|
||||
|
||||
layout.addView(numberPicker)
|
||||
val c = TextView(context)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".constraints.objectives.ObjectivesFragment">
|
||||
tools:context="info.nightscout.plugins.constraints.objectives.ObjectivesFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Pas basale en verhoudings aan as nodig, en dan aktiveer auto-sens</string>
|
||||
<string name="objectives_autosens_gate">1 week suksesvolle dagtyd lus met gereelde karb toevoegings</string>
|
||||
<string name="objectives_smb_objective">Skakel bykomende nutsfunskies aan vir bedags gebruik, soos bv. SMB</string>
|
||||
<string name="objectives_smb_gate">Jy moet asb die wiki lees en verhoog maksIAB om SMBs te laat werk! \'n Goeie begin is maksIAB = gemiddelde ete bolus + 3 x maks daaglikse basale</string>
|
||||
<string name="objectives_manualenacts">Per hand aksies</string>
|
||||
<string name="accomplished">Bereik: %1$s</string>
|
||||
<string name="objectives_useprofileswitch">Stel profiel 90% vir 10 min (Lang-pers profiel naam op Oorsig)</string>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<string name="objectives_autosens_gate">Една седмица успешно дневно използване с редовно въвеждане на въглехидрати</string>
|
||||
<string name="objectives_autosens_learned">Ако вашият резултат от autosens не се колебае около 100%, вашият профил вероятно е грешен.</string>
|
||||
<string name="objectives_smb_objective">Добавяне на допълнителни функции за използване през деня, като SMB</string>
|
||||
<string name="objectives_smb_gate">Трябва да прочетете wiki и увеличите maxIOB за да може SMB да работи добре! Добро начало е maxIOB = средния болус за хранене + 3 пъти най-големия базал от профила</string>
|
||||
<string name="objectives_smb_learned">Използването на SMB трябва да е вашата основна цел. Алгоритъмът Oref1 е създаден, за да ви помогне и с вашите болуси. Не трябва да давате пълен болус за вашата храна, а само част от него и оставете AAPS да ви даде останалото, ако е необходимо. По този начин имате по-голям диапазон за грешно изчислени въглехидрати. Знаете ли, че можете да зададете процент от резултата от болус калкулатора, за да намалите размера на болуса?</string>
|
||||
<string name="objectives_auto_objective">Разрешаване на автоматизация</string>
|
||||
<string name="objectives_auto_gate">Прочетете документацията за това как работи автоматизацията. Настройте първите си прости правила. Нека AAPS показва само известия. Когато сте сигурни, автоматизацията се задейства в точното време, за да заменете известяването с реални действия. (https: //androidaps.readthedocs.io/en/latest/EN/Usage/Automation.html)</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Ajustar basals i ràtios si cal, i després activar auto-sens</string>
|
||||
<string name="objectives_autosens_gate">1 setmana d\'èxit en mode llaç tancat durant el dia, amb introducció regular de carbohidrats</string>
|
||||
<string name="objectives_smb_objective">Activant funcions addicionals d\'ús diurn, com l\'SMB (super micro bolus)</string>
|
||||
<string name="objectives_smb_gate">Heu de llegir la wiki i augmentar la maxIOB per a què l\'SMB funcioni correctament! Una bona manera de començar és amb maxIOB = bolus d\'àpat mig + 3 x màxima basal diària</string>
|
||||
<string name="objectives_auto_objective">Activant l\'automatització</string>
|
||||
<string name="objectives_manualenacts">Activació manual</string>
|
||||
<string name="accomplished">Completat: %1$s</string>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<string name="objectives_autosens_gate">Jeden týden úspěšného používání s běžným příjmem sacharidů</string>
|
||||
<string name="objectives_autosens_learned">Pokud váš výsledek autosens neosciluje kolem 100%, nastavení Vašeho profilu pravděpodobně špatné.</string>
|
||||
<string name="objectives_smb_objective">Povolit další funkce pro běžné používání jako SMB</string>
|
||||
<string name="objectives_smb_gate">Přečíst si dokumentaci a zvýšit maximální IOB, aby mohlo SMB fungovat. Pro začátek se dá použít velikost běžného bolusu + 3x maximální denní bazál</string>
|
||||
<string name="objectives_smb_gate">Přečíst si dokumentaci a zvýšit maximání IOB, aby mohlo SMB fungovat. Pro začátek se dá použít velikost běžného bolusu + 3x maximální denní bazál</string>
|
||||
<string name="objectives_smb_learned">Použití SMB je vaším cílem. Oref1 algoritmus byl navržen tak, aby vám pomohl i s vašimi bolusy. Neměli byste dávat úplný bolus pro vaše jídlo, ale jen jeho část a nechtat AAPS v případě potřeby dát zbytek. Takto máte větší rezervu pro špatně vypočtené sacharidy. Věděli jste, že můžete nastavit procento bolusové kalkulačky pro snížení velikosti bolusu?</string>
|
||||
<string name="objectives_auto_objective">Povolení automatizace</string>
|
||||
<string name="objectives_auto_gate">Přečtěte si na wiki, jak automatizace funguje. Nejdříve nastavte pouze jednoduchá pravidla. Namísto provádění akcí nechte AAPS zobrazovat pouze oznámení. Pokud jste si jistí, že je automatizace spouštěna v pravý čas, můžete oznámení nahradit prováděním akce. (https://wiki.aaps.app/cs/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Justér om nødvendigt basaler og forhold og aktivér derefter auto-sens</string>
|
||||
<string name="objectives_autosens_gate">1 uges vellykket looping i dagtimerne med alle måltider tastet ind</string>
|
||||
<string name="objectives_smb_objective">Aktivering af yderligere funktioner til brug i dagtimerne, såsom SMB</string>
|
||||
<string name="objectives_smb_gate">Du skal læse wikien og hæve maxIOB for at få SMB\'er til at fungere fint! En god start er maxIOB=gennemsnitlig måltidsbolus + 3 x max daglig basal</string>
|
||||
<string name="objectives_auto_objective">Aktiverer automatisering</string>
|
||||
<string name="objectives_manualenacts">Manuelle handlinger</string>
|
||||
<string name="accomplished">Udført: %1$s</string>
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
<string name="objectives_autosens_gate">Loope eine Woche tagsüber mit regelmäßiger Kohlenhydrat-Eingabe</string>
|
||||
<string name="objectives_autosens_learned">Wenn Ihr Autosens Ergebnis nicht stündlich schwankt, um die angestrebten 100 % ist das verwendete Profil wahrscheinlich falsch.</string>
|
||||
<string name="objectives_smb_objective">Aktiviere zusätzliche Funktionen für die Nutzung tagsüber wie z. B. SMB</string>
|
||||
<string name="objectives_smb_gate">Lies das Wiki und erhöhe maxIOB, damit der SMB gut funktioniert. Ein guter Anfang ist
|
||||
die Formel maxIOB = durchschnittlicher Essensbolus + 3 x höchste Basalrate</string>
|
||||
<string name="objectives_smb_learned">Die Verwendung von SMB ist Dein Ziel. Der Oref1-Algorithmus wurde entwickelt, um Dir auch mit Boli zu helfen. Du solltest nicht den vollen Bolus für Dein Essen geben, sondern nur einen Teil davon abgeben und es AAPS überlassen bei Bedarf den notwendigen Rest entsprechend dem Blutzuckerverlauf zugeben zu lassen. Auf diese Weise hast Du mehr Platz für falsch berechnete Kohlenhydrate. Wusstest Du, dass Du einen Prozentsatz bei Verwendung des Bolusrechners festlegen kannst, um die Größe des Bolus zu reduzieren?</string>
|
||||
<string name="objectives_auto_objective">Automatisierung aktivieren</string>
|
||||
<string name="objectives_auto_gate">Lies in der Dokumentation nach, wie die Automation funktioniert. Richte Dir erst einfache Regeln ein. Zunächst sollte AAPS keine Änderungen vornehmen, sondern Dir nur eine Benachrichtigung anzeigen. Wenn Du Dir sicher bist, dass die Automation im richtigen Moment angetriggert wird, dann kannst Du die Benachrichtigung durch eine Aktion ersetzen (https://androidaps.readthedocs.io/de/latest/CROWDIN/de/Usage/Automation.html)</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Ρυθμίστε τον βασικό ρυθμό και τις αναλογίες αν χρειάζεται, και μετά ενεργοποιήστε το auto-sens</string>
|
||||
<string name="objectives_autosens_gate">1 επιτυχής εβδομάδα ημερήσιου κυκλώματος με κανονική εισαγωγή υδατανθράκων</string>
|
||||
<string name="objectives_smb_objective">Ενεργοποιώντας επιπρόσθετα χαρακτηριστικά για χρήση κατά την ημέρα, όπως το SMB</string>
|
||||
<string name="objectives_smb_gate">Πρέπει να διαβάσετε τον οδηγό wiki και να αυξήσετε το ανώτατο όριο του IOB για να μπορέσει να λειτουργήσει σωστά το SMB! Μια καλή αρχή είναι μέγιστο IOB= μέσο bolus γεύματος + 3 x το μέγιστο ημερήσιο βασικού ρυθμού</string>
|
||||
<string name="objectives_manualenacts">Ξεκινήστε χειροκίνητα</string>
|
||||
<string name="accomplished">Επιτεύχθηκε: %1$s</string>
|
||||
<string name="objectives_useprofileswitch">Θέστε το προφίλ στο 90% για 10 λεπτά (Παρατεταμένο πάτημα του προφίλ στην Επισκόπηση)</string>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<string name="objectives_autosens_gate">Una semana con éxito en bucle cerrado durante el día con entrada regular de carbohidratos</string>
|
||||
<string name="objectives_autosens_learned">Si el resultado de tu autosens no oscila en torno al 100% es probable que tu perfil esté equivocado.</string>
|
||||
<string name="objectives_smb_objective">Habilitar funciones adicionales para uso durante el día como SMB</string>
|
||||
<string name="objectives_smb_gate">¡Debes leer el wiki y subir maxIOB para que SMB funcione bien! Para comenzar un buen valor sería maxIOB = bolo de comida medio + 3 x máximo basal diario</string>
|
||||
<string name="objectives_smb_gate">Debes leer la wiki y aumentar el valor de maxIOB para que SMB funcione bien. Un buen comienzo sería maxIOB = bolo de comida promedio + 3x máxima basal diaria</string>
|
||||
<string name="objectives_smb_learned">Utilizar SMB es su objetivo. El algoritmo Oref1 fue diseñado para ayudarle también con sus bolos. No debe dar un bolo completo para su comida, sino sólo una parte y dejar que AAPS le dé el resto si es necesario. De esta forma tendrás más espacio para los carbohidratos mal calculados. ¿Sabías que puedes establecer un porcentaje del resultado de la calculadora de bolo para reducir el tamaño del bolo?</string>
|
||||
<string name="objectives_auto_objective">Activar automatización</string>
|
||||
<string name="objectives_auto_gate">Lee la documentación sobre el funcionamiento de la automatización. Configure sus primeras reglas simples. En lugar de una acción, deja que AAPS muestre sólo una notificación. Cuando esté seguro de que la automatización se activa en el momento adecuado, sustituya la notificación por una acción real. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<string name="objectives_autosens_gate">1 semaine de Boucle Fermée en journée en saisissant régulièrement les glucides</string>
|
||||
<string name="objectives_autosens_learned">Si le résultat de votre autosens n\'est pas autour de 100%, votre profil est probablement erroné.</string>
|
||||
<string name="objectives_smb_objective">Activation de fonctionnalités supplémentaires pour l\'utilisation en journée, telles que la fonction SMB</string>
|
||||
<string name="objectives_smb_gate">Lisez le wiki et augmentez le maxIA pour que les SMBs fonctionnent correctement ! Un bon début est maxIA = moyenne des Bolus Repas + 3 x maximum débit Basal quotidien</string>
|
||||
<string name="objectives_smb_gate">Vous devez lire le wiki et augmenter le maxIA pour faire fonctionner les SMB ! Un bon début est maxIA = moyenne des bolus repas + 3 fois le basal le plus élevé</string>
|
||||
<string name="objectives_smb_learned">L\'utilisation de SMB est votre objectif. L\'algorithme Oref1 a été conçu pour vous aider également avec vos bolus. Vous ne devriez pas donner un bolus complet pour votre nourriture, mais seulement une partie de celui-ci et laisser AAPS vous donner le reste si nécessaire. De cette façon, vous avez plus de latitude pour les glucides mal calculés. Saviez-vous que vous pouvez définir un pourcentage à appliquer au résultat de la calculatrice de bolus pour réduire la taille du bolus ?</string>
|
||||
<string name="objectives_auto_objective">Activation de l\'automatisation</string>
|
||||
<string name="objectives_auto_gate">Lisez la documentation sur le fonctionnement de l\'automatisation fonctionne. Configurez vos premières règles simples. Au lieu de mettre une action, configurez une notification. Quand vous êtes sûr que l\'automatisation est déclenchée au bon moment, remplacez la notification par une action réelle. (https://wiki.aaps.app/fr/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<string name="objectives_autosens_gate">שבוע של הפעלה מוצלחת של הלולאה במשך שעות היום, עם רישום ערכי פחמימות בקביעות</string>
|
||||
<string name="objectives_autosens_learned">אם תוצאת הזיהוי האוטומטי שלכם לא מתנודדת סביב 100%, כנראה שהפרופיל טעון שיפור.</string>
|
||||
<string name="objectives_smb_objective">הפעלת פונקציות נוספות לשימוש במשך היום, כגון סופר מיקרו בולוסים (SMB)</string>
|
||||
<string name="objectives_smb_gate">חובה לקרוא את הויקי ולהעלות את ערך ה-maxIOB כדי להפעיל את ה- SMB כראוי. התחלה טובה תהיה maxIOB=בולוס ממוצע + 3 פעמים ערך הבזאלי היומי המקסימלי</string>
|
||||
<string name="objectives_smb_gate">חובה לקרוא את הויקי ולהעלות את ערך האינסולין הפעיל המרבי (maxIOB) כדי להפעיל את ה- SMB כראוי. התחלה טובה תהיה maxIOB=בולוס ארוחה טיפוסי + 3 פעמים ערך הבזאלי המקסימלי ביממה</string>
|
||||
<string name="objectives_smb_learned">שימוש ב-SMB הוא המטרה שלכם. אלגוריתם Oref1 תוכנן לעזור גם עם הבולוסים שלכם. אתם לא צריכים להזריק בולוס מלא למזון שלכם אלא רק על חלק ממנו ולתת ל-AAPS לטפל בשאר במידת הצורך. כך קל יותר להכיל טעויות בספירת פחמימות. הידעתם שאפשר להגדיר אחוז מתוצאת מחשבון הבולוס כדי להקטין את גודל הבולוס?</string>
|
||||
<string name="objectives_auto_objective">הפעלת אוטומציה</string>
|
||||
<string name="objectives_auto_gate">קראו את המסמכים על אופן הפעולה של אוטומציות. הגדירו את התנאים הפשוטים הראשונים שלכם. במקום פעולה תנו ל-AAPS להציג הודעה בלבד. כאשר אתם בטוחים שהאוטומציה מופעלת בזמן הנכון, החליפו את ההודעה בפעולה אמיתית. (https://wiki.aaps.app/he/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">필요하면 Basal과 비율을 조절하고, auto-sens를 활성화합니다</string>
|
||||
<string name="objectives_autosens_gate">섭취한 탄수화물양을 입력하고 1주일동안 낮시간대에 loop를 성공적으로 사용하여 봅니다</string>
|
||||
<string name="objectives_smb_objective">낮시간대에 SMB(Super Micro Bolus)같은 추가기능을 활성화해 사용해봅니다</string>
|
||||
<string name="objectives_smb_gate">SMB가 잘 작동하게 하기위해서 wiki를 반드시 읽은 다음 maxIOB 값을 올려보세요! maxIOB=평균 식사 Bolus + 3 x 최대하루 Basal이면 적당한 시작값입니다</string>
|
||||
<string name="objectives_auto_objective">자동화 사용</string>
|
||||
<string name="objectives_manualenacts">수동 주입</string>
|
||||
<string name="accomplished">완료: %1$s</string>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<string name="objectives_autosens_gate">1 savaitę praleiskite sėkmingai naudodami uždarąjį ciklą dienos metu ir įvesdami visus valgomus angliavandenius</string>
|
||||
<string name="objectives_autosens_learned">Jei Jūsų autosens rezultatai nesvyruoja apie 100%, tikėtina, kad profilis turi klaidų.</string>
|
||||
<string name="objectives_smb_objective">Dienos metu aktyvuokite papildomas funkcijas, tokias kaip SMB (Super Mikro Bolusas)</string>
|
||||
<string name="objectives_smb_gate">Norėdami, kad SMB veiktų gerai, turite perskaityti dokumentaciją ir padidinti max AIO! Pradžiai patartina skaičiuoti taip: maxAIO=(didžiausia valandinė bazė x 3) + vidutinis bolusas</string>
|
||||
<string name="objectives_smb_learned">SMB yra Jūsų tikslas. Oref1 algoritmas sukurtas taip, kad taptų Jums pagalba su bolusavimu. Jūs galite nesileisti viso boluso maistui, susileiskite dalį, o AAPS padarys likusį darbą, jei reikės. Taip išvengsite klaidų dėl neteisingai apskaičiuotų AV. Ar žinote, kad galite skaičiuotuve nurodyti, kiek % apskaičiuoto boluso suleisti?</string>
|
||||
<string name="objectives_auto_objective">Automatizavimo įjungimas</string>
|
||||
<string name="objectives_auto_gate">Perskaitykite dokumentaciją apie automatizacijos veikimą. Nustatykite kelias paprastas taisykles. Nustatykite, kad AAPS tik parodytų pranešimą, o ne atliktų realų veiksmą. Kai įsitikinsite, kad automatizacija suveikia reikalingu metu, vietoj pranešimo įjunkite veiksmą. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
@ -40,7 +39,7 @@
|
|||
<string name="objectives_usedisconnectpump">Imituokite maudynes duše. Atjunkite pompą 1 valandai (ilgai paspauskite Atviras Ciklas)</string>
|
||||
<string name="objectives_usereconnectpump">... ir iš naujo prisijunkite tuo pačiu būdu</string>
|
||||
<string name="objectives_usetemptarget">Nustatykite 10 min trukmės laikiną tikslą (ilgai spausti ant dabartinio tikslo)</string>
|
||||
<string name="objectives_useactions">Konfigūracijoje įjunkite Veiksmų įskiepį, nustatykite jį matomą ir jo turinio rodymą viršutiniame meniu</string>
|
||||
<string name="objectives_useactions">Konfigūracijoje įjunkite Veiksmų įskiepį, padarykite jį ir jo turinį matomą viršutiniame meniu</string>
|
||||
<string name="objectives_useloop">Parodyti Ciklo įskiepio turinį</string>
|
||||
<string name="objectives_usescale">Panaudokite vaizdo dydžio keitimo funkciją ilgai spaudžiant ant glikemijos kreivės</string>
|
||||
<string name="objectives_exam_objective">Patvirtinkite savo žinias</string>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<string name="objectives_autosens_gate">Gedurende 1 week succesvol overdag loopen met regelmatige invoer van koolhydraten</string>
|
||||
<string name="objectives_autosens_learned">Als het resultaat van autosens zich niet rond de 100% beweegt dan is je profiel waarschijnlijk niet juist.</string>
|
||||
<string name="objectives_smb_objective">Activeren van extra functies overdag zoals SMB (super micro bolus)</string>
|
||||
<string name="objectives_smb_gate">Lees de wiki en verhoog maxIOB om SMB goed werkend te krijgen. Een goed begin is maxIOB=gemiddelde maaltijdbolus + 3 x max dagelijkse basaal</string>
|
||||
<string name="objectives_smb_learned">Het gebruik van SMB is het uiteindelijke doel. Het Oref1 algoritme is ontworpen om je ook te helpen met je bolussen. Je hoeft geen volledige bolus te geven voor jouw voeding, maar slechts een deel ervan en AAPS zal de rest geven als dat nodig is. Op deze manier heb je meer ruimte voor verkeerd berekende koolhydraten. Wist je dat je een percentage in de bolus calculator kan instellen om de hoeveelheid bolus te verminderen?</string>
|
||||
<string name="objectives_auto_objective">Automatisering inschakelen</string>
|
||||
<string name="objectives_auto_gate">Lees eerst de documentatie over hoe automatisering werkt. Maak daarna je eerste simpele regels, waarbij je in plaats van acties eerst gebruikt maakt van de notificaties. Wanneer je er dan zeker van bent, dat je automatisering op de goede momenten wordt geactiveerd, kan je de noticifcatie omzetten naar een echte actie.
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<string name="objectives_autosens_gate">1 tydzień sukcesu w działaniu pętli w ciągu dnia z regularnym wprowadzaniem spożywanych węglowodanów</string>
|
||||
<string name="objectives_autosens_learned">Jeśli wynik autosens nie oscyluje w okolicach 100%, prawdopodobnie Twój profil nie jest poprawny.</string>
|
||||
<string name="objectives_smb_objective">Włączanie dodatkowych funkcji do użytku, jak SMB (Super Mikro Bolusy)</string>
|
||||
<string name="objectives_smb_gate">Musisz przeczytać wiki i zwiększyć maxIOB, aby SMB działało dobrze! Dobrym początkiem jest maxIOB = średni bolus + 3 x maks. dzienna dawka bazowa</string>
|
||||
<string name="objectives_smb_learned">Używanie SMB jest Twoim celem. Algorytm Oref1 został zaprojektowany, aby pomóc Ci również w bolusach. Nie należy podawać pełnego bolusa do jedzenia, ale tylko jego część, a w razie potrzeby pozostawić resztę AAPS. W ten sposób masz więcej miejsca na błędnie obliczone węglowodany. Czy wiesz, że można w kalkulatorze ustawić procent wyniku bolusa, aby zmniejszyć rozmiar bolusa?</string>
|
||||
<string name="objectives_auto_objective">Włączanie automatyzacji</string>
|
||||
<string name="objectives_auto_gate">Przeczytaj dokumentację dotyczącą działania automatyzacji. Skonfiguruj swoje pierwsze proste zasady. Zamiast wykonania działania niech AAPS wyświetli tylko powiadomienie. Gdy masz pewność, że automatyzacja zostaje uruchomiona we właściwym czasie, zastąp powiadomienie rzeczywistą akcją. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
<string name="objectives_autosens_gate">1 semana de looping durante o dia com sucesso com entrada regular de carboidratos</string>
|
||||
<string name="objectives_autosens_learned">Se o resultado do seu autosens não está oscilando por volta de 100% seu perfil provavelmente está errado.</string>
|
||||
<string name="objectives_smb_objective">Activando recursos adicionais para uso durante o dia, como SMB</string>
|
||||
<string name="objectives_smb_gate">Deverá ler a wiki e aumentar a IA máx para que os SMBs funcionem corretamente! Inicialmente poderá considerar maxIA=média dos bólus + 3 x a basal diária máxima</string>
|
||||
<string name="objectives_smb_learned">Usar SMB é o seu objetivo. O algoritmo Oref1 foi projetado para ajudá-lo também com seus bolus. Você não deve dar bolus completo para sua comida, apenas parte dela e deixar o AAPS lhe dar o resto, se necessário. Desta forma, você tem mais espaço para carboidratos mal calculado. Você sabia que pode definir uma porcentagem do resultado da calculadora de bolus para reduzir o tamanho do bolus?</string>
|
||||
<string name="objectives_auto_objective">Ativando a automação</string>
|
||||
<string name="objectives_auto_gate">Leia os documentos de como a automação funciona. Configure suas primeiras regras simples. Em vez de efetuar uma ação deixe AAPS apresentar apenas uma notificação. Quando você tiver certeza de que a automação é acionada no momento certo substitua a notificação por uma ação real. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Ajuste as basais e os rácios, se necessário, e, em seguida, active o auto-sens</string>
|
||||
<string name="objectives_autosens_gate">1 semana de looping durante o dia com sucesso com entrada regular de hidratos de carbono</string>
|
||||
<string name="objectives_smb_objective">Activando recursos adicionais para uso durante o dia, como SMB</string>
|
||||
<string name="objectives_smb_gate">Deverá ler a wiki e aumentar a IA máx para que os SMBs funcionem devidamente! Inicialmente poderá considerar maxIA=média dos bólus + 3 x a basal máxima</string>
|
||||
<string name="objectives_auto_objective">A ativar a automatização</string>
|
||||
<string name="objectives_manualenacts">Execução manual</string>
|
||||
<string name="accomplished">Concluído: %1$s</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Ajustarea bazalelor și a factorilor dacă este necesar și apoi activarea auto-sens</string>
|
||||
<string name="objectives_autosens_gate">O săptămână de buclă închisă încheiată cu succes în condițiile introducerii regulate a carbohidraților</string>
|
||||
<string name="objectives_smb_objective">Se activează opțiuni pentru uzul în timpul zilei, cum ar fi SMB</string>
|
||||
<string name="objectives_smb_gate">Trebuie sa citiți wiki și să măriți maxIOB pentru a obține SMB corect! Un start bun este maxIOB=media bolusurilor + 3x maxima bazalei din zi</string>
|
||||
<string name="objectives_auto_objective">Activarea automatizării</string>
|
||||
<string name="objectives_manualenacts">Acțiuni manuale</string>
|
||||
<string name="accomplished">Îndeplinit: %1$s</string>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<string name="nth_objective">Цель %1$d</string>
|
||||
<string name="objectivenotstarted">Цель %1$d не начата</string>
|
||||
<string name="objectivenotfinished">Цель %1$d не завершена</string>
|
||||
<string name="objectives_0_objective">Настройка визуализации и мониторинга, анализ базала и коэффициентов</string>
|
||||
<string name="objectives_0_gate">Убедитесь, что величина ГК и данные по инсулину помпы передаются в Nightscout</string>
|
||||
<string name="objectives_0_objective">Настройка интеграции с Nightscout, анализ базала и коэффициентов</string>
|
||||
<string name="objectives_0_gate">Убедитесь, что данные о гликемии и подаваемом AAPSом инсулине отображаются в Nightscout и актуальны</string>
|
||||
<string name="objectives_0_learned">Вы сделали базовую настройку экосистемы AAPS. Nightscout не нужен для работы AAPS, но может быть полезен для отчетов и мониторинга других пациентов. Необходимости в постоянном подключении к NS нет, если вы используете NS только для себя. Вы можете установить загрузку, например, только на домашний wifi, чтобы сэкономить заряд батареи.</string>
|
||||
<string name="objectives_openloop_objective">Старт незамкнутого цикла</string>
|
||||
<string name="objectives_openloop_gate">Начинайте работу в режиме незамкнутого цикла и ручной подстройки величины временного базала. Установите и применяйте временные цели и временные цели по умолчанию (напр. углеводы при нагрузке или купировании гипо)</string>
|
||||
|
@ -14,9 +14,9 @@
|
|||
<string name="objectives_maxbasal_objective">Глубже понимаем работу системы в режиме незамкнутого цикла, включая ее рекомендации по временным базалам</string>
|
||||
<string name="objectives_maxbasal_gate">На основе накопленного опыта, определяем максимальную величину базала и задаем ее в помпе и в настройки AndroidAPS</string>
|
||||
<string name="objectives_maxbasal_learned">Примите меры предосторожности и корректируйте, если необходимо, параметры безопасности.</string>
|
||||
<string name="objectives_maxiobzero_objective">Начинаем замыкать цикл с прекращением подачи инсулина при низком значении Ск (режим Low Glucose Suspend)</string>
|
||||
<string name="objectives_maxiobzero_objective">Начинаем замыкать цикл с прекращением подачи инсулина при низком значении ГК (режим Low Glucose Suspend)</string>
|
||||
<string name="objectives_maxiobzero_gate">Работа в замкнутом цикле с макс активным инсулином IOB = 0 на протяжении нескольких дней избегая событий типа приостановка на низких ГК Low Suspend</string>
|
||||
<string name="objectives_maxiobzero_learned">Установка MaxIOB на нуль предотвращает от гипо и не добавит инсулина выше базальной скорости (за исключением отрицательных значений IOB)</string>
|
||||
<string name="objectives_maxiobzero_learned">Установка MaxIOB на нуль предотвращает гипо и не добавит инсулина выше базальной скорости (за исключением отрицательных значений IOB)</string>
|
||||
<string name="objectives_maxiob_objective">Настройка замкнутого цикла с поднятием макс величины IOB выше 0 и постепенным понижением целевой ГК</string>
|
||||
<string name="objectives_maxiob_gate">Работа несколько дней и по кр мере одну ночь без срабатывания оповещений о низкой ГК</string>
|
||||
<string name="objectives_maxiob_learned">Обновляйте MaxIOB по мере взросления ребенка. Не допускайте, чтобы система подавала больше инсулина, чем вы можете покрыть едой = действительно, плохая идея выставлять высокие значения.</string>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<string name="objectives_autosens_gate">1 неделя успешной дневной работы с регулярным введением углеводов</string>
|
||||
<string name="objectives_autosens_learned">Если результаты autosense не колеблются около 100%, то возможно ваш профиль неверный.</string>
|
||||
<string name="objectives_smb_objective">Активация таких доп функций для дневного времени как супер микро болюс SMB</string>
|
||||
<string name="objectives_smb_gate">Прочтите wiki и увеличьте maxIOB чтобы супер микро болюс SMB заработал как положено! Хорошее начало – maxIOB = средний болюс на еду + троекратный максимальный суточный базал</string>
|
||||
<string name="objectives_smb_gate">Прочтите статью wiki и увеличивайте maxIOB так, чтобы SMB заработал как положено! Для начала рассчитайте maxIOB как средний болюс на еду + макс. суточная базальная скорость*3</string>
|
||||
<string name="objectives_smb_learned">Ваша цель - это использование СМБ. Алгоритм Oref1 предназначен также, чтобы помочь вам с болюсами. Вы не должны подавать полный болюс на еду, а только часть его, предоставив AAPS подать при необходимости остальную часть болюса. Таким образом вы можете иметь большее пространство для ошибки в подсчетах углеводов. Вы знаете, что можно установить проценты для уменьшения размера болюса?</string>
|
||||
<string name="objectives_auto_objective">Включение автоматизации</string>
|
||||
<string name="objectives_auto_gate">Прочтите документацию по автоматизации. Настройте свои первые простые правила. Вместо действия позвольте AAPS только выводить уведомления. Если вы уверены, что автоматизация инициируется в нужное время, замените уведомление реальными действиями. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
@ -49,9 +49,9 @@
|
|||
<string name="objectives_exam_learned_prerequisites2">AAPS может работать в автономном режиме.</string>
|
||||
<string name="objectives_exam_learned_basaltest">Следует пересмотреть и обновить профиль. Лучший профиль = лучшие результаты.</string>
|
||||
<string name="objectives_exam_learned_dia">Продолжительность действия инсулина DIA в AAPS имеет иное значение (время до полного поглощения инсулина), чем в классической помповой терапии (время до поглощения основной массы инсулина).</string>
|
||||
<string name="objectives_exam_learned_isf">Вы изучили понятие чувствительность к инсулину ISF, и как она влияет на коррекцию ГК.</string>
|
||||
<string name="objectives_exam_learned_ic">Вы изучили понятие углеводный коэффициент IC и как он влияет на количество инсулина, необходимого для покрытия углеводов.</string>
|
||||
<string name="objectives_exam_learned_hypott">Временная цель Hypo используется только для предотвращения чрезмерной коррекции после гипо, когда накапливается отрицательный IOB. Необходимо принять дополнительные меры, чтобы предотвратить ситуацию в будущем.</string>
|
||||
<string name="objectives_exam_learned_isf">Вы изучили понятие чувствительность к инсулину ISF и то, как она влияет на коррекцию ГК.</string>
|
||||
<string name="objectives_exam_learned_ic">Вы изучили понятие углеводный коэффициент IC и то, как он влияет на количество инсулина, необходимого для покрытия углеводов.</string>
|
||||
<string name="objectives_exam_learned_hypott">Временная цель Гипо используется только для предотвращения чрезмерной коррекции после гипо, когда накапливается отрицательный IOB. Необходимо принять дополнительные меры, чтобы предотвратить ситуацию в будущем.</string>
|
||||
<string name="objectives_exam_learned_profileswitch">Использование процентов не повлияет на целевую ГК, а только на базу, ISF и IC таким образом, чтобы дать больше инсулина (выше 100%%) или меньше инсулина (ниже 100%%).</string>
|
||||
<string name="objectives_exam_learned_profileswitchtime">Используя сдвиг по времени, можно адаптировать профиль к нерегулярным событиям типа позднего пробуждения.</string>
|
||||
<string name="objectives_exam_learned_profileswitch4">Редактирование профиля не является достаточным для внесения изменений. Все еще нужно переключиться на этот профиль и активировать изменения.</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">Justera basaler och kvoter om det behövs. Aktivera sedan autosens</string>
|
||||
<string name="objectives_autosens_gate">1 veckas lyckad looping dagtid, där alla måltider lagts in</string>
|
||||
<string name="objectives_smb_objective">Aktiverar ytterligare funktioner för användning dagtid, t ex SMB</string>
|
||||
<string name="objectives_smb_gate">Du måste läsa på wikin och öka max IOB för att få SMB att fungera bra. En bra start är att sätta max IOB till din genomsnittliga måltidsbolus plus 3 gånger den högsta basalen du har under ett dygn</string>
|
||||
<string name="objectives_auto_objective">Aktivera automatisering</string>
|
||||
<string name="objectives_manualenacts">Manuella justeringar</string>
|
||||
<string name="accomplished">Utfört: %1$s</string>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<string name="objectives_autosens_objective">必要时调整胰岛素基础率和比率,然后再启用auto-sens胰岛素敏感系数自动调整功能</string>
|
||||
<string name="objectives_autosens_gate">规律的进行碳水记录,成功在一个星期的白天开启闭环</string>
|
||||
<string name="objectives_smb_objective">在白天启用额外的功能,例如微型大剂量 SMB</string>
|
||||
<string name="objectives_smb_gate">你应该阅读wiki指南,以调整 maxIOB(活性胰岛素的最大值) 设置,让SMB(微型大剂量) 更好的工作。建议是 maxIOB值=餐时剂量的平均值+基础率的最大值的3倍。</string>
|
||||
<string name="objectives_auto_objective">启用自动操作功能插件</string>
|
||||
<string name="objectives_manualenacts">手动执行</string>
|
||||
<string name="accomplished">已完成: %1$s</string>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="objectives_autosens_gate">1 week successful daytime looping with regular carb entry</string>
|
||||
<string name="objectives_autosens_learned">If your autosens result is not oscillating around 100% your profile probably wrong.</string>
|
||||
<string name="objectives_smb_objective">Enabling additional features for daytime use, such as SMB</string>
|
||||
<string name="objectives_smb_gate">You must read the wiki and rise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal</string>
|
||||
<string name="objectives_smb_gate">You must read the wiki and raise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal</string>
|
||||
<string name="objectives_smb_learned">Using SMB is your goal. Oref1 algorithm was designed to help you with your boluses as well. You should not give full bolus for your food but only part of it and let AAPS give you the rest if needed. This way you have more space for miscalculated carbs. Did you know that you can set a percentage of bolus calculator result to reduce the size of bolus?</string>
|
||||
<string name="objectives_auto_objective">Enabling automation</string>
|
||||
<string name="objectives_auto_gate">Read the docs on how automation works. Set up your first simple rules. Instead of action let AAPS display only notification. When you are sure automation is triggered at the right time replace notification by real action. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package info.nightscout.plugins.general.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -59,7 +57,6 @@ class ActionsFragment : DaggerFragment() {
|
|||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var rh: ResourceHelper
|
||||
@Inject lateinit var statusLightHandler: StatusLightHandler
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
|
@ -78,31 +75,22 @@ class ActionsFragment : DaggerFragment() {
|
|||
|
||||
private val pumpCustomActions = HashMap<String, CustomAction>()
|
||||
private val pumpCustomButtons = ArrayList<SingleClickButton>()
|
||||
private lateinit var dm: DisplayMetrics
|
||||
|
||||
private var _binding: ActionsFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
//check screen width
|
||||
dm = DisplayMetrics()
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||
@Suppress("DEPRECATION")
|
||||
activity?.display?.getRealMetrics(dm)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
activity?.windowManager?.defaultDisplay?.getMetrics(dm)
|
||||
}
|
||||
_binding = ActionsFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
ActionsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
skinProvider.activeSkin().preProcessLandscapeActionsLayout(dm, binding)
|
||||
val screenWidth = activity?.window?.decorView?.width ?: 0
|
||||
val screenHeight = activity?.window?.decorView?.height ?: 0
|
||||
val isLandscape = screenHeight < screenWidth
|
||||
skinProvider.activeSkin().preProcessLandscapeActionsLayout(isLandscape, binding)
|
||||
|
||||
binding.profileSwitch.setOnClickListener {
|
||||
activity?.let { activity ->
|
||||
|
@ -285,7 +273,7 @@ class ActionsFragment : DaggerFragment() {
|
|||
binding.tddStats.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
|
||||
val isPatchPump = pump.pumpDescription.isPatchPump
|
||||
binding.status.apply {
|
||||
cannulaOrPatch.text = if (isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula)
|
||||
cannulaOrPatch.text = if (cannulaOrPatch.text.isEmpty()) "" else if (isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula)
|
||||
val imageResource = if (isPatchPump) info.nightscout.core.main.R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula
|
||||
cannulaOrPatch.setCompoundDrawablesWithIntrinsicBounds(imageResource, 0, 0, 0)
|
||||
batteryLayout.visibility = (!isPatchPump || pump.pumpDescription.useHardwareLink).toVisibility()
|
||||
|
@ -293,7 +281,11 @@ class ActionsFragment : DaggerFragment() {
|
|||
cannulaUsage.visibility = isPatchPump.not().toVisibility()
|
||||
|
||||
if (!config.NSCLIENT) {
|
||||
statusLightHandler.updateStatusLights(cannulaAge, cannulaUsage, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel)
|
||||
statusLightHandler.updateStatusLights(
|
||||
cannulaAge, cannulaUsage, insulinAge,
|
||||
reservoirLevel, sensorAge, sensorLevel,
|
||||
pbAge, pbLevel
|
||||
)
|
||||
sensorLevelLabel.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.level_label)
|
||||
} else {
|
||||
statusLightHandler.updateStatusLights(cannulaAge, cannulaUsage, insulinAge, null, sensorAge, null, pbAge, null)
|
||||
|
|
|
@ -188,7 +188,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
smallHeight = screenHeight <= Constants.SMALL_HEIGHT
|
||||
val landscape = screenHeight < screenWidth
|
||||
|
||||
skinProvider.activeSkin().preProcessLandscapeOverviewLayout(dm, binding, landscape, rh.gb(info.nightscout.shared.R.bool.isTablet), smallHeight)
|
||||
skinProvider.activeSkin().preProcessLandscapeOverviewLayout(binding, landscape, rh.gb(info.nightscout.shared.R.bool.isTablet), smallHeight)
|
||||
binding.nsclientCard.visibility = config.NSCLIENT.toVisibility()
|
||||
|
||||
binding.notifications.setHasFixedSize(false)
|
||||
|
@ -841,11 +841,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||
info.nightscout.core.ui.R.attr.ribbonWarningColor
|
||||
else info.nightscout.core.ui.R.attr.ribbonDefaultColor
|
||||
} else if (it is ProfileSealed.PS) {
|
||||
info.nightscout.core.ui.R.attr.ribbonDefaultColor
|
||||
} else {
|
||||
info.nightscout.core.ui.R.attr.ribbonDefaultColor
|
||||
}
|
||||
} else info.nightscout.core.ui.R.attr.ribbonDefaultColor
|
||||
} ?: info.nightscout.core.ui.R.attr.ribbonCriticalColor
|
||||
|
||||
val profileTextColor = profile?.let {
|
||||
|
@ -853,11 +849,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||
info.nightscout.core.ui.R.attr.ribbonTextWarningColor
|
||||
else info.nightscout.core.ui.R.attr.ribbonTextDefaultColor
|
||||
} else if (it is ProfileSealed.PS) {
|
||||
info.nightscout.core.ui.R.attr.ribbonTextDefaultColor
|
||||
} else {
|
||||
info.nightscout.core.ui.R.attr.ribbonTextDefaultColor
|
||||
}
|
||||
} else info.nightscout.core.ui.R.attr.ribbonTextDefaultColor
|
||||
} ?: info.nightscout.core.ui.R.attr.ribbonTextDefaultColor
|
||||
setRibbon(binding.activeProfile, profileTextColor, profileBackgroundColor, profileFunction.getProfileNameWithRemainingTime())
|
||||
}
|
||||
|
@ -899,14 +891,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
binding.statusLightsLayout.apply {
|
||||
cannulaOrPatch.setImageResource(if (isPatchPump) info.nightscout.core.main.R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula)
|
||||
cannulaOrPatch.contentDescription = rh.gs(if (isPatchPump) R.string.statuslights_patch_pump_age else R.string.statuslights_cannula_age)
|
||||
cannulaOrPatch.scaleX = if (isPatchPump) 1.4f else 2f
|
||||
cannulaOrPatch.scaleY = cannulaOrPatch.scaleX
|
||||
insulinAge.visibility = isPatchPump.not().toVisibility()
|
||||
batteryLayout.visibility = (!isPatchPump || pump.pumpDescription.useHardwareLink).toVisibility()
|
||||
pbAge.visibility = (pump.pumpDescription.isBatteryReplaceable || pump.isBatteryChangeLoggingEnabled()).toVisibility()
|
||||
val useBatteryLevel = (pump.model() == PumpType.OMNIPOD_EROS)
|
||||
|| (pump.model() != PumpType.ACCU_CHEK_COMBO && pump.model() != PumpType.OMNIPOD_DASH)
|
||||
batteryLevel.visibility = useBatteryLevel.toVisibility()
|
||||
pbLevel.visibility = useBatteryLevel.toVisibility()
|
||||
statusLightsLayout.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
|
||||
}
|
||||
statusLightHandler.updateStatusLights(
|
||||
|
@ -917,7 +907,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
binding.statusLightsLayout.sensorAge,
|
||||
null,
|
||||
binding.statusLightsLayout.pbAge,
|
||||
binding.statusLightsLayout.batteryLevel
|
||||
binding.statusLightsLayout.pbLevel
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1040,6 +1030,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useBGIForScale = false
|
||||
var useHRForScale = false
|
||||
when {
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
|
@ -1048,6 +1039,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] -> useHRForScale = true
|
||||
}
|
||||
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||
|
||||
|
@ -1062,6 +1054,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
if (useDSForScale) 1.0 else 0.8,
|
||||
useRatioForScale
|
||||
)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal]) secondGraphData.addHeartRate(useHRForScale, if (useHRForScale) 1.0 else 0.8)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(overviewData.fromTime, overviewData.endTime)
|
||||
|
@ -1077,7 +1070,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal]
|
||||
).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ class OverviewMenusImpl @Inject constructor(
|
|||
BGI(R.string.overview_show_bgi, info.nightscout.core.ui.R.attr.bgiColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.bgi_shortname),
|
||||
SEN(R.string.overview_show_sensitivity, info.nightscout.core.ui.R.attr.ratioColor, info.nightscout.core.ui.R.attr.menuTextColorInverse, primary = false, secondary = true, shortnameId = R.string.sensitivity_shortname),
|
||||
ACT(R.string.overview_show_activity, info.nightscout.core.ui.R.attr.activityColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = true, secondary = false, shortnameId = R.string.activity_shortname),
|
||||
DEVSLOPE(R.string.overview_show_deviation_slope, info.nightscout.core.ui.R.attr.devSlopePosColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.devslope_shortname)
|
||||
DEVSLOPE(R.string.overview_show_deviation_slope, info.nightscout.core.ui.R.attr.devSlopePosColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.devslope_shortname),
|
||||
HR(R.string.overview_show_heartRate, info.nightscout.core.ui.R.attr.heartRateColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.heartRate_shortname),
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -202,4 +203,4 @@ class OverviewMenusImpl @Inject constructor(
|
|||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,5 +258,14 @@ class GraphData(
|
|||
// draw it
|
||||
graph.onDataChanged(false, false)
|
||||
}
|
||||
}
|
||||
|
||||
fun addHeartRate(useForScale: Boolean, scale: Double) {
|
||||
val maxHR = overviewData.heartRateGraphSeries.highestValueY
|
||||
if (useForScale) {
|
||||
minY = 0.0
|
||||
maxY = maxHR
|
||||
}
|
||||
addSeries(overviewData.heartRateGraphSeries)
|
||||
overviewData.heartRateScale.multiplier = maxY * scale / maxHR
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import android.view.View
|
|||
import android.view.WindowManager
|
||||
import com.google.common.primitives.Ints.min
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.core.ui.activities.TranslatedDaggerAppCompatActivity
|
||||
import info.nightscout.core.ui.dialogs.OKDialog
|
||||
import info.nightscout.core.ui.toast.ToastUtils
|
||||
import info.nightscout.core.utils.fabric.FabricPrivacy
|
||||
|
@ -28,7 +28,7 @@ import info.nightscout.shared.interfaces.ResourceHelper
|
|||
import net.glxn.qrgen.android.QRCode
|
||||
import javax.inject.Inject
|
||||
|
||||
class SmsCommunicatorOtpActivity : DaggerAppCompatActivity() {
|
||||
class SmsCommunicatorOtpActivity : TranslatedDaggerAppCompatActivity() {
|
||||
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var smsCommunicator: SmsCommunicator
|
||||
|
|
|
@ -19,6 +19,7 @@ import info.nightscout.database.ValueWrapper
|
|||
import info.nightscout.database.entities.Bolus
|
||||
import info.nightscout.database.entities.BolusCalculatorResult
|
||||
import info.nightscout.database.entities.GlucoseValue
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.database.entities.TemporaryBasal
|
||||
import info.nightscout.database.entities.TemporaryTarget
|
||||
import info.nightscout.database.entities.TotalDailyDose
|
||||
|
@ -28,6 +29,7 @@ import info.nightscout.database.entities.interfaces.end
|
|||
import info.nightscout.database.impl.AppRepository
|
||||
import info.nightscout.database.impl.transactions.CancelCurrentTemporaryTargetIfAnyTransaction
|
||||
import info.nightscout.database.impl.transactions.InsertAndCancelCurrentTemporaryTargetTransaction
|
||||
import info.nightscout.database.impl.transactions.InsertOrUpdateHeartRateTransaction
|
||||
import info.nightscout.interfaces.Config
|
||||
import info.nightscout.interfaces.Constants
|
||||
import info.nightscout.interfaces.GlucoseUnit
|
||||
|
@ -308,6 +310,10 @@ class DataHandlerMobile @Inject constructor(
|
|||
aapsLogger.debug(LTag.WEAR, "WearException received $it from ${it.sourceNodeId}")
|
||||
fabricPrivacy.logWearException(it)
|
||||
}, fabricPrivacy::logException)
|
||||
disposable += rxBus
|
||||
.toObservable(EventData.ActionHeartRate::class.java)
|
||||
.observeOn(aapsSchedulers.io)
|
||||
.subscribe({ handleHeartRate(it) }, fabricPrivacy::logException)
|
||||
}
|
||||
|
||||
private fun handleTddStatus() {
|
||||
|
@ -1230,4 +1236,15 @@ class DataHandlerMobile @Inject constructor(
|
|||
@Synchronized private fun sendError(errorMessage: String) {
|
||||
rxBus.send(EventMobileToWear(EventData.ConfirmAction(rh.gs(info.nightscout.core.ui.R.string.error), errorMessage, returnCommand = EventData.Error(dateUtil.now())))) // ignore return path
|
||||
}
|
||||
|
||||
/** Stores heart rate events coming from the Wear device. */
|
||||
private fun handleHeartRate(actionHeartRate: EventData.ActionHeartRate) {
|
||||
aapsLogger.debug(LTag.WEAR, "Heart rate received $actionHeartRate from ${actionHeartRate.sourceNodeId}")
|
||||
val hr = HeartRate(
|
||||
duration = actionHeartRate.duration,
|
||||
timestamp = actionHeartRate.timestamp,
|
||||
beatsPerMinute = actionHeartRate.beatsPerMinute,
|
||||
device = actionHeartRate.device)
|
||||
repository.runTransaction(InsertOrUpdateHeartRateTransaction(hr)).blockingAwait()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,7 @@ class ProfilePlugin @Inject constructor(
|
|||
isEdited = false
|
||||
createAndStoreConvertedProfile()
|
||||
aapsLogger.debug(LTag.PROFILE, "Accepted ${profiles.size} profiles")
|
||||
storeSettings()
|
||||
rxBus.send(EventLocalProfileChanged())
|
||||
} else
|
||||
aapsLogger.debug(LTag.PROFILE, "ProfileStore not accepted")
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.plugins.skins
|
||||
|
||||
import android.util.DisplayMetrics
|
||||
import info.nightscout.interfaces.Config
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.databinding.OverviewFragmentBinding
|
||||
|
@ -14,8 +13,8 @@ class SkinClassic @Inject constructor(private val config: Config) : SkinInterfac
|
|||
override val mainGraphHeight: Int get() = 200
|
||||
override val secondaryGraphHeight: Int get() = 100
|
||||
|
||||
override fun preProcessLandscapeOverviewLayout(dm: DisplayMetrics, binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
super.preProcessLandscapeOverviewLayout(dm, binding, isLandscape, isTablet, isSmallHeight)
|
||||
override fun preProcessLandscapeOverviewLayout(binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
super.preProcessLandscapeOverviewLayout(binding, isLandscape, isTablet, isSmallHeight)
|
||||
if (!config.NSCLIENT && (isSmallHeight || isLandscape)) moveButtonsLayout(binding.root)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.plugins.skins
|
||||
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue.COMPLEX_UNIT_PX
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
|
@ -18,16 +17,11 @@ interface SkinInterface {
|
|||
val secondaryGraphHeight: Int // in dp
|
||||
|
||||
// no pre processing by default
|
||||
fun preProcessLandscapeActionsLayout(dm: DisplayMetrics, binding: ActionsFragmentBinding) {
|
||||
fun preProcessLandscapeActionsLayout(isLandscape: Boolean, binding: ActionsFragmentBinding) {
|
||||
}
|
||||
|
||||
fun preProcessLandscapeOverviewLayout(dm: DisplayMetrics, binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
// pre-process landscape mode
|
||||
val screenWidth = dm.widthPixels
|
||||
val screenHeight = dm.heightPixels
|
||||
val landscape = screenHeight < screenWidth
|
||||
|
||||
if (landscape) {
|
||||
fun preProcessLandscapeOverviewLayout(binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
if (isLandscape) {
|
||||
val iobLayout = binding.infoLayout.iobLayout
|
||||
val iobLayoutParams = iobLayout.layoutParams as ConstraintLayout.LayoutParams
|
||||
val timeLayout = binding.infoLayout.timeLayout
|
||||
|
@ -59,7 +53,7 @@ interface SkinInterface {
|
|||
for (v in texts) v.setTextSize(COMPLEX_UNIT_PX, v.textSize * 1.3f)
|
||||
}
|
||||
binding.statusLightsLayout.apply {
|
||||
val texts = listOf(cannulaAge, insulinAge, reservoirLevel, sensorAge, pbAge, batteryLevel)
|
||||
val texts = listOf(cannulaAge, insulinAge, reservoirLevel, sensorAge, pbAge, pbLevel)
|
||||
for (v in texts) v.setTextSize(COMPLEX_UNIT_PX, v.textSize * 1.3f)
|
||||
}
|
||||
timeLayout.orientation = LinearLayout.HORIZONTAL
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.plugins.skins
|
||||
|
||||
import android.util.DisplayMetrics
|
||||
import info.nightscout.interfaces.Config
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.databinding.OverviewFragmentBinding
|
||||
|
@ -14,8 +13,8 @@ class SkinLargeDisplay @Inject constructor(private val config: Config) : SkinInt
|
|||
override val mainGraphHeight: Int get() = 400
|
||||
override val secondaryGraphHeight: Int get() = 150
|
||||
|
||||
override fun preProcessLandscapeOverviewLayout(dm: DisplayMetrics, binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
super.preProcessLandscapeOverviewLayout(dm, binding, isLandscape, isTablet, isSmallHeight)
|
||||
override fun preProcessLandscapeOverviewLayout(binding: OverviewFragmentBinding, isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean) {
|
||||
super.preProcessLandscapeOverviewLayout(binding, isLandscape, isTablet, isSmallHeight)
|
||||
if (!config.NSCLIENT && (isSmallHeight || isLandscape)) moveButtonsLayout(binding.root)
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue