diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2ccca5cea7..381dffa690 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ Translations ------------ * If possible, always use Android translation mechanism (with strings.xml and @strings/id) instead of hardcoded texts -* Provide only English strings - all other languages will be crowd translated via Crowdn https://translations.androidaps.org/ +* Provide only English strings - all other languages will be crowd translated via Crowdin (https://crowdin.com/project/androidaps and https://crowdin.com/project/androidapsdocs) Hints ----- diff --git a/app/build.gradle b/app/build.gradle index 2720ef7605..ce1b0af2aa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -22,14 +22,6 @@ jacoco { toolVersion = "0.8.3" } -ext { - powermockVersion = "1.7.3" - dexmakerVersion = "1.2" - retrofit2Version = '2.9.0' - okhttp3Version = '4.7.2' -} - - repositories { jcenter { url "https://jcenter.bintray.com/" } mavenCentral() @@ -124,15 +116,16 @@ android { ndkVersion "21.1.6352462" defaultConfig { - minSdkVersion 24 + minSdkVersion 26 targetSdkVersion 28 multiDexEnabled true versionCode 1500 - version "2.7.0-dev" + version "2.8.1.2-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"' + buildConfigField "String", "COMMITED", '"' + allCommited() + '"' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // if you change minSdkVersion to less than 11, you need to change executeTask for wear @@ -143,6 +136,9 @@ android { kotlinOptions { jvmTarget = '1.8' } + buildFeatures { + viewBinding true + } lintOptions { checkReleaseBuilds false disable 'MissingTranslation' @@ -230,11 +226,9 @@ android { allprojects { repositories { - jcenter() flatDir { dirs 'libs' } - maven { url 'https://jitpack.io' } } } @@ -250,66 +244,10 @@ dependencies { implementation project(':omnipod') implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.google.android.gms:play-services-wearable:17.0.0' - implementation "com.google.android.gms:play-services-location:17.0.0" - implementation 'com.google.firebase:firebase-core:17.4.3' - implementation 'com.google.firebase:firebase-auth:19.3.1' - implementation 'com.google.firebase:firebase-database:19.3.1' - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.legacy:legacy-support-v13:1.0.0' - implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.biometric:biometric:1.0.1' - implementation 'androidx.recyclerview:recyclerview:1.1.0' - implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'androidx.percentlayout:percentlayout:1.0.0' - implementation "androidx.preference:preference-ktx:1.1.1" - implementation "androidx.activity:activity-ktx:${activityVersion}" - implementation "androidx.fragment:fragment:${fragmentVersion}" - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" - implementation "androidx.navigation:navigation-ui-ktx:$nav_version" - implementation 'com.google.android.material:material:1.1.0' - - implementation "io.reactivex.rxjava2:rxandroid:${rxandroid_version}" - - implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}" - implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}" - implementation("com.github.tony19:logback-android-classic:1.1.1-6") { - exclude group: "com.google.android", module: "android" - } - implementation 'org.apache.commons:commons-lang3:3.10' - implementation 'org.slf4j:slf4j-api:1.7.30' - // Graphview cannot be upgraded - implementation "com.jjoe64:graphview:4.0.1" - implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2" - implementation 'com.madgag.spongycastle:core:1.58.0.0' - implementation("com.google.android:flexbox:0.3.0") { - exclude group: "com.android.support" - } - implementation("io.socket:socket.io-client:1.0.0") { - // excluding org.json which is provided by Android - exclude group: "org.json", module: "json" - } - implementation "com.google.code.gson:gson:2.8.6" - implementation('com.google.guava:guava:29.0-jre') { - exclude group: "com.google.code.findbugs", module: "jsr305" - } - implementation 'com.google.code.findbugs:jsr305:3.0.2' - - implementation 'net.danlew:android.joda:2.10.6' - - implementation 'org.mozilla:rhino:1.7.12' - - implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0' - - implementation 'com.github.kenglxn.QRGen:android:2.6.0' - implementation 'com.eatthepath:java-otp:0.2.0' - - testImplementation "junit:junit:4.13" + testImplementation "junit:junit:$junit_version" testImplementation 'org.json:json:20200518' - testImplementation "org.mockito:mockito-core:2.8.47" + testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}" @@ -322,31 +260,16 @@ dependencies { testImplementation "org.skyscreamer:jsonassert:1.5.0" testImplementation "org.hamcrest:hamcrest-all:1.3" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion" - - // new for tidepool - implementation "com.squareup.okhttp3:okhttp:$okhttp3Version" - implementation "com.squareup.okhttp3:logging-interceptor:$okhttp3Version" - implementation "com.squareup.retrofit2:retrofit:$retrofit2Version" - implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version" - implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version" - - // Phone checker - implementation 'com.scottyab:rootbeer-lib:0.0.8' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test:rules:1.3.0-beta01' + androidTestImplementation "androidx.test.ext:junit:$androidx_junit" + androidTestImplementation "androidx.test:rules:$androidx_rules" androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2' /* Dagger2 - We are going to use dagger.android which includes * support for Activity and fragment injection so we need to include * the following dependencies */ - implementation "com.google.dagger:dagger-android:$dagger_version" - implementation "com.google.dagger:dagger-android-support:$dagger_version" + + annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version" kapt "com.google.dagger:dagger-android-processor:$dagger_version" @@ -355,15 +278,6 @@ dependencies { kapt "com.google.dagger:dagger-compiler:$dagger_version" androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' - - //WorkManager - implementation 'androidx.work:work-runtime:2.3.4' - implementation 'androidx.work:work-runtime-ktx:2.3.4' - implementation 'androidx.work:work-rxjava2:2.3.4' - - implementation 'com.google.androidbrowserhelper:androidbrowserhelper:1.1.0' - - implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' } /* diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 96763d8274..e0e2a6b05b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -71,6 +72,10 @@ + 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) { + } else if ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 && !isSaveCgmSource) { if ( glucose_status.last_cal && glucose_status.last_cal < 3 ) { rT.reason = "CGM was just calibrated"; } else { @@ -151,7 +151,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ } } //cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc - if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) ) { + if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) && !isSaveCgmSource ) { if (currenttemp.rate > basal) { // high temp is running rT.reason += ". Replacing high temp basal of "+currenttemp.rate+" with neutral temp of "+basal; rT.deliverAt = deliverAt; diff --git a/app/src/main/assets/revoked_certs.txt b/app/src/main/assets/revoked_certs.txt index 41177d5667..103792a183 100644 --- a/app/src/main/assets/revoked_certs.txt +++ b/app/src/main/assets/revoked_certs.txt @@ -2,3 +2,6 @@ 51:6D:12:67:4C:27:F4:9B:9F:E5:42:9B:01:B3:98:E4:66:2B:85:B7:A8:DD:70:32:B7:6A:D7:97:9A:0D:97:10 #Leaked 55:5D:70:C9:BE:10:41:7E:4B:01:A9:C4:C6:44:4A:F8:69:71:35:25:ED:95:23:16:C7:15:E8:EB:C6:08:FC:B1 +# àqΣnΖ`ZϼγwÛ/τàΒϳ9Φ'$ΑϵžλUΛ`ÆÌΣЃA +E0:71:A3:6E:96:60:5A:FC:B3:77:DB:2F:C4:E0:92:F3:39:A6:27:24:91:F5:7E:BB:55:9B:60:C6:CC:A3:03:41 +32:99:61:C4:A0:92:E8:D2:C7:65:04:74:04:17:7E:2D:2A:16:2A:5A:63:48:69:6A:0A:C4:53:3C:7C:78:22:95 diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt index ff35d585ee..b07111ed3b 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.kt @@ -25,11 +25,13 @@ import androidx.appcompat.widget.Toolbar import androidx.core.app.ActivityCompat import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.joanzapata.iconify.Iconify import com.joanzapata.iconify.fonts.FontAwesomeModule -import info.nightscout.androidaps.activities.ProfileHelperActivity +import dev.doubledot.doki.ui.DokiActivity import info.nightscout.androidaps.activities.NoSplashAppCompatActivity import info.nightscout.androidaps.activities.PreferencesActivity +import info.nightscout.androidaps.activities.ProfileHelperActivity import info.nightscout.androidaps.activities.SingleFragmentActivity import info.nightscout.androidaps.activities.StatsActivity import info.nightscout.androidaps.events.EventAppExit @@ -45,6 +47,8 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils +import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs +import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.setupwizard.SetupWizardActivity @@ -68,6 +72,7 @@ import javax.inject.Inject import kotlin.system.exitProcess class MainActivity : NoSplashAppCompatActivity() { + private val disposable = CompositeDisposable() @Inject lateinit var aapsLogger: AAPSLogger @@ -87,9 +92,17 @@ class MainActivity : NoSplashAppCompatActivity() { @Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin @Inject lateinit var config: Config + @Inject lateinit var importExportPrefs: ImportExportPrefs private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private var pluginPreferencesMenuItem: MenuItem? = null + private var menu: Menu? = null + + val callForPrefFile = registerForActivityResult(PrefsFileContract()) { + it?.let { + importExportPrefs.importSharedPreferences(this, it) + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -111,6 +124,7 @@ class MainActivity : NoSplashAppCompatActivity() { override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageSelected(position: Int) { + setPluginPreferenceMenuName() checkPluginPreferences(main_pager) } }) @@ -126,16 +140,17 @@ class MainActivity : NoSplashAppCompatActivity() { if (it.recreate) recreate() else setupViews() setWakeLock() - }) { fabricPrivacy::logException } + }, fabricPrivacy::logException) ) disposable.add(rxBus .toObservable(EventPreferenceChange::class.java) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ processPreferenceChange(it) }) { fabricPrivacy::logException } + .subscribe({ processPreferenceChange(it) }, fabricPrivacy::logException) ) if (!sp.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) { - val intent = Intent(this, SetupWizardActivity::class.java) - startActivity(intent) + protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, { + startActivity(Intent(this, SetupWizardActivity::class.java)) + }) } androidPermission.notifyForStoragePermission(this) androidPermission.notifyForBatteryOptimizationPermission(this) @@ -163,8 +178,8 @@ class MainActivity : NoSplashAppCompatActivity() { override fun onResume() { super.onResume() protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null, - UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) }), - UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) }) + UIRunnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed)) { finish() } }, + UIRunnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed)) { finish() } } ) } @@ -183,14 +198,20 @@ class MainActivity : NoSplashAppCompatActivity() { val pageAdapter = TabPageAdapter(this) main_navigation_view.setNavigationItemSelectedListener { true } val menu = main_navigation_view.menu.also { it.clear() } - for (p in activePlugin.pluginsList) { + for (p in activePlugin.getPluginsList()) { pageAdapter.registerNewFragment(p) if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) { val menuItem = menu.add(p.name) menuItem.isCheckable = true + if(p.menuIcon != -1) { + menuItem.setIcon(p.menuIcon) + } else + { + menuItem.setIcon(R.drawable.ic_settings) + } menuItem.setOnMenuItemClickListener { val intent = Intent(this, SingleFragmentActivity::class.java) - intent.putExtra("plugin", activePlugin.pluginsList.indexOf(p)) + intent.putExtra("plugin", activePlugin.getPluginsList().indexOf(p)) startActivity(intent) main_drawer_layout.closeDrawers() true @@ -228,7 +249,7 @@ class MainActivity : NoSplashAppCompatActivity() { if (permissions.isNotEmpty()) { if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { when (requestCode) { - AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted + AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text)) AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> { @@ -254,17 +275,26 @@ class MainActivity : NoSplashAppCompatActivity() { return super.dispatchTouchEvent(event) } + private fun setPluginPreferenceMenuName() { + if (main_pager.currentItem > 0) { + val plugin = (main_pager.adapter as TabPageAdapter).getPluginAt(main_pager.currentItem) + this.menu?.findItem(R.id.nav_plugin_preferences)?.title = resourceHelper.gs(R.string.nav_preferences_plugin, plugin.name) + } + } + override fun onCreateOptionsMenu(menu: Menu): Boolean { + this.menu = menu menuInflater.inflate(R.menu.menu_main, menu) pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences) + setPluginPreferenceMenuName() checkPluginPreferences(main_pager) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.nav_preferences -> { - protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable { + R.id.nav_preferences -> { + protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, { val i = Intent(this, PreferencesActivity::class.java) i.putExtra("id", -1) startActivity(i) @@ -272,21 +302,24 @@ class MainActivity : NoSplashAppCompatActivity() { return true } - R.id.nav_historybrowser -> { + R.id.nav_historybrowser -> { startActivity(Intent(this, HistoryBrowseActivity::class.java)) return true } - R.id.nav_setupwizard -> { - startActivity(Intent(this, SetupWizardActivity::class.java)) + R.id.nav_setupwizard -> { + protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, { + startActivity(Intent(this, SetupWizardActivity::class.java)) + }) return true } - R.id.nav_about -> { + R.id.nav_about -> { var message = "Build: ${BuildConfig.BUILDVERSION}\n" message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n" message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.nightscoutVersionName}" if (buildHelper.isEngineeringMode()) message += "\n${resourceHelper.gs(R.string.engineering_mode_enabled)}" + if (!fabricPrivacy.fabricEnabled()) message += "\n${resourceHelper.gs(R.string.fabric_upload_disabled)}" message += resourceHelper.gs(R.string.about_link_urls) val messageSpanned = SpannableString(message) Linkify.addLinks(messageSpanned, Linkify.WEB_URLS) @@ -295,14 +328,15 @@ class MainActivity : NoSplashAppCompatActivity() { .setIcon(iconsProvider.getIcon()) .setMessage(messageSpanned) .setPositiveButton(resourceHelper.gs(R.string.ok), null) - .create().also { - it.show() - (it.findViewById(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance() + .setNeutralButton(resourceHelper.gs(R.string.cta_dont_kill_my_app_info)) { _, _ -> DokiActivity.start(context = this@MainActivity) } + .create().apply { + show() + findViewById(android.R.id.message)?.movementMethod = LinkMovementMethod.getInstance() } return true } - R.id.nav_exit -> { + R.id.nav_exit -> { aapsLogger.debug(LTag.CORE, "Exiting") rxBus.send(EventAppExit()) finish() @@ -312,7 +346,7 @@ class MainActivity : NoSplashAppCompatActivity() { R.id.nav_plugin_preferences -> { val plugin = (main_pager.adapter as TabPageAdapter).getPluginAt(main_pager.currentItem) - protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable { + protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, { val i = Intent(this, PreferencesActivity::class.java) i.putExtra("id", plugin.preferencesId) startActivity(i) @@ -325,12 +359,12 @@ class MainActivity : NoSplashAppCompatActivity() { return true } */ - R.id.nav_defaultprofile -> { + R.id.nav_defaultprofile -> { startActivity(Intent(this, ProfileHelperActivity::class.java)) return true } - R.id.nav_stats -> { + R.id.nav_stats -> { startActivity(Intent(this, StatsActivity::class.java)) return true } @@ -366,6 +400,12 @@ class MainActivity : NoSplashAppCompatActivity() { fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileInterface.javaClass.simpleName) activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) } activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) } + // Add to crash log too + FirebaseCrashlytics.getInstance().setCustomKey("HEAD", BuildConfig.HEAD) + FirebaseCrashlytics.getInstance().setCustomKey("Version", BuildConfig.VERSION) + FirebaseCrashlytics.getInstance().setCustomKey("Remote", remote) + FirebaseCrashlytics.getInstance().setCustomKey("Commited", BuildConfig.COMMITED) + FirebaseCrashlytics.getInstance().setCustomKey("Hash", hashes[0]) } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt index d7ffdc5358..16a870ce61 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt @@ -7,9 +7,6 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.os.Bundle import androidx.annotation.XmlRes import androidx.preference.* -import dagger.android.AndroidInjector -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector import dagger.android.support.AndroidSupportInjection import info.nightscout.androidaps.Config import info.nightscout.androidaps.R @@ -58,9 +55,10 @@ import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject -class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListener, HasAndroidInjector { +class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListener { private var pluginId = -1 + private var filter = "" @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper @@ -102,11 +100,6 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang @Inject lateinit var nsSettingStatus: NSSettingsStatus @Inject lateinit var openHumansUploader: OpenHumansUploader - // TODO why? - @Inject lateinit var androidInjector: DispatchingAndroidInjector - - override fun androidInjector(): AndroidInjector = androidInjector - override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) super.onAttach(context) @@ -115,11 +108,13 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang override fun setArguments(args: Bundle?) { super.setArguments(args) pluginId = args?.getInt("id") ?: -1 + filter = args?.getString("filter") ?: "" } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putInt("id", pluginId) + outState.putString("filter", filter) } override fun onDestroy() { @@ -150,6 +145,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang if (bundle.containsKey("id")) { pluginId = bundle.getInt("id") } + if (bundle.containsKey("filter")) { + filter = bundle.getString("filter") ?: "" + } } if (pluginId != -1) { addPreferencesFromResource(pluginId, rootKey) @@ -175,7 +173,8 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang addPreferencesFromResourceIfEnabled(localInsightPlugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(comboPlugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS) - addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey, !config.NSCLIENT) + addPreferencesFromResource(R.xml.pref_pump, rootKey, config.PUMPDRIVERS) + addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey) addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey) addPreferencesFromResourceIfEnabled(nsClientPlugin, rootKey) addPreferencesFromResourceIfEnabled(tidepoolPlugin, rootKey) @@ -190,6 +189,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang } initSummary(preferenceScreen, pluginId != -1) preprocessPreferences() + if (filter != "") updateFilterVisibility(filter, preferenceScreen) } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { @@ -251,6 +251,10 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang } } + private fun addPreferencesFromResource(@Suppress("SameParameterValue") @XmlRes preferencesResId: Int, key: String?, enabled: Boolean) { + if (enabled) addPreferencesFromResource(preferencesResId, key) + } + @SuppressLint("RestrictedApi") private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) { val xmlRoot = preferenceManager.inflateFromResource(context, @@ -283,6 +287,33 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang } } + private fun updateFilterVisibility(filter: String, p: Preference): Boolean { + + var visible = false + + if (p is PreferenceGroup) { + for (i in 0 until p.preferenceCount) { + visible = updateFilterVisibility(filter, p.getPreference(i)) || visible + } + if (visible && p is PreferenceCategory) { + p.initialExpandedChildrenCount = Int.MAX_VALUE + } + } else { + if (p.key != null) { + visible = visible || p.key.contains(filter, true) + } + if (p.title != null) { + visible = visible || p.title.contains(filter, true) + } + if (p.summary != null) { + visible = visible || p.summary.contains(filter, true) + } + } + + p.isVisible = visible + return visible + } + private fun updatePrefSummary(pref: Preference?) { if (pref is ListPreference) { pref.setSummary(pref.entry) @@ -386,4 +417,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang } return super.onPreferenceTreeClick(preference) } + + fun setFilter(filter: String) { + this.filter = filter + updateFilterVisibility(filter, preferenceScreen) + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt index ea90f4b250..3a2fda604b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.kt @@ -2,11 +2,14 @@ package info.nightscout.androidaps.activities import android.content.Context import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceScreen import info.nightscout.androidaps.R import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.resources.ResourceHelper +import kotlinx.android.synthetic.main.activity_preferences.* import javax.inject.Inject class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback { @@ -14,18 +17,31 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa @Inject lateinit var resourceHelper: ResourceHelper var preferenceId = 0 + var myPreferenceFragment: MyPreferenceFragment? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_single_fragment) + setContentView(R.layout.activity_preferences) + + pref_filter.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + filterPreferences() + } + + override fun afterTextChanged(s: Editable) {} + }) + title = resourceHelper.gs(R.string.nav_preferences) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - val myPreferenceFragment = MyPreferenceFragment() + myPreferenceFragment = MyPreferenceFragment() preferenceId = intent.getIntExtra("id", -1) val args = Bundle() args.putInt("id", preferenceId) - myPreferenceFragment.arguments = args - supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment).commit() + args.putString("filter", pref_filter.text.toString()) + myPreferenceFragment?.arguments = args + supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment!!).commit() } override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat, pref: PreferenceScreen): Boolean { @@ -44,4 +60,8 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa override fun attachBaseContext(newBase: Context) { super.attachBaseContext(LocaleHelper.wrap(newBase)) } + + private fun filterPreferences() { + myPreferenceFragment?.setFilter(pref_filter.text.toString()) + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt index 0193b690a6..862509249e 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.kt @@ -9,6 +9,8 @@ import dagger.android.support.DaggerAppCompatActivity import info.nightscout.androidaps.R import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.plugins.configBuilder.PluginStore +import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs +import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract import info.nightscout.androidaps.utils.locale.LocaleHelper import info.nightscout.androidaps.utils.protection.ProtectionCheck import javax.inject.Inject @@ -16,9 +18,16 @@ import javax.inject.Inject class SingleFragmentActivity : DaggerAppCompatActivity() { @Inject lateinit var pluginStore: PluginStore @Inject lateinit var protectionCheck: ProtectionCheck + @Inject lateinit var importExportPrefs: ImportExportPrefs private var plugin: PluginBase? = null + val callForPrefFile = registerForActivityResult(PrefsFileContract()) { + it?.let { + importExportPrefs.importSharedPreferences(this, it) + } + } + public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_single_fragment) diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index ef38b9e44e..679e119b21 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -417,6 +417,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { getDaoBgReadings().update(bgReading); openHumansUploader.enqueueBGReading(bgReading); + aapsLogger.debug(LTag.DATABASE, "BG: Updating record from: "+ bgReading.toString()); + scheduleBgHistoryChange(bgReading.date); // trigger cache invalidation } catch (SQLException e) { aapsLogger.error("Unhandled exception", e); } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt index 8edce1ece4..f6790caa25 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/ActivitiesModule.kt @@ -10,7 +10,7 @@ import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImp import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity -import info.nightscout.androidaps.plugins.pump.common.dialog.RileyLinkBLEScanActivity +import info.nightscout.androidaps.plugins.pump.common.dialog.RileyLinkBLEConfigActivity import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingActivity @@ -33,7 +33,7 @@ abstract class ActivitiesModule { @ContributesAndroidInjector abstract fun contributesQuickWizardListActivity(): QuickWizardListActivity @ContributesAndroidInjector abstract fun contributesRequestDexcomPermissionActivity(): RequestDexcomPermissionActivity @ContributesAndroidInjector abstract fun contributesRileyLinkStatusActivity(): RileyLinkStatusActivity - @ContributesAndroidInjector abstract fun contributesRileyLinkBLEScanActivity(): RileyLinkBLEScanActivity + @ContributesAndroidInjector abstract fun contributesRileyLinkBLEConfigActivity(): RileyLinkBLEConfigActivity @ContributesAndroidInjector abstract fun contributesSetupWizardActivity(): SetupWizardActivity @ContributesAndroidInjector abstract fun contributesSingleFragmentActivity(): SingleFragmentActivity @ContributesAndroidInjector abstract fun contributesSmsCommunicatorOtpActivity(): SmsCommunicatorOtpActivity diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AutomationModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AutomationModule.kt index bf54732d93..04aacf5a84 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AutomationModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AutomationModule.kt @@ -39,6 +39,7 @@ abstract class AutomationModule { @ContributesAndroidInjector abstract fun actionLoopResumeInjector(): ActionLoopResume @ContributesAndroidInjector abstract fun actionLoopSuspendInjector(): ActionLoopSuspend @ContributesAndroidInjector abstract fun actionNotificationInjector(): ActionNotification + @ContributesAndroidInjector abstract fun actionAlarmInjector(): ActionAlarm @ContributesAndroidInjector abstract fun actionProfileSwitchInjector(): ActionProfileSwitch @ContributesAndroidInjector abstract fun actionProfileSwitchPercentInjector(): ActionProfileSwitchPercent @ContributesAndroidInjector abstract fun actionSendSMSInjector(): ActionSendSMS diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt index 42dd3e2972..c7cfec45eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt @@ -109,6 +109,7 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog @ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog @ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog + @ContributesAndroidInjector abstract fun contributesLoopDialog(): LoopDialog @ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog @ContributesAndroidInjector abstract fun contributesProfileSwitchDialog(): ProfileSwitchDialog @ContributesAndroidInjector abstract fun contributesTempBasalDialog(): TempBasalDialog diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt index 892c9c36a8..b28073a055 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt @@ -42,6 +42,7 @@ import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin +import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin @@ -155,6 +156,12 @@ abstract class PluginsModule { @IntKey(150) abstract fun bindMedtronicPumpPlugin(plugin: MedtronicPumpPlugin): PluginBase + @Binds + @PumpDriver + @IntoMap + @IntKey(155) + abstract fun bindOmnipodPumpPlugin(plugin: OmnipodPumpPlugin): PluginBase + @Binds @NotNSClient @IntoMap diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/SkinsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/SkinsModule.kt index cd71cc8fd2..feb0b2f812 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/SkinsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/SkinsModule.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.skins.SkinButtonsOn import info.nightscout.androidaps.skins.SkinClassic import info.nightscout.androidaps.skins.SkinInterface import info.nightscout.androidaps.skins.SkinLargeDisplay +import info.nightscout.androidaps.skins.SkinLowRes import javax.inject.Qualifier @Module @@ -32,6 +33,12 @@ open class SkinsModule { @IntKey(20) fun bindsSkinLargeDisplay(skinLargeDisplay: SkinLargeDisplay): SkinInterface = skinLargeDisplay + @Provides + @Skin + @IntoMap + @IntKey(30) + fun bindsSkinLowRes(skinLowRes: SkinLowRes): SkinInterface = skinLowRes + @Qualifier annotation class Skin } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt index 10c10b27f5..894f017995 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CalibrationDialog.kt @@ -58,7 +58,7 @@ class CalibrationDialog : DialogFragmentWithDate() { val units = profileFunction.getUnits() val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) val actions: LinkedList = LinkedList() - val bg = overview_calibration_bg.value + val bg = overview_calibration_bg?.value ?: return false actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, bg) + " " + unitLabel) if (bg > 0) { activity?.let { activity -> diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt index 22ed2bb688..f911c1ef66 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CarbsDialog.kt @@ -150,7 +150,7 @@ class CarbsDialog : DialogFragmentWithDate() { } override fun submit(): Boolean { - val carbs = overview_carbs_carbs.value.toInt() + val carbs = overview_carbs_carbs?.value?.toInt() ?: return false val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() val units = profileFunction.getUnits() val activityTTDuration = defaultValueHelper.determineActivityTTDuration() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt index bad46290aa..3dae80e53f 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/CareDialog.kt @@ -122,7 +122,7 @@ class CareDialog : DialogFragmentWithDate() { } } - val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).getGlucoseStatusData()?.glucose + val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).glucoseStatusData?.glucose ?: 0.0, profileFunction.getUnits()) val bgTextWatcher: TextWatcher = object : TextWatcher { override fun afterTextChanged(s: Editable) {} diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt index 78b436269a..3414325fab 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ExtendedBolusDialog.kt @@ -1,12 +1,12 @@ package info.nightscout.androidaps.dialogs +import android.content.Context import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.google.common.base.Joiner -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.ErrorHelperActivity import info.nightscout.androidaps.interfaces.ActivePluginProvider @@ -15,8 +15,8 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.HtmlHelper -import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.SafeParse +import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.extensions.formatColor import info.nightscout.androidaps.utils.resources.ResourceHelper import kotlinx.android.synthetic.main.dialog_extendedbolus.* @@ -27,7 +27,8 @@ import javax.inject.Inject import kotlin.math.abs class ExtendedBolusDialog : DialogFragmentWithDate() { - @Inject lateinit var mainApp: MainApp + + @Inject lateinit var ctx: Context @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var constraintChecker: ConstraintChecker @Inject lateinit var commandQueue: CommandQueueProvider @@ -62,7 +63,7 @@ class ExtendedBolusDialog : DialogFragmentWithDate() { } override fun submit(): Boolean { - val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text) + val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin?.text ?: return false) val durationInMinutes = actions_extendedbolus_duration.value.toInt() val actions: LinkedList = LinkedList() val insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value() @@ -77,12 +78,12 @@ class ExtendedBolusDialog : DialogFragmentWithDate() { commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() { override fun run() { if (!result.success) { - val i = Intent(mainApp, ErrorHelperActivity::class.java) + val i = Intent(ctx, ErrorHelperActivity::class.java) i.putExtra("soundid", R.raw.boluserror) i.putExtra("status", result.comment) i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror)) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - mainApp.startActivity(i) + ctx.startActivity(i) } } }) diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt index 24b2f798ea..167ee2cd84 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/FillDialog.kt @@ -85,7 +85,7 @@ class FillDialog : DialogFragmentWithDate() { } override fun submit(): Boolean { - val insulin = SafeParse.stringToDouble(fill_insulinamount.text) + val insulin = SafeParse.stringToDouble(fill_insulinamount?.text ?: return false) val actions: LinkedList = LinkedList() val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt index f1c9c406db..881d5f8de0 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt @@ -129,7 +129,7 @@ class InsulinDialog : DialogFragmentWithDate() { override fun submit(): Boolean { val pumpDescription = activePlugin.activePump.pumpDescription - val insulin = SafeParse.stringToDouble(overview_insulin_amount.text) + val insulin = SafeParse.stringToDouble(overview_insulin_amount?.text ?: return false) val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value() val actions: LinkedList = LinkedList() val units = profileFunction.getUnits() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt new file mode 100644 index 0000000000..cda4b6e0be --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/LoopDialog.kt @@ -0,0 +1,385 @@ +package info.nightscout.androidaps.dialogs + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import androidx.fragment.app.FragmentManager +import dagger.android.support.DaggerDialogFragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.ErrorHelperActivity +import info.nightscout.androidaps.databinding.DialogLoopBinding +import info.nightscout.androidaps.events.* +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.ToastUtils +import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Inject + +class LoopDialog : DaggerDialogFragment() { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var ctx: Context + @Inject lateinit var sp: SP + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var loopPlugin: LoopPlugin + @Inject lateinit var objectivesPlugin: ObjectivesPlugin + @Inject lateinit var activePlugin: ActivePluginProvider + @Inject lateinit var constraintChecker: ConstraintChecker + @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin + + private var showOkCancel: Boolean = true + private var _binding: DialogLoopBinding? = null + private var loopHandler = Handler() + private var refreshDialog: Runnable? = null + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onStart() { + super.onStart() + dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + override fun onSaveInstanceState(savedInstanceState: Bundle) { + super.onSaveInstanceState(savedInstanceState) + savedInstanceState.putInt("showOkCancel", if (showOkCancel) 1 else 0) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View { + // load data from bundle + (savedInstanceState ?: arguments)?.let { bundle -> + showOkCancel = bundle.getInt("showOkCancel", 1) == 1 + } + dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) + dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) + isCancelable = true + dialog?.setCanceledOnTouchOutside(false) + + _binding = DialogLoopBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + updateGUI("LoopDialogOnViewCreated") + + binding.overviewCloseloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewLgsloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewOpenloop.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisable.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewEnable.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewResume.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewReconnect.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewSuspend1h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewSuspend2h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewSuspend3h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewSuspend10h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisconnect15m.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisconnect30m.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisconnect1h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisconnect2h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + binding.overviewDisconnect3h.setOnClickListener { if (showOkCancel) onClickOkCancelEnabled(it) else onClick(it); dismiss() } + + // cancel button + binding.cancel.setOnClickListener { dismiss() } + + refreshDialog = Runnable { + scheduleUpdateGUI("refreshDialog") + loopHandler.postDelayed(refreshDialog, 15 * 1000L) + } + loopHandler.postDelayed(refreshDialog, 15 * 1000L) + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + _binding = null + loopHandler.removeCallbacksAndMessages(null) + } + + var task: Runnable? = null + + private fun scheduleUpdateGUI(from: String) { + class UpdateRunnable : Runnable { + + override fun run() { + updateGUI(from) + task = null + } + } + view?.removeCallbacks(task) + task = UpdateRunnable() + view?.postDelayed(task, 500) + } + + @Synchronized + fun updateGUI(from: String) { + if (_binding == null) return + aapsLogger.debug("UpdateGUI from $from") + val pumpDescription: PumpDescription = activePlugin.activePump.pumpDescription + val closedLoopAllowed = objectivesPlugin.isClosedLoopAllowed(Constraint(true)) + val lgsEnabled = objectivesPlugin.isLgsAllowed(Constraint(true)) + val apsMode = sp.getString(R.string.key_aps_mode, "open") + if (profileFunction.isProfileValid("LoopDialogUpdateGUI")) { + if (loopPlugin.isEnabled(PluginType.LOOP)) { + when { + closedLoopAllowed.value() -> { + binding.overviewCloseloop.visibility = (apsMode != "closed").toVisibility() + binding.overviewLgsloop.visibility = (apsMode != "lgs").toVisibility() + binding.overviewOpenloop.visibility = (apsMode != "open").toVisibility() + } + + lgsEnabled.value() -> { + binding.overviewCloseloop.visibility = View.GONE + binding.overviewLgsloop.visibility = (apsMode != "lgs").toVisibility() + binding.overviewOpenloop.visibility = (apsMode != "open").toVisibility() + } + + else -> { + binding.overviewCloseloop.visibility = View.GONE + binding.overviewLgsloop.visibility = View.GONE + binding.overviewOpenloop.visibility = View.GONE + } + } + binding.overviewEnable.visibility = View.GONE + binding.overviewDisable.visibility = View.VISIBLE + if (!loopPlugin.isSuspended) { + binding.overviewSuspendHeader.text = resourceHelper.gs(R.string.suspendloop) + binding.overviewResume.visibility = View.GONE + binding.overviewSuspendButtons.visibility = View.VISIBLE + binding.overviewSuspend.visibility = View.VISIBLE + } else { + if (!loopPlugin.isDisconnected) { + binding.overviewSuspendHeader.text = resourceHelper.gs(R.string.resumeloop) + binding.overviewResume.visibility = View.VISIBLE + binding.overviewSuspendButtons.visibility = View.GONE + binding.overviewSuspend.visibility = View.VISIBLE + } else + binding.overviewSuspend.visibility = View.GONE + } + } else { + binding.overviewEnable.visibility = View.VISIBLE + binding.overviewDisable.visibility = View.GONE + binding.overviewSuspend.visibility = View.GONE + } + if (!loopPlugin.isDisconnected) { + binding.overviewPumpHeader.text = resourceHelper.gs(R.string.disconnectpump) + binding.overviewDisconnect15m.visibility = pumpDescription.tempDurationStep15mAllowed.toVisibility() + binding.overviewDisconnect30m.visibility = pumpDescription.tempDurationStep30mAllowed.toVisibility() + binding.overviewDisconnectButtons.visibility = View.VISIBLE + binding.overviewReconnect.visibility = View.GONE + } else { + binding.overviewPumpHeader.text = resourceHelper.gs(R.string.reconnect) + binding.overviewDisconnectButtons.visibility = View.GONE + binding.overviewReconnect.visibility = View.VISIBLE + } + } + val profile = profileFunction.getProfile() + val profileStore = activePlugin.activeProfileInterface.profile + + if (profile == null || profileStore == null) { + ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.noprofile)) + dismiss() + return + } + + } + + private fun onClickOkCancelEnabled(v: View): Boolean { + var description = "" + when (v.id) { + R.id.overview_closeloop -> description = resourceHelper.gs(R.string.closedloop) + R.id.overview_lgsloop -> description = resourceHelper.gs(R.string.lowglucosesuspend) + R.id.overview_openloop -> description = resourceHelper.gs(R.string.openloop) + R.id.overview_disable -> description = resourceHelper.gs(R.string.disableloop) + R.id.overview_enable -> description = resourceHelper.gs(R.string.enableloop) + R.id.overview_resume -> description = resourceHelper.gs(R.string.resume) + R.id.overview_reconnect -> description = resourceHelper.gs(R.string.reconnect) + R.id.overview_suspend_1h -> description = resourceHelper.gs(R.string.suspendloopfor1h) + R.id.overview_suspend_2h -> description = resourceHelper.gs(R.string.suspendloopfor2h) + R.id.overview_suspend_3h -> description = resourceHelper.gs(R.string.suspendloopfor3h) + R.id.overview_suspend_10h -> description = resourceHelper.gs(R.string.suspendloopfor10h) + R.id.overview_disconnect_15m -> description = resourceHelper.gs(R.string.disconnectpumpfor15m) + R.id.overview_disconnect_30m -> description = resourceHelper.gs(R.string.disconnectpumpfor30m) + R.id.overview_disconnect_1h -> description = resourceHelper.gs(R.string.disconnectpumpfor1h) + R.id.overview_disconnect_2h -> description = resourceHelper.gs(R.string.disconnectpumpfor2h) + R.id.overview_disconnect_3h -> description = resourceHelper.gs(R.string.disconnectpumpfor3h) + } + activity?.let { activity -> + OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.confirm), description, Runnable { + onClick(v) + }) + } + return true + } + + fun onClick(v: View): Boolean { + val profile = profileFunction.getProfile() ?: return true + when (v.id) { + R.id.overview_closeloop -> { + aapsLogger.debug("USER ENTRY: CLOSED LOOP MODE") + sp.putString(R.string.key_aps_mode, "closed") + rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.closedloop))) + return true + } + + R.id.overview_lgsloop -> { + aapsLogger.debug("USER ENTRY: LGS LOOP MODE") + sp.putString(R.string.key_aps_mode, "lgs") + rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend))) + return true + } + + R.id.overview_openloop -> { + aapsLogger.debug("USER ENTRY: OPEN LOOP MODE") + sp.putString(R.string.key_aps_mode, "open") + rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.lowglucosesuspend))) + return true + } + + R.id.overview_disable -> { + aapsLogger.debug("USER ENTRY: LOOP DISABLED") + loopPlugin.setPluginEnabled(PluginType.LOOP, false) + loopPlugin.setFragmentVisible(PluginType.LOOP, false) + configBuilderPlugin.storeSettings("DisablingLoop") + rxBus.send(EventRefreshOverview("suspendmenu")) + commandQueue.cancelTempBasal(true, object : Callback() { + override fun run() { + if (!result.success) { + ToastUtils.showToastInUiThread(ctx, resourceHelper.gs(R.string.tempbasaldeliveryerror)) + } + } + }) + loopPlugin.createOfflineEvent(24 * 60) // upload 24h, we don't know real duration + return true + } + + R.id.overview_enable -> { + aapsLogger.debug("USER ENTRY: LOOP ENABLED") + loopPlugin.setPluginEnabled(PluginType.LOOP, true) + loopPlugin.setFragmentVisible(PluginType.LOOP, true) + configBuilderPlugin.storeSettings("EnablingLoop") + rxBus.send(EventRefreshOverview("suspendmenu")) + loopPlugin.createOfflineEvent(0) + return true + } + + R.id.overview_resume, R.id.overview_reconnect -> { + aapsLogger.debug("USER ENTRY: RESUME") + loopPlugin.suspendTo(0L) + rxBus.send(EventRefreshOverview("suspendmenu")) + commandQueue.cancelTempBasal(true, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(ctx, ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + ctx.startActivity(i) + } + } + }) + sp.putBoolean(R.string.key_objectiveusereconnect, true) + loopPlugin.createOfflineEvent(0) + return true + } + + R.id.overview_suspend_1h -> { + aapsLogger.debug("USER ENTRY: SUSPEND 1h") + loopPlugin.suspendLoop(60) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_suspend_2h -> { + aapsLogger.debug("USER ENTRY: SUSPEND 2h") + loopPlugin.suspendLoop(120) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_suspend_3h -> { + aapsLogger.debug("USER ENTRY: SUSPEND 3h") + loopPlugin.suspendLoop(180) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_suspend_10h -> { + aapsLogger.debug("USER ENTRY: SUSPEND 10h") + loopPlugin.suspendLoop(600) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_disconnect_15m -> { + aapsLogger.debug("USER ENTRY: DISCONNECT 15m") + loopPlugin.disconnectPump(15, profile) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_disconnect_30m -> { + aapsLogger.debug("USER ENTRY: DISCONNECT 30m") + loopPlugin.disconnectPump(30, profile) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_disconnect_1h -> { + aapsLogger.debug("USER ENTRY: DISCONNECT 1h") + loopPlugin.disconnectPump(60, profile) + sp.putBoolean(R.string.key_objectiveusedisconnect, true) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_disconnect_2h -> { + aapsLogger.debug("USER ENTRY: DISCONNECT 2h") + loopPlugin.disconnectPump(120, profile) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + + R.id.overview_disconnect_3h -> { + aapsLogger.debug("USER ENTRY: DISCONNECT 3h") + loopPlugin.disconnectPump(180, profile) + rxBus.send(EventRefreshOverview("suspendmenu")) + return true + } + } + return false + } + + override fun show(manager: FragmentManager, tag: String?) { + try { + manager.beginTransaction().let { + it.add(this, tag) + it.commitAllowingStateLoss() + } + } catch (e: IllegalStateException) { + aapsLogger.debug(e.localizedMessage) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt index 5ea091fa28..31cc463bdc 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/ProfileSwitchDialog.kt @@ -52,7 +52,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() { overview_profileswitch_duration.setParams(savedInstanceState?.getDouble("overview_profileswitch_duration") ?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok) overview_profileswitch_percentage.setParams(savedInstanceState?.getDouble("overview_profileswitch_percentage") - ?: 100.0, Constants.CPP_MIN_PERCENTAGE.toDouble(), Constants.CPP_MAX_PERCENTAGE.toDouble(), 1.0, DecimalFormat("0"), false, ok) + ?: 100.0, Constants.CPP_MIN_PERCENTAGE.toDouble(), Constants.CPP_MAX_PERCENTAGE.toDouble(), 5.0, DecimalFormat("0"), false, ok) overview_profileswitch_timeshift.setParams(savedInstanceState?.getDouble("overview_profileswitch_timeshift") ?: 0.0, Constants.CPP_MIN_TIMESHIFT.toDouble(), Constants.CPP_MAX_TIMESHIFT.toDouble(), 1.0, DecimalFormat("0"), false, ok) @@ -91,7 +91,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() { ?: return false val actions: LinkedList = LinkedList() - val duration = overview_profileswitch_duration.value.toInt() + val duration = overview_profileswitch_duration?.value?.toInt() ?: return false if (duration > 0) actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration)) val profile = overview_profileswitch_profile.selectedItem.toString() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt index 68be68e060..cf8fad96b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempBasalDialog.kt @@ -84,7 +84,7 @@ class TempBasalDialog : DialogFragmentWithDate() { override fun submit(): Boolean { var percent = 0 var absolute = 0.0 - val durationInMinutes = actions_tempbasal_duration.value.toInt() + val durationInMinutes = actions_tempbasal_duration?.value?.toInt() ?: return false val profile = profileFunction.getProfile() ?: return false val actions: LinkedList = LinkedList() if (isPercentPump) { diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt index e4f5208471..57c1689ada 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TempTargetDialog.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.db.TempTarget +import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin @@ -32,6 +33,9 @@ class TempTargetDialog : DialogFragmentWithDate() { @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var activePlugin: ActivePluginProvider + + lateinit var reasonList: List override fun onSaveInstanceState(savedInstanceState: Bundle) { super.onSaveInstanceState(savedInstanceState) @@ -64,59 +68,71 @@ class TempTargetDialog : DialogFragmentWithDate() { val units = profileFunction.getUnits() overview_temptarget_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl) + // temp target context?.let { context -> - val reasonList: List = Lists.newArrayList( + if (activePlugin.activeTreatments.tempTargetFromHistory != null) + overview_temptarget_cancel?.visibility = View.VISIBLE + else + overview_temptarget_cancel?.visibility = View.GONE + + reasonList = Lists.newArrayList( resourceHelper.gs(R.string.manual), - resourceHelper.gs(R.string.cancel), resourceHelper.gs(R.string.eatingsoon), resourceHelper.gs(R.string.activity), resourceHelper.gs(R.string.hypo) ) val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList) overview_temptarget_reason.adapter = adapterReason - overview_temptarget_reason.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - val defaultDuration: Double - val defaultTarget: Double - when (reasonList[position]) { - resourceHelper.gs(R.string.eatingsoon) -> { - defaultDuration = defaultValueHelper.determineEatingSoonTTDuration().toDouble() - defaultTarget = defaultValueHelper.determineEatingSoonTT() - } - resourceHelper.gs(R.string.activity) -> { - defaultDuration = defaultValueHelper.determineActivityTTDuration().toDouble() - defaultTarget = defaultValueHelper.determineActivityTT() - } + overview_temptarget_cancel?.setOnClickListener { shortClick(it) } + overview_temptarget_eating_soon?.setOnClickListener { shortClick(it) } + overview_temptarget_activity?.setOnClickListener { shortClick(it) } + overview_temptarget_hypo?.setOnClickListener { shortClick(it) } - resourceHelper.gs(R.string.hypo) -> { - defaultDuration = defaultValueHelper.determineHypoTTDuration().toDouble() - defaultTarget = defaultValueHelper.determineHypoTT() - } + overview_temptarget_eating_soon?.setOnLongClickListener { + longClick(it) + return@setOnLongClickListener true + } + overview_temptarget_activity?.setOnLongClickListener { + longClick(it) + return@setOnLongClickListener true + } + overview_temptarget_hypo?.setOnLongClickListener { + longClick(it) + return@setOnLongClickListener true + } + } + } - resourceHelper.gs(R.string.cancel) -> { - defaultDuration = 0.0 - defaultTarget = 0.0 - } + private fun shortClick(v:View){ + v.performLongClick() + if (submit()) dismiss() + } - else -> { - defaultDuration = overview_temptarget_duration.value - defaultTarget = overview_temptarget_temptarget.value - } - } - overview_temptarget_temptarget.value = defaultTarget - overview_temptarget_duration.value = defaultDuration - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} + private fun longClick(v:View) { + when (v.id) { + R.id.overview_temptarget_eating_soon -> { + overview_temptarget_temptarget.value = defaultValueHelper.determineEatingSoonTT() + overview_temptarget_duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble() + overview_temptarget_reason.setSelection(reasonList.indexOf( resourceHelper.gs(R.string.eatingsoon))) + } + R.id.overview_temptarget_activity -> { + overview_temptarget_temptarget.value = defaultValueHelper.determineActivityTT() + overview_temptarget_duration.value = defaultValueHelper.determineActivityTTDuration().toDouble() + overview_temptarget_reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.activity))) + } + R.id.overview_temptarget_hypo -> { + overview_temptarget_temptarget.value = defaultValueHelper.determineHypoTT() + overview_temptarget_duration.value = defaultValueHelper.determineHypoTTDuration().toDouble() + overview_temptarget_reason.setSelection(reasonList.indexOf(resourceHelper.gs(R.string.hypo))) } } } override fun submit(): Boolean { val actions: LinkedList = LinkedList() - val reason = overview_temptarget_reason.selectedItem.toString() + val reason = overview_temptarget_reason?.selectedItem?.toString() ?: return false val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol val target = overview_temptarget_temptarget.value val duration = overview_temptarget_duration.value.toInt() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt index 429862ede9..c54f7b8378 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/TreatmentDialog.kt @@ -94,7 +94,7 @@ class TreatmentDialog : DialogFragmentWithDate() { override fun submit(): Boolean { val pumpDescription = activePlugin.activePump.pumpDescription - val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text) + val insulin = SafeParse.stringToDouble(overview_treatment_insulin?.text ?: return false) val carbs = SafeParse.stringToInt(overview_treatment_carbs.text) val recordOnlyChecked = overview_treatment_record_only.isChecked val actions: LinkedList = LinkedList() diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index fb28182e33..63102ed9ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -18,6 +18,7 @@ import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.databinding.DialogWizardBinding import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint @@ -39,7 +40,6 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.wizard.BolusWizard import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import kotlinx.android.synthetic.main.dialog_wizard.* import java.text.DecimalFormat import java.util.* import javax.inject.Inject @@ -72,8 +72,23 @@ class WizardDialog : DaggerDialogFragment() { } } + private val timeTextWatcher = object : TextWatcher { + override fun afterTextChanged(s: Editable) {} + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + calculateInsulin() + binding.alarm.isChecked = binding.carbTimeInput.value > 0 + } + } + private var disposable: CompositeDisposable = CompositeDisposable() + private var _binding: DialogWizardBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + override fun onStart() { super.onStart() dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) @@ -81,49 +96,50 @@ class WizardDialog : DaggerDialogFragment() { override fun onSaveInstanceState(savedInstanceState: Bundle) { super.onSaveInstanceState(savedInstanceState) - savedInstanceState.putDouble("treatments_wizard_bg_input", treatments_wizard_bg_input.value) - savedInstanceState.putDouble("treatments_wizard_carbs_input", treatments_wizard_carbs_input.value) - savedInstanceState.putDouble("treatments_wizard_correction_input", treatments_wizard_correction_input.value) - savedInstanceState.putDouble("treatments_wizard_carb_time_input", treatments_wizard_carb_time_input.value) + savedInstanceState.putDouble("bg_input", binding.bgInput.value) + savedInstanceState.putDouble("carbs_input", binding.carbsInput.value) + savedInstanceState.putDouble("correction_input", binding.correctionInput.value) + savedInstanceState.putDouble("carb_time_input", binding.carbTimeInput.value) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + savedInstanceState: Bundle?): View { dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) isCancelable = true dialog?.setCanceledOnTouchOutside(false) - return inflater.inflate(R.layout.dialog_wizard, container, false) + _binding = DialogWizardBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { loadCheckedStates() processCobCheckBox() - treatments_wizard_sbcheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility() - treatments_wizard_notes_layout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility() + binding.sbcheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility() + binding.notesLayout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility() val maxCarbs = constraintChecker.getMaxCarbsAllowed().value() val maxCorrection = constraintChecker.getMaxBolusAllowed().value() if (profileFunction.getUnits() == Constants.MGDL) - treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input") - ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0.0"), false, ok, textWatcher) + binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") + ?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) else - treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input") - ?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher) - treatments_wizard_carbs_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carbs_input") - ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher) + binding.bgInput.setParams(savedInstanceState?.getDouble("bg_input") + ?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.ok, textWatcher) + binding.carbsInput.setParams(savedInstanceState?.getDouble("carbs_input") + ?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.ok, textWatcher) val bolusStep = activePlugin.activePump.pumpDescription.bolusStep - treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input") - ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher) - treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input") - ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) + binding.correctionInput.setParams(savedInstanceState?.getDouble("correction_input") + ?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.ok, textWatcher) + binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input") + ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.ok, timeTextWatcher) initDialog() - treatments_wizard_percent_used.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100)) + binding.percentUsed.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100)) // ok button - ok.setOnClickListener { + binding.ok.setOnClickListener { if (okClicked) { aapsLogger.debug(LTag.UI, "guarding: ok already clicked") } else { @@ -136,37 +152,37 @@ class WizardDialog : DaggerDialogFragment() { dismiss() } // cancel button - cancel.setOnClickListener { dismiss() } + binding.cancel.setOnClickListener { dismiss() } // checkboxes - treatments_wizard_bgcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_ttcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_cobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.bgcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.ttcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.cobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.basaliobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.bolusiobcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged) + binding.sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged) - val showCalc = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), false) - treatments_wizard_delimiter.visibility = showCalc.toVisibility() - treatments_wizard_resulttable.visibility = showCalc.toVisibility() - treatments_wizard_calculationcheckbox.isChecked = showCalc - treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked -> + val showCalc = sp.getBoolean(R.string.key_wizard_calculation_visible, false) + binding.delimiter.visibility = showCalc.toVisibility() + binding.resulttable.visibility = showCalc.toVisibility() + binding.calculationcheckbox.isChecked = showCalc + binding.calculationcheckbox.setOnCheckedChangeListener { _, isChecked -> run { sp.putBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), isChecked) - treatments_wizard_delimiter.visibility = isChecked.toVisibility() - treatments_wizard_resulttable.visibility = isChecked.toVisibility() + binding.delimiter.visibility = isChecked.toVisibility() + binding.resulttable.visibility = isChecked.toVisibility() } } // profile spinner - treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener { + binding.profile.onItemSelectedListener = object : OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) { ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected)) - ok.visibility = View.GONE + binding.ok.visibility = View.GONE } override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { calculateInsulin() - ok.visibility = View.VISIBLE + binding.ok.visibility = View.VISIBLE } } // bus @@ -183,36 +199,37 @@ class WizardDialog : DaggerDialogFragment() { override fun onDestroyView() { super.onDestroyView() disposable.clear() + _binding = null } private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) { saveCheckedStates() - treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null - if (buttonView.id == treatments_wizard_cobcheckbox.id) + binding.ttcheckbox.isEnabled = binding.bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null + if (buttonView.id == binding.cobcheckbox.id) processCobCheckBox() calculateInsulin() } private fun processCobCheckBox() { - if (treatments_wizard_cobcheckbox.isChecked) { - treatments_wizard_bolusiobcheckbox.isEnabled = false - treatments_wizard_basaliobcheckbox.isEnabled = false - treatments_wizard_bolusiobcheckbox.isChecked = true - treatments_wizard_basaliobcheckbox.isChecked = true + if (binding.cobcheckbox.isChecked) { + binding.bolusiobcheckbox.isEnabled = false + binding.basaliobcheckbox.isEnabled = false + binding.bolusiobcheckbox.isChecked = true + binding.basaliobcheckbox.isChecked = true } else { - treatments_wizard_bolusiobcheckbox.isEnabled = true - treatments_wizard_basaliobcheckbox.isEnabled = true + binding.bolusiobcheckbox.isEnabled = true + binding.basaliobcheckbox.isEnabled = true } } private fun saveCheckedStates() { - sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked) - sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked) + sp.putBoolean(R.string.key_wizard_include_cob, binding.cobcheckbox.isChecked) + sp.putBoolean(R.string.key_wizard_include_trend_bg, binding.bgtrendcheckbox.isChecked) } private fun loadCheckedStates() { - treatments_wizard_bgtrendcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), false) - treatments_wizard_cobcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), false) + binding.bgtrendcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_trend_bg, false) + binding.cobcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false) } private fun initDialog() { @@ -230,25 +247,25 @@ class WizardDialog : DaggerDialogFragment() { profileList.add(0, resourceHelper.gs(R.string.active)) context?.let { context -> val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) - treatments_wizard_profile.adapter = adapter + binding.profile.adapter = adapter } ?: return val units = profileFunction.getUnits() - treatments_wizard_bgunits.text = units + binding.bgunits.text = units if (units == Constants.MGDL) - treatments_wizard_bg_input.setStep(1.0) + binding.bgInput.setStep(1.0) else - treatments_wizard_bg_input.setStep(0.1) + binding.bgInput.setStep(0.1) // Set BG if not old val lastBg = iobCobCalculatorPlugin.actualBg() if (lastBg != null) { - treatments_wizard_bg_input.value = lastBg.valueToUnits(units) + binding.bgInput.value = lastBg.valueToUnits(units) } else { - treatments_wizard_bg_input.value = 0.0 + binding.bgInput.value = 0.0 } - treatments_wizard_ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null + binding.ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null // IOB calculation treatmentsPlugin.updateTotalIOBTreatments() @@ -256,19 +273,19 @@ class WizardDialog : DaggerDialogFragment() { treatmentsPlugin.updateTotalIOBTempBasals() val basalIob = treatmentsPlugin.lastCalculationTempBasals.round() - treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob) - treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob) + binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob) + binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob) calculateInsulin() - treatments_wizard_percent_used.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility() + binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility() } private fun calculateInsulin() { val profileStore = activePlugin.activeProfileInterface.profile - if (treatments_wizard_profile?.selectedItem == null || profileStore == null) + if (binding.profile.selectedItem == null || profileStore == null) return // not initialized yet - var profileName = treatments_wizard_profile.selectedItem.toString() + var profileName = binding.profile.selectedItem.toString() val specificProfile: Profile? if (profileName == resourceHelper.gs(R.string.active)) { specificProfile = profileFunction.getProfile() @@ -279,82 +296,83 @@ class WizardDialog : DaggerDialogFragment() { if (specificProfile == null) return // Entered values - var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text) - val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text) - val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text) + var bg = SafeParse.stringToDouble(binding.bgInput.text) + val carbs = SafeParse.stringToInt(binding.carbsInput.text) + val correction = SafeParse.stringToDouble(binding.correctionInput.text) val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() if (abs(carbs - carbsAfterConstraint) > 0.01) { - treatments_wizard_carbs_input.value = 0.0 + binding.carbsInput.value = 0.0 ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied)) return } - bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0 - val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null + bg = if (binding.bgcheckbox.isChecked) bg else 0.0 + val tempTarget = if (binding.ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null // COB var cob = 0.0 - if (treatments_wizard_cobcheckbox.isChecked) { + if (binding.cobcheckbox.isChecked) { val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard COB") cobInfo.displayCob?.let { cob = it } } - val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text) + val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text) wizard = BolusWizard(mainApp).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble(), - treatments_wizard_bgcheckbox.isChecked, - treatments_wizard_cobcheckbox.isChecked, - treatments_wizard_bolusiobcheckbox.isChecked, - treatments_wizard_basaliobcheckbox.isChecked, - treatments_wizard_sbcheckbox.isChecked, - treatments_wizard_ttcheckbox.isChecked, - treatments_wizard_bgtrendcheckbox.isChecked, - treatment_wizard_notes.text.toString(), carbTime) + binding.bgcheckbox.isChecked, + binding.cobcheckbox.isChecked, + binding.bolusiobcheckbox.isChecked, + binding.basaliobcheckbox.isChecked, + binding.sbcheckbox.isChecked, + binding.ttcheckbox.isChecked, + binding.bgtrendcheckbox.isChecked, + binding.alarm.isChecked, + binding.notes.text.toString(), carbTime) wizard?.let { wizard -> - treatments_wizard_bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens) - treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG) + binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens) + binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG) - treatments_wizard_carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) - treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs) + binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) + binding.carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs) - treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB) - treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalsIOB) + binding.bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB) + binding.basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalIOB) - treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection) + binding.correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection) // Superbolus - treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else "" - treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus) + binding.sb.text = if (binding.sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else "" + binding.sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus) // Trend - if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) { - treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "") + if (binding.bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) { + binding.bgtrend.text = ((if (wizard.trend > 0) "+" else "") + Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, profileFunction.getUnits()) + " " + profileFunction.getUnits()) } else { - treatments_wizard_bgtrend.text = "" + binding.bgtrend.text = "" } - treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend) + binding.bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend) // COB - if (treatments_wizard_cobcheckbox.isChecked) { - treatments_wizard_cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic) - treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB) + if (binding.cobcheckbox.isChecked) { + binding.cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic) + binding.cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB) } else { - treatments_wizard_cob.text = "" - treatments_wizard_cobinsulin.text = "" + binding.cob.text = "" + binding.cobinsulin.text = "" } if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) { val insulinText = if (wizard.calculatedTotalInsulin > 0.0) resourceHelper.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else "" val carbsText = if (carbsAfterConstraint > 0.0) resourceHelper.gs(R.string.format_carbs, carbsAfterConstraint) else "" - treatments_wizard_total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText) - ok.visibility = View.VISIBLE + binding.total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText) + binding.ok.visibility = View.VISIBLE } else { - treatments_wizard_total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()) - ok.visibility = View.INVISIBLE + binding.total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()) + binding.ok.visibility = View.INVISIBLE } } diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt index df22cabde6..255a73f755 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import android.widget.LinearLayout import android.widget.RelativeLayout import android.widget.TextView +import androidx.lifecycle.lifecycleScope import com.jjoe64.graphview.GraphView import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R @@ -37,13 +38,13 @@ import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers import kotlinx.android.synthetic.main.activity_historybrowse.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.* import javax.inject.Inject class HistoryBrowseActivity : NoSplashAppCompatActivity() { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var rxBus: RxBusWrapper @@ -144,7 +145,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { historybrowse_bggraph?.gridLabelRenderer?.labelVerticalWidth = axisWidth overviewMenus.setupChartMenu(overview_chartMenuButton) - prepareGraphs() + prepareGraphsIfNeeded(overviewMenus.setting.size) savedInstanceState?.let { bundle -> rangeToDisplay = bundle.getInt("rangeToDisplay", 0) start = bundle.getLong("start", 0) @@ -168,7 +169,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { if (it.cause is EventCustomCalculationFinished) { updateGUI("EventAutosensCalculationFinished", bgOnly = false) } - }) { fabricPrivacy::logException } + }, fabricPrivacy::logException) ) disposable.add(rxBus .toObservable(EventAutosensBgLoaded::class.java) @@ -178,22 +179,21 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { if (it.cause is EventCustomCalculationFinished) { updateGUI("EventAutosensCalculationFinished", bgOnly = true) } - }) { fabricPrivacy::logException } + }, fabricPrivacy::logException) ) disposable.add(rxBus .toObservable(EventIobCalculationProgress::class.java) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ overview_iobcalculationprogess?.text = it.progress }) { fabricPrivacy::logException } + .subscribe({ overview_iobcalculationprogess?.text = it.progress }, fabricPrivacy::logException) ) disposable.add(rxBus .toObservable(EventRefreshOverview::class.java) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ if (it.now) { - prepareGraphs() updateGUI("EventRefreshOverview", bgOnly = false) } - }) { fabricPrivacy::logException } + }, fabricPrivacy::logException) ) if (start == 0L) { // set start of current day @@ -217,8 +217,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { } - private fun prepareGraphs() { - val numOfGraphs = overviewMenus.setting.size + private fun prepareGraphsIfNeeded(numOfGraphs: Int) { if (numOfGraphs != secondaryGraphs.size - 1) { //aapsLogger.debug("New secondary graph count ${numOfGraphs-1}") @@ -256,7 +255,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { } private fun runCalculation(from: String) { - GlobalScope.launch(Dispatchers.Default) { + lifecycleScope.launch(Dispatchers.Default) { treatmentsPluginHistory.initializeData(start - T.hours(8).msecs()) val end = start + T.hours(rangeToDisplay.toLong()).msecs() iobCobCalculatorPluginHistory.stopCalculation(from) @@ -266,6 +265,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { } fun updateGUI(from: String, bgOnly: Boolean) { + val menuChartSettings = overviewMenus.setting + prepareGraphsIfNeeded(menuChartSettings.size) aapsLogger.debug(LTag.UI, "updateGUI from: $from") val pump = activePlugin.activePump val profile = profileFunction.getProfile() @@ -273,7 +274,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { val lowLine = defaultValueHelper.determineLowLine() val highLine = defaultValueHelper.determineHighLine() - GlobalScope.launch(Dispatchers.Main) { + lifecycleScope.launch(Dispatchers.Main) { historybrowse_noprofile?.visibility = (profile == null).toVisibility() profile ?: return@launch @@ -308,11 +309,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { if (!bgOnly) { // Treatments graphData.addTreatments(fromTime, toTime) - if (overviewMenus.setting[0][OverviewMenus.CharType.ACT.ordinal]) + if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal]) graphData.addActivity(fromTime, toTime, false, 0.8) // add basal data - if (pump.pumpDescription.isTempBasalCapable && overviewMenus.setting[0][OverviewMenus.CharType.BAS.ordinal]) { + if (pump.pumpDescription.isTempBasalCapable && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal]) { graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2) } // ------------------ 2nd graph @@ -326,22 +327,22 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { var useIAForScale = false var useABSForScale = false when { - overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true - overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true + menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true } - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, overviewMenus.setting[g + 1][OverviewMenus.CharType.PRE.ordinal]) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) - if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, menuChartSettings[g + 1][OverviewMenus.CharType.PRE.ordinal]) + if (menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) + if (menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) + if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) // set manual x bounds to have nice steps secondGraphData.formatAxis(fromTime, toTime) @@ -356,13 +357,13 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() { for (g in 0 until secondaryGraphs.size) { secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1) secondaryGraphs[g].visibility = (!bgOnly && ( - overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] || - overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] + menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.ACT.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] || + menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] )).toVisibility() secondaryGraphsData[g].performUpdate() } diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt index caa0fb1b1a..f9d0a4019b 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/TreatmentsPluginHistory.kt @@ -7,6 +7,7 @@ import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.treatments.TreatmentService import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil @@ -27,8 +28,10 @@ class TreatmentsPluginHistory @Inject constructor( profileFunction: ProfileFunction, activePlugin: ActivePluginProvider, nsUpload: NSUpload, - fabricPrivacy: FabricPrivacy, dateUtil: DateUtil -) : TreatmentsPlugin(injector, aapsLogger, rxBus, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil) { + fabricPrivacy: FabricPrivacy, + dateUtil: DateUtil, + uploadQueue: UploadQueue +) : TreatmentsPlugin(injector, aapsLogger, rxBus, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil, uploadQueue) { init { onStart() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 0040dbc6fc..0c27aeac44 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -22,6 +22,7 @@ import javax.inject.Singleton; import dagger.Lazy; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; @@ -55,10 +56,10 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; @@ -95,9 +96,8 @@ public class LoopPlugin extends PluginBase implements LoopInterface { private final FabricPrivacy fabricPrivacy; private final NSUpload nsUpload; private final HardLimits hardLimits; - private Notification notification; - private CompositeDisposable disposable = new CompositeDisposable(); + private final CompositeDisposable disposable = new CompositeDisposable(); private static final String CHANNEL_ID = "AndroidAPS-Openloop"; @@ -126,6 +126,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { AAPSLogger aapsLogger, RxBusWrapper rxBus, SP sp, + Config config, ConstraintChecker constraintChecker, ResourceHelper resourceHelper, ProfileFunction profileFunction, @@ -144,9 +145,11 @@ public class LoopPlugin extends PluginBase implements LoopInterface { super(new PluginDescription() .mainType(PluginType.LOOP) .fragmentClass(LoopFragment.class.getName()) + .pluginIcon(R.drawable.ic_loop_closed_white) .pluginName(R.string.loop) .shortName(R.string.loop_shortname) .preferencesId(R.xml.pref_loop) + .enableByDefault(config.getAPS()) .description(R.string.description_loop), aapsLogger, resourceHelper, injector ); @@ -415,7 +418,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { resultAfterConstraints.smb = 0; } - if (lastRun != null) { + if (lastRun != null && lastRun.getConstraintsProcessed() != null) { prevCarbsreq = lastRun.getConstraintsProcessed().carbsReq; } @@ -551,6 +554,9 @@ public class LoopPlugin extends PluginBase implements LoopInterface { rxBus.send(new EventLoopUpdateGui()); } }); + } else { + lastRun.setTbrSetByPump(result); + lastRun.setLastTBRRequest(lastRun.getLastAPSRun()); } rxBus.send(new EventLoopUpdateGui()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java index a5b4fdff9b..a6876a3144 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java @@ -40,7 +40,7 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.sharedPreferences.SP; public class DetermineBasalAdapterAMAJS { - private HasAndroidInjector injector; + private final HasAndroidInjector injector; @Inject AAPSLogger aapsLogger; @Inject ConstraintChecker constraintChecker; @Inject SP sp; @@ -48,7 +48,7 @@ public class DetermineBasalAdapterAMAJS { @Inject TreatmentsPlugin treatmentsPlugin; @Inject OpenHumansUploader openHumansUploader; - private ScriptReader mScriptReader; + private final ScriptReader mScriptReader; private JSONObject mProfile; private JSONObject mGlucoseStatus; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java index 0cb082f368..7d132db4d3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java @@ -80,6 +80,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { super(new PluginDescription() .mainType(PluginType.APS) .fragmentClass(OpenAPSAMAFragment.class.getName()) + .pluginIcon(R.drawable.ic_generic_icon) .pluginName(R.string.openapsama) .shortName(R.string.oaps_shortname) .preferencesId(R.xml.pref_openapsama) @@ -189,9 +190,9 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { } - if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.getMINDIA(), hardLimits.getMAXDIA())) + if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.minDia(), hardLimits.maxDia())) return; - if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.getMINIC(), hardLimits.getMAXIC())) + if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return; if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), "sens", hardLimits.getMINISF(), hardLimits.getMAXISF())) return; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java index 0331ea6146..e42b139f3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java @@ -19,7 +19,6 @@ import java.nio.charset.StandardCharsets; import javax.annotation.Nullable; import javax.inject.Inject; -import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; @@ -28,13 +27,14 @@ import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.ActivePluginProvider; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback; import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.interfaces.ProfileFunction; +import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; @@ -55,7 +55,7 @@ public class DetermineBasalAdapterSMBJS { @Inject OpenHumansUploader openHumansUploader; - private ScriptReader mScriptReader; + private final ScriptReader mScriptReader; private JSONObject mProfile; private JSONObject mGlucoseStatus; private JSONArray mIobData; @@ -65,6 +65,7 @@ public class DetermineBasalAdapterSMBJS { private boolean mMicrobolusAllowed; private boolean mSMBAlwaysAllowed; private long mCurrentTime; + private boolean mIsSaveCgmSource; private String storedCurrentTemp = null; private String storedIobData = null; @@ -72,10 +73,6 @@ public class DetermineBasalAdapterSMBJS { private String storedGlucoseStatus = null; private String storedProfile = null; private String storedMeal_data = null; - private String storedAutosens_data = null; - private String storedMicroBolusAllowed = null; - private String storedSMBAlwaysAllowed = null; - private String storedCurrentTime = null; private String scriptDebug = ""; @@ -101,13 +98,14 @@ public class DetermineBasalAdapterSMBJS { aapsLogger.debug(LTag.APS, "Profile: " + (storedProfile = mProfile.toString())); aapsLogger.debug(LTag.APS, "Meal data: " + (storedMeal_data = mMealData.toString())); if (mAutosensData != null) - aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = mAutosensData.toString())); + aapsLogger.debug(LTag.APS, "Autosens data: " + mAutosensData.toString()); else - aapsLogger.debug(LTag.APS, "Autosens data: " + (storedAutosens_data = "undefined")); + aapsLogger.debug(LTag.APS, "Autosens data: " + "undefined"); aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined"); - aapsLogger.debug(LTag.APS, "MicroBolusAllowed: " + (storedMicroBolusAllowed = "" + mMicrobolusAllowed)); - aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: " + (storedSMBAlwaysAllowed = "" + mSMBAlwaysAllowed)); - aapsLogger.debug(LTag.APS, "CurrentTime: " + (storedCurrentTime = "" + mCurrentTime)); + aapsLogger.debug(LTag.APS, "MicroBolusAllowed: " + mMicrobolusAllowed); + aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: " + mSMBAlwaysAllowed); + aapsLogger.debug(LTag.APS, "CurrentTime: " + mCurrentTime); + aapsLogger.debug(LTag.APS, "isSaveCgmSource: " + mIsSaveCgmSource); DetermineBasalResultSMB determineBasalResultSMB = null; @@ -149,9 +147,10 @@ public class DetermineBasalAdapterSMBJS { makeParam(mAutosensData, rhino, scope), makeParam(mMealData, rhino, scope), setTempBasalFunctionsObj, - new Boolean(mMicrobolusAllowed), + Boolean.valueOf(mMicrobolusAllowed), makeParam(null, rhino, scope), // reservoir data as undefined - new Long(mCurrentTime) + Long.valueOf(mCurrentTime), + Boolean.valueOf(mIsSaveCgmSource) }; @@ -211,14 +210,6 @@ public class DetermineBasalAdapterSMBJS { return storedMeal_data; } - String getAutosensDataParam() { - return storedAutosens_data; - } - - String getMicroBolusAllowedParam() { - return storedMicroBolusAllowed; - } - String getScriptDebug() { return scriptDebug; } @@ -237,10 +228,10 @@ public class DetermineBasalAdapterSMBJS { boolean tempTargetSet, boolean microBolusAllowed, boolean uamAllowed, - boolean advancedFiltering + boolean advancedFiltering, + boolean isSaveCgmSource ) throws JSONException { - String units = profile.getUnits(); PumpInterface pump = activePluginProvider.getActivePump(); Double pumpbolusstep = pump.getPumpDescription().bolusStep; mProfile = new JSONObject(); @@ -264,8 +255,8 @@ public class DetermineBasalAdapterSMBJS { mProfile.put("low_temptarget_lowers_sensitivity", false); - mProfile.put("sensitivity_raises_target", sp.getBoolean(resourceHelper.gs(R.string.key_sensitivity_raises_target),SMBDefaults.sensitivity_raises_target)); - mProfile.put("resistance_lowers_target", sp.getBoolean(resourceHelper.gs(R.string.key_resistance_lowers_target),SMBDefaults.resistance_lowers_target)); + mProfile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target)); + mProfile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target)); mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments); mProfile.put("exercise_mode", SMBDefaults.exercise_mode); mProfile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target); @@ -281,7 +272,7 @@ public class DetermineBasalAdapterSMBJS { mProfile.put("enableUAM", uamAllowed); mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable); - boolean smbEnabled = sp.getBoolean(resourceHelper.gs(R.string.key_use_smb), false); + boolean smbEnabled = sp.getBoolean(R.string.key_use_smb, false); mProfile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval)); mProfile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false)); mProfile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false)); @@ -354,20 +345,19 @@ public class DetermineBasalAdapterSMBJS { mCurrentTime = now; + mIsSaveCgmSource = isSaveCgmSource; } private Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) { if (jsonObject == null) return Undefined.instance; - Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); - return param; + return NativeJSON.parse(rhino, scope, jsonObject.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); } private Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) { //Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() { - Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); - return param; + return NativeJSON.parse(rhino, scope, jsonArray.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); } private String readFile(String filename) throws IOException { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index 3e54eb8a3a..4a6ec60b7d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -88,6 +88,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr super(new PluginDescription() .mainType(PluginType.APS) .fragmentClass(OpenAPSSMBFragment.class.getName()) + .pluginIcon(R.drawable.ic_generic_icon) .pluginName(R.string.openapssmb) .shortName(R.string.smb_shortname) .preferencesId(R.xml.pref_openapssmb) @@ -220,9 +221,9 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr } - if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.getMINDIA(), hardLimits.getMAXDIA())) + if (!hardLimits.checkOnlyHardLimits(profile.getDia(), "dia", hardLimits.minDia(), hardLimits.maxDia())) return; - if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.getMINIC(), hardLimits.getMAXIC())) + if (!hardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(Profile.secondsFromMidnight()), "carbratio", hardLimits.minIC(), hardLimits.maxIC())) return; if (!hardLimits.checkOnlyHardLimits(profile.getIsfMgdl(), "sens", hardLimits.getMINISF(), hardLimits.getMAXISF())) return; @@ -270,7 +271,8 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr isTempTarget, smbAllowed.value(), uam.value(), - advancedFiltering.value() + advancedFiltering.value(), + activePlugin.getActiveBgSource().getClass().getSimpleName().equals("DexcomPlugin") ); } catch (JSONException e) { fabricPrivacy.logException(e); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt index 3badb56824..09bbf3c04d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt @@ -5,12 +5,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.CheckBox -import android.widget.ImageButton -import android.widget.LinearLayout -import android.widget.RadioButton -import android.widget.TextView +import android.widget.* import androidx.annotation.StringRes +import androidx.core.content.ContextCompat import dagger.android.support.DaggerFragment import info.nightscout.androidaps.Config import info.nightscout.androidaps.R @@ -129,6 +126,7 @@ class ConfigBuilderFragment : DaggerFragment() { val baseView: LinearLayout = fragment.layoutInflater.inflate(R.layout.configbuilder_single_plugin, null) as LinearLayout private val enabledExclusive: RadioButton private val enabledInclusive: CheckBox + private val pluginIcon: ImageView private val pluginName: TextView private val pluginDescription: TextView private val pluginPreferences: ImageButton @@ -137,6 +135,7 @@ class ConfigBuilderFragment : DaggerFragment() { init { enabledExclusive = baseView.findViewById(R.id.plugin_enabled_exclusive) enabledInclusive = baseView.findViewById(R.id.plugin_enabled_inclusive) + pluginIcon = baseView.findViewById(R.id.plugin_icon) pluginName = baseView.findViewById(R.id.plugin_name) pluginDescription = baseView.findViewById(R.id.plugin_description) pluginPreferences = baseView.findViewById(R.id.plugin_preferences) @@ -175,6 +174,12 @@ class ConfigBuilderFragment : DaggerFragment() { enabledInclusive.isChecked = plugin.isEnabled(pluginType) enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled enabledExclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled + if(plugin.menuIcon != -1) { + pluginIcon.visibility = View.VISIBLE + pluginIcon.setImageDrawable(context?.let { ContextCompat.getDrawable(it, plugin.menuIcon) }) + } else { + pluginIcon.visibility = View.GONE + } pluginName.text = plugin.name if (plugin.description == null) pluginDescription.visibility = View.GONE diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.kt index 598ddf085f..4fb140d55a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.kt @@ -32,6 +32,7 @@ class ConfigBuilderPlugin @Inject constructor( .showInList(true) .alwaysEnabled(true) .alwaysVisible(false) + .pluginIcon(R.drawable.ic_cogs) .pluginName(R.string.configbuilder) .shortName(R.string.configbuilder_shortname) .description(R.string.description_config_builder), @@ -46,17 +47,17 @@ class ConfigBuilderPlugin @Inject constructor( } private fun setAlwaysEnabledPluginsEnabled() { - for (plugin in activePlugin.pluginsList) { + for (plugin in activePlugin.getPluginsList()) { if (plugin.pluginDescription.alwaysEnabled) plugin.setPluginEnabled(plugin.getType(), true) } storeSettings("setAlwaysEnabledPluginsEnabled") } override fun storeSettings(from: String) { - activePlugin.pluginsList + activePlugin.getPluginsList() aapsLogger.debug(LTag.CONFIGBUILDER, "Storing settings from: $from") activePlugin.verifySelectionInCategories() - for (p in activePlugin.pluginsList) { + for (p in activePlugin.getPluginsList()) { val type = p.getType() if (p.pluginDescription.alwaysEnabled && p.pluginDescription.alwaysVisible) continue if (p.pluginDescription.alwaysEnabled && p.pluginDescription.neverVisible) continue @@ -82,7 +83,7 @@ class ConfigBuilderPlugin @Inject constructor( private fun loadSettings() { aapsLogger.debug(LTag.CONFIGBUILDER, "Loading stored settings") - for (p in activePlugin.pluginsList) { + for (p in activePlugin.getPluginsList()) { val type = p.getType() loadPref(p, type, true) if (p.getType() == PluginType.PUMP) { @@ -110,7 +111,7 @@ class ConfigBuilderPlugin @Inject constructor( } fun logPluginStatus() { - for (p in activePlugin.pluginsList) { + for (p in activePlugin.getPluginsList()) { aapsLogger.debug(LTag.CONFIGBUILDER, p.name + ":" + (if (p.isEnabled(PluginType.GENERAL)) " GENERAL" else "") + (if (p.isEnabled(PluginType.TREATMENT)) " TREATMENT" else "") + @@ -147,7 +148,7 @@ class ConfigBuilderPlugin @Inject constructor( } } - fun performPluginSwitch(changedPlugin: PluginBase, enabled: Boolean, type: PluginType) { + override fun performPluginSwitch(changedPlugin: PluginBase, enabled: Boolean, type: PluginType) { changedPlugin.setPluginEnabled(type, enabled) changedPlugin.setFragmentVisible(type, enabled) processOnEnabledCategoryChanged(changedPlugin, type) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginStore.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginStore.kt index 3958f17d78..05b020fac4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginStore.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginStore.kt @@ -15,13 +15,13 @@ class PluginStore @Inject constructor( lateinit var plugins: List<@JvmSuppressWildcards PluginBase> - private var activeBgSource: BgSourceInterface? = null - private var activePump: PumpInterface? = null + private var activeBgSourceStore: BgSourceInterface? = null + private var activePumpStore: PumpInterface? = null private var activeProfile: ProfileInterface? = null - private var activeAPS: APSInterface? = null - private var activeInsulin: InsulinInterface? = null - private var activeSensitivity: SensitivityInterface? = null - private var activeTreatments: TreatmentsInterface? = null + private var activeAPSStore: APSInterface? = null + private var activeInsulinStore: InsulinInterface? = null + private var activeSensitivityStore: SensitivityInterface? = null + private var activeTreatmentsStore: TreatmentsInterface? = null fun loadDefaults() { verifySelectionInCategories() @@ -71,34 +71,34 @@ class PluginStore @Inject constructor( // PluginType.APS if (!config.NSCLIENT && !config.PUMPCONTROL) { pluginsInCategory = getSpecificPluginsList(PluginType.APS) - activeAPS = getTheOneEnabledInArray(pluginsInCategory, PluginType.APS) as APSInterface? - if (activeAPS == null) { - activeAPS = getDefaultPlugin(PluginType.APS) as APSInterface - (activeAPS as PluginBase).setPluginEnabled(PluginType.APS, true) + activeAPSStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.APS) as APSInterface? + if (activeAPSStore == null) { + activeAPSStore = getDefaultPlugin(PluginType.APS) as APSInterface + (activeAPSStore as PluginBase).setPluginEnabled(PluginType.APS, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting APSInterface") } - setFragmentVisiblities((activeAPS as PluginBase).name, pluginsInCategory, PluginType.APS) + setFragmentVisiblities((activeAPSStore as PluginBase).name, pluginsInCategory, PluginType.APS) } // PluginType.INSULIN pluginsInCategory = getSpecificPluginsList(PluginType.INSULIN) - activeInsulin = getTheOneEnabledInArray(pluginsInCategory, PluginType.INSULIN) as InsulinInterface? - if (activeInsulin == null) { - activeInsulin = getDefaultPlugin(PluginType.INSULIN) as InsulinInterface - (activeInsulin as PluginBase).setPluginEnabled(PluginType.INSULIN, true) + activeInsulinStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.INSULIN) as InsulinInterface? + if (activeInsulinStore == null) { + activeInsulinStore = getDefaultPlugin(PluginType.INSULIN) as InsulinInterface + (activeInsulinStore as PluginBase).setPluginEnabled(PluginType.INSULIN, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting InsulinInterface") } - setFragmentVisiblities((activeInsulin as PluginBase).name, pluginsInCategory, PluginType.INSULIN) + setFragmentVisiblities((activeInsulinStore as PluginBase).name, pluginsInCategory, PluginType.INSULIN) // PluginType.SENSITIVITY pluginsInCategory = getSpecificPluginsList(PluginType.SENSITIVITY) - activeSensitivity = getTheOneEnabledInArray(pluginsInCategory, PluginType.SENSITIVITY) as SensitivityInterface? - if (activeSensitivity == null) { - activeSensitivity = getDefaultPlugin(PluginType.SENSITIVITY) as SensitivityInterface - (activeSensitivity as PluginBase).setPluginEnabled(PluginType.SENSITIVITY, true) + activeSensitivityStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.SENSITIVITY) as SensitivityInterface? + if (activeSensitivityStore == null) { + activeSensitivityStore = getDefaultPlugin(PluginType.SENSITIVITY) as SensitivityInterface + (activeSensitivityStore as PluginBase).setPluginEnabled(PluginType.SENSITIVITY, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting SensitivityInterface") } - setFragmentVisiblities((activeSensitivity as PluginBase).name, pluginsInCategory, PluginType.SENSITIVITY) + setFragmentVisiblities((activeSensitivityStore as PluginBase).name, pluginsInCategory, PluginType.SENSITIVITY) // PluginType.PROFILE pluginsInCategory = getSpecificPluginsList(PluginType.PROFILE) @@ -112,33 +112,33 @@ class PluginStore @Inject constructor( // PluginType.BGSOURCE pluginsInCategory = getSpecificPluginsList(PluginType.BGSOURCE) - activeBgSource = getTheOneEnabledInArray(pluginsInCategory, PluginType.BGSOURCE) as BgSourceInterface? - if (activeBgSource == null) { - activeBgSource = getDefaultPlugin(PluginType.BGSOURCE) as BgSourceInterface - (activeBgSource as PluginBase).setPluginEnabled(PluginType.BGSOURCE, true) + activeBgSourceStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.BGSOURCE) as BgSourceInterface? + if (activeBgSourceStore == null) { + activeBgSourceStore = getDefaultPlugin(PluginType.BGSOURCE) as BgSourceInterface + (activeBgSourceStore as PluginBase).setPluginEnabled(PluginType.BGSOURCE, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting BgInterface") } - setFragmentVisiblities((activeBgSource as PluginBase).name, pluginsInCategory, PluginType.PUMP) + setFragmentVisiblities((activeBgSourceStore as PluginBase).name, pluginsInCategory, PluginType.PUMP) // PluginType.PUMP pluginsInCategory = getSpecificPluginsList(PluginType.PUMP) - activePump = getTheOneEnabledInArray(pluginsInCategory, PluginType.PUMP) as PumpInterface? - if (activePump == null) { - activePump = getDefaultPlugin(PluginType.PUMP) as PumpInterface - (activePump as PluginBase).setPluginEnabled(PluginType.PUMP, true) + activePumpStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.PUMP) as PumpInterface? + if (activePumpStore == null) { + activePumpStore = getDefaultPlugin(PluginType.PUMP) as PumpInterface + (activePumpStore as PluginBase).setPluginEnabled(PluginType.PUMP, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface") } - setFragmentVisiblities((activePump as PluginBase).name, pluginsInCategory, PluginType.PUMP) + setFragmentVisiblities((activePumpStore as PluginBase).name, pluginsInCategory, PluginType.PUMP) // PluginType.TREATMENT pluginsInCategory = getSpecificPluginsList(PluginType.TREATMENT) - activeTreatments = getTheOneEnabledInArray(pluginsInCategory, PluginType.TREATMENT) as TreatmentsInterface? - if (activeTreatments == null) { - activeTreatments = getDefaultPlugin(PluginType.TREATMENT) as TreatmentsInterface - (activeTreatments as PluginBase).setPluginEnabled(PluginType.TREATMENT, true) + activeTreatmentsStore = getTheOneEnabledInArray(pluginsInCategory, PluginType.TREATMENT) as TreatmentsInterface? + if (activeTreatmentsStore == null) { + activeTreatmentsStore = getDefaultPlugin(PluginType.TREATMENT) as TreatmentsInterface + (activeTreatmentsStore as PluginBase).setPluginEnabled(PluginType.TREATMENT, true) aapsLogger.debug(LTag.CONFIGBUILDER, "Defaulting PumpInterface") } - setFragmentVisiblities((activeTreatments as PluginBase).name, pluginsInCategory, PluginType.TREATMENT) + setFragmentVisiblities((activeTreatmentsStore as PluginBase).name, pluginsInCategory, PluginType.TREATMENT) } /** @@ -203,27 +203,31 @@ class PluginStore @Inject constructor( // ***** Interface ***** - override fun getActiveBgSource(): BgSourceInterface { - return activeBgSource ?: checkNotNull(activeBgSource) { "No bg source selected" } - } + override val activeBgSource: BgSourceInterface + get() = activeBgSourceStore ?: checkNotNull(activeBgSourceStore) { "No bg source selected" } - override fun getActiveProfileInterface(): ProfileInterface = - activeProfile ?: checkNotNull(activeProfile) { "No profile selected" } + override val activeProfileInterface: ProfileInterface + get() = activeProfile ?: checkNotNull(activeProfile) { "No profile selected" } - override fun getActiveInsulin(): InsulinInterface = - activeInsulin ?: checkNotNull(activeInsulin) { "No insulin selected" } + override val activeInsulin: InsulinInterface + get() = activeInsulinStore ?: checkNotNull(activeInsulinStore) { "No insulin selected" } - override fun getActiveAPS(): APSInterface = - activeAPS ?: checkNotNull(activeAPS) { "No APS selected" } + override val activeAPS: APSInterface + get() = activeAPSStore ?: checkNotNull(activeAPSStore) { "No APS selected" } - override fun getActivePump(): PumpInterface = - activePump ?: checkNotNull(activePump) { "No pump selected" } + override val activePump: PumpInterface + get() = activePumpStore ?: checkNotNull(activePumpStore) { "No pump selected" } - override fun getActiveSensitivity(): SensitivityInterface = - activeSensitivity ?: checkNotNull(activeSensitivity) { "No sensitivity selected" } + override val activeSensitivity: SensitivityInterface + get() = activeSensitivityStore + ?: checkNotNull(activeSensitivityStore) { "No sensitivity selected" } - override fun getActiveTreatments(): TreatmentsInterface = - activeTreatments ?: checkNotNull(activeTreatments) { "No treatments selected" } + override val activeTreatments: TreatmentsInterface + get() = activeTreatmentsStore + ?: checkNotNull(activeTreatmentsStore) { "No treatments selected" } + + override val activeOverview: OverviewInterface + get() = getSpecificPluginsListByInterface(OverviewInterface::class.java).first() as OverviewInterface override fun getPluginsList(): ArrayList = ArrayList(plugins) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/events/EventConfigBuilderUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/events/EventConfigBuilderUpdateGui.kt index 26904127dd..8d24c912ad 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/events/EventConfigBuilderUpdateGui.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/events/EventConfigBuilderUpdateGui.kt @@ -2,5 +2,4 @@ package info.nightscout.androidaps.plugins.configBuilder.events import info.nightscout.androidaps.events.EventUpdateGui -class EventConfigBuilderUpdateGui : EventUpdateGui() { -} \ No newline at end of file +class EventConfigBuilderUpdateGui : EventUpdateGui() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt index cc57908438..009812a1f2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.constraints.objectives -import android.app.Activity +import androidx.fragment.app.FragmentActivity import com.google.common.base.Charsets import com.google.common.hash.Hashing import dagger.android.HasAndroidInjector @@ -32,6 +32,7 @@ class ObjectivesPlugin @Inject constructor( .fragmentClass(ObjectivesFragment::class.qualifiedName) .alwaysEnabled(config.APS) .showInList(config.APS) + .pluginIcon(R.drawable.ic_graduation) .pluginName(R.string.objectives) .shortName(R.string.objectives_shortname) .description(R.string.description_objectives), @@ -116,7 +117,7 @@ class ObjectivesPlugin @Inject constructor( sp.putBoolean(R.string.key_objectiveusescale, false) } - fun completeObjectives(activity: Activity, request: String) { + fun completeObjectives(activity: FragmentActivity, request: String) { val requestCode = sp.getString(R.string.key_objectives_request_code, "") var url = sp.getString(R.string.key_nsclientinternal_url, "").toLowerCase(Locale.getDefault()) if (!url.endsWith("/")) url = "$url/" @@ -145,7 +146,7 @@ class ObjectivesPlugin @Inject constructor( } } - fun allPriorAccomplished(position: Int) : Boolean { + fun allPriorAccomplished(position: Int): Boolean { var accomplished = true for (i in 0 until position) { accomplished = accomplished && objectives[i].isAccomplished @@ -162,6 +163,12 @@ class ObjectivesPlugin @Inject constructor( return value } + fun isLgsAllowed(value: Constraint): Constraint { + if (!objectives[MAXBASAL_OBJECTIVE].isStarted) + value.set(aapsLogger, false, String.format(resourceHelper.gs(R.string.objectivenotstarted), MAXBASAL_OBJECTIVE + 1), this) + return value + } + override fun isClosedLoopAllowed(value: Constraint): Constraint { if (!objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted) value.set(aapsLogger, false, String.format(resourceHelper.gs(R.string.objectivenotstarted), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java index c15e1f8599..feef4a4222 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java @@ -8,6 +8,7 @@ import android.widget.CheckBox; import android.widget.TextView; import androidx.annotation.StringRes; +import androidx.fragment.app.FragmentActivity; import java.util.ArrayList; import java.util.List; @@ -25,9 +26,9 @@ public abstract class Objective { @Inject public SP sp; @Inject public ResourceHelper resourceHelper; - private String spName; - @StringRes private int objective; - @StringRes private int gate; + private final String spName; + @StringRes private final int objective; + @StringRes private final int gate; private long startedOn; private long accomplishedOn; List tasks = new ArrayList<>(); @@ -110,12 +111,12 @@ public abstract class Objective { return true; } - public void specialAction(Activity activity, String input) { + public void specialAction(FragmentActivity activity, String input) { } public abstract class Task { @StringRes - private int task; + private final int task; private Objective objective; ArrayList hints = new ArrayList<>(); @@ -137,8 +138,6 @@ public abstract class Objective { return isCompleted(); } - ; - public String getProgress() { return resourceHelper.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet); } @@ -159,7 +158,7 @@ public abstract class Objective { public class MinimumDurationTask extends Task { - private long minimumDuration; + private final long minimumDuration; MinimumDurationTask(long minimumDuration) { super(R.string.time_elapsed); @@ -196,7 +195,7 @@ public abstract class Objective { @StringRes int question; ArrayList